awarzynski updated this revision to Diff 439285.
awarzynski added a comment.
Add tests
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D128043/new/
https://reviews.llvm.org/D128043
Files:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
flang/include/flang/Frontend/CodeGenOptions.def
flang/include/flang/Frontend/CodeGenOptions.h
flang/include/flang/Frontend/CompilerInvocation.h
flang/include/flang/Frontend/FrontendActions.h
flang/lib/Frontend/CMakeLists.txt
flang/lib/Frontend/CodeGenOptions.cpp
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/FrontendActions.cpp
flang/test/Driver/default-optimization-pipelines.f90
flang/test/Driver/driver-help.f90
flang/test/Driver/flang_f_opts.f90
Index: flang/test/Driver/flang_f_opts.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/flang_f_opts.f90
@@ -0,0 +1,14 @@
+! Test for warnings generated when parsing driver options. You can use this file for relatively small tests and to avoid creating
+! new test files.
+
+!-----------
+! RUN LINES
+!-----------
+! RUN: %flang -### -S -O4 %s 2>&1 | FileCheck %s
+
+!-----------------------
+! EXPECTED OUTPUT
+!-----------------------
+! CHECK: warning: -O4 is equivalent to -O3
+! CHECK-LABEL: "-fc1"
+! CHECK: -O3
Index: flang/test/Driver/driver-help.f90
===================================================================
--- flang/test/Driver/driver-help.f90
+++ flang/test/Driver/driver-help.f90
@@ -96,6 +96,7 @@
! HELP-FC1-NEXT: -fdebug-measure-parse-tree
! HELP-FC1-NEXT: Measure the parse tree
! HELP-FC1-NEXT: -fdebug-module-writer Enable debug messages while writing module files
+! HELP-FC1-NEXT: -fdebug-pass-manager Prints debug information for the new pass manage
! HELP-FC1-NEXT: -fdebug-pre-fir-tree Dump the pre-FIR tree
! HELP-FC1-NEXT: -fdebug-unparse-no-sema Unparse and stop (skips the semantic checks)
! HELP-FC1-NEXT: -fdebug-unparse-with-symbols
@@ -120,6 +121,7 @@
! HELP-FC1-NEXT: -fno-analyzed-objects-for-unparse
! HELP-FC1-NEXT: Do not use the analyzed objects when unparsing
! HELP-FC1-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
+! HELP-FC1-NEXT: -fno-debug-pass-manager Disables debug printing for the new pass manager
! HELP-FC1-NEXT: -fno-reformat Dump the cooked character stream in -E mode
! HELP-FC1-NEXT: -fopenacc Enable OpenACC
! HELP-FC1-NEXT: -fopenmp Parse OpenMP pragmas and generate parallel code.
Index: flang/test/Driver/default-optimization-pipelines.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/default-optimization-pipelines.f90
@@ -0,0 +1,27 @@
+! Verify that`-O{n}` is indeed taken into account when defining the LLVM optimization/middle-end pass pipeline.
+
+!-----------
+! RUN LINES
+!-----------
+! RUN: %flang -S -O0 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0
+! RUN: %flang_fc1 -S -O0 %s -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0
+
+! RUN: %flang -S -O2 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2
+! RUN: %flang_fc1 -S -O2 %s -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2
+
+!-----------------------
+! EXPECTED OUTPUT
+!-----------------------
+! CHECK-O0-NOT: Running pass: SimplifyCFGPass on simple_loop_
+! CHECK-O0: Running analysis: TargetLibraryAnalysis on simple_loop_
+
+! CHECK-O2: Running pass: SimplifyCFGPass on simple_loop_
+
+!-------
+! INPUT
+!-------
+subroutine simple_loop
+ integer :: i
+ do i=1,5
+ end do
+end subroutine
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ flang/lib/Frontend/FrontendActions.cpp
@@ -46,6 +46,7 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetMachine.h"
@@ -538,7 +539,6 @@
/*Features=*/"",
llvm::TargetOptions(), llvm::None));
assert(tm && "Failed to create TargetMachine");
- llvmModule->setDataLayout(tm->createDataLayout());
}
static std::unique_ptr<llvm::raw_pwrite_stream>
@@ -610,23 +610,59 @@
codeGenPasses.run(llvmModule);
}
-/// Generate LLVM byte code file from the input LLVM module.
-///
-/// \param [in] tm Target machine to aid the code-gen pipeline set-up
-/// \param [in] llvmModule LLVM module to lower to assembly/machine-code
-/// \param [out] os Output stream to emit the generated code to
-static void generateLLVMBCImpl(llvm::TargetMachine &tm,
- llvm::Module &llvmModule,
- llvm::raw_pwrite_stream &os) {
- // Set-up the pass manager
- llvm::ModulePassManager mpm;
+static llvm::OptimizationLevel
+mapToLevel(const Fortran::frontend::CodeGenOptions &opts) {
+ switch (opts.OptimizationLevel) {
+ default:
+ llvm_unreachable("Invalid optimization level!");
+ case 0:
+ return llvm::OptimizationLevel::O0;
+ case 1:
+ return llvm::OptimizationLevel::O1;
+ case 2:
+ return llvm::OptimizationLevel::O2;
+ case 3:
+ return llvm::OptimizationLevel::O3;
+ }
+}
+
+void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
+ auto opts = getInstance().getInvocation().getCodeGenOpts();
+ llvm::OptimizationLevel level = mapToLevel(opts);
+
+ // Create the analysis managers.
+ llvm::LoopAnalysisManager lam;
+ llvm::FunctionAnalysisManager fam;
+ llvm::CGSCCAnalysisManager cgam;
llvm::ModuleAnalysisManager mam;
- llvm::PassBuilder pb(&tm);
+
+ // Create the pass manager builder.
+ llvm::PassInstrumentationCallbacks pic;
+ llvm::PipelineTuningOptions pto;
+ llvm::Optional<llvm::PGOOptions> pgoOpt;
+ llvm::StandardInstrumentations si(opts.DebugPassManager);
+ si.registerCallbacks(pic, &fam);
+ llvm::PassBuilder pb(tm.get(), pto, pgoOpt, &pic);
+
+ // Register all the basic analyses with the managers.
pb.registerModuleAnalyses(mam);
- mpm.addPass(llvm::BitcodeWriterPass(os));
+ pb.registerCGSCCAnalyses(cgam);
+ pb.registerFunctionAnalyses(fam);
+ pb.registerLoopAnalyses(lam);
+ pb.crossRegisterProxies(lam, fam, cgam, mam);
+
+ // Create the pass manager.
+ llvm::ModulePassManager mpm;
+ if (opts.OptimizationLevel == 0)
+ mpm = pb.buildO0DefaultPipeline(level, false);
+ else
+ mpm = pb.buildPerModuleDefaultPipeline(level);
- // run the passes
- mpm.run(llvmModule, mam);
+ if (action == BackendActionTy::Backend_EmitBC)
+ mpm.addPass(llvm::BitcodeWriterPass(os));
+
+ // Run the passes.
+ mpm.run(*llvmModule, mam);
}
void CodeGenAction::executeAction() {
@@ -661,11 +697,14 @@
return;
}
- // generate an LLVM module if it's not already present (it will already be
+ // Generate an LLVM module if it's not already present (it will already be
// present if the input file is an LLVM IR/BC file).
if (!llvmModule)
generateLLVMIR();
+ // Run LLVM's middle-end (i.e. the optimizer).
+ runOptimizationPipeline(*os);
+
if (action == BackendActionTy::Backend_EmitLL) {
llvmModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream(),
/*AssemblyAnnotationWriter=*/nullptr);
@@ -673,11 +712,14 @@
}
setUpTargetMachine();
+ llvmModule->setDataLayout(tm->createDataLayout());
+
if (action == BackendActionTy::Backend_EmitBC) {
- generateLLVMBCImpl(*tm, *llvmModule, *os);
+ // This action has effectively been completed in runOptimizationPipeline.
return;
}
+ // Run LLVM's backend and generate either assembly or machine code
if (action == BackendActionTy::Backend_EmitAssembly ||
action == BackendActionTy::Backend_EmitObj) {
generateMachineCodeOrAssemblyImpl(
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -12,6 +12,7 @@
#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Common/Fortran-features.h"
+#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
#include "flang/Semantics/semantics.h"
@@ -20,6 +21,7 @@
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/OptionUtils.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -95,6 +97,18 @@
return true;
}
+static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
+ llvm::opt::ArgList &args,
+ clang::DiagnosticsEngine &diags) {
+ unsigned defaultOpt = llvm::CodeGenOpt::None;
+ opts.OptimizationLevel = clang::getLastArgIntValue(
+ args, clang::driver::options::OPT_O, defaultOpt, diags);
+
+ if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager,
+ clang::driver::options::OPT_fno_debug_pass_manager, false))
+ opts.DebugPassManager = 1;
+}
+
/// Parses all target input arguments and populates the target
/// options accordingly.
///
@@ -616,6 +630,7 @@
success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
parseTargetArgs(res.getTargetOpts(), args);
parsePreprocessorArgs(res.getPreprocessorOpts(), args);
+ parseCodeGenArgs(res.getCodeGenOpts(), args, diags);
success &= parseSemaArgs(res, args, diags);
success &= parseDialectArgs(res, args, diags);
success &= parseDiagArgs(res, args, diags);
Index: flang/lib/Frontend/CodeGenOptions.cpp
===================================================================
--- /dev/null
+++ flang/lib/Frontend/CodeGenOptions.cpp
@@ -0,0 +1,23 @@
+//===--- CodeGenOptions.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Frontend/CodeGenOptions.h"
+#include <string.h>
+
+namespace Fortran::frontend {
+
+CodeGenOptions::CodeGenOptions() {
+#define CODEGENOPT(Name, Bits, Default) Name = Default;
+#include "flang/Frontend/CodeGenOptions.def"
+}
+
+} // end namespace Fortran::frontend
Index: flang/lib/Frontend/CMakeLists.txt
===================================================================
--- flang/lib/Frontend/CMakeLists.txt
+++ flang/lib/Frontend/CMakeLists.txt
@@ -3,6 +3,7 @@
add_flang_library(flangFrontend
CompilerInstance.cpp
CompilerInvocation.cpp
+ CodeGenOptions.cpp
FrontendAction.cpp
FrontendActions.cpp
FrontendOptions.cpp
Index: flang/include/flang/Frontend/FrontendActions.h
===================================================================
--- flang/include/flang/Frontend/FrontendActions.h
+++ flang/include/flang/Frontend/FrontendActions.h
@@ -13,6 +13,7 @@
#ifndef FORTRAN_FRONTEND_FRONTENDACTIONS_H
#define FORTRAN_FRONTEND_FRONTENDACTIONS_H
+#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/FrontendAction.h"
#include "flang/Parser/parsing.h"
#include "flang/Semantics/semantics.h"
@@ -198,7 +199,11 @@
void executeAction() override;
/// Runs prescan, parsing, sema and lowers to MLIR.
bool beginSourceFileAction() override;
+ /// Sets up LLVM's TargetMachine, configures llvmModule accordingly.
void setUpTargetMachine();
+ /// Runs the optimization (aka middle-end) pipeline on the LLVM module
+ /// associated with this action.
+ void runOptimizationPipeline(llvm::raw_pwrite_stream &os);
protected:
CodeGenAction(BackendActionTy act) : action{act} {};
Index: flang/include/flang/Frontend/CompilerInvocation.h
===================================================================
--- flang/include/flang/Frontend/CompilerInvocation.h
+++ flang/include/flang/Frontend/CompilerInvocation.h
@@ -13,6 +13,7 @@
#ifndef FORTRAN_FRONTEND_COMPILERINVOCATION_H
#define FORTRAN_FRONTEND_COMPILERINVOCATION_H
+#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/FrontendOptions.h"
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
@@ -70,6 +71,9 @@
/// Options controlling the target.
Fortran::frontend::TargetOptions targetOpts;
+ /// Options controlling IRgen and the backend.
+ Fortran::frontend::CodeGenOptions codeGenOpts;
+
// Semantics context
std::unique_ptr<Fortran::semantics::SemanticsContext> semanticsContext;
@@ -129,6 +133,9 @@
TargetOptions &getTargetOpts() { return targetOpts; }
const TargetOptions &getTargetOpts() const { return targetOpts; }
+ CodeGenOptions &getCodeGenOpts() { return codeGenOpts; }
+ const CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
+
Fortran::semantics::SemanticsContext &getSemanticsContext() {
return *semanticsContext;
}
Index: flang/include/flang/Frontend/CodeGenOptions.h
===================================================================
--- /dev/null
+++ flang/include/flang/Frontend/CodeGenOptions.h
@@ -0,0 +1,52 @@
+//===--- CodeGenOptions.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeGenOptions interface, which holds the
+// configuration for LLVM's middle-end and back-end. It controls LLVM's code
+// generation into assembly or machine code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H
+
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace Fortran::frontend {
+
+/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
+/// that this large collection of bitfields is a trivial class type.
+class CodeGenOptionsBase {
+
+public:
+#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits;
+#include "flang/Frontend/CodeGenOptions.def"
+
+protected:
+#define CODEGENOPT(Name, Bits, Default)
+#include "flang/Frontend/CodeGenOptions.def"
+};
+
+/// Tracks various options which control how the code is optimized and passed
+/// to the LLVM backend.
+class CodeGenOptions : public CodeGenOptionsBase {
+
+public:
+ CodeGenOptions();
+};
+
+} // end namespace Fortran::frontend
+
+#endif
Index: flang/include/flang/Frontend/CodeGenOptions.def
===================================================================
--- /dev/null
+++ flang/include/flang/Frontend/CodeGenOptions.def
@@ -0,0 +1,22 @@
+//===--- CodeGenOptions.def - Code generation option database ----- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the code generation options. Users of this file
+// must define the CODEGENOPT macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CODEGENOPT
+# error Define the CODEGENOPT macro to handle language options
+#endif
+
+CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
+
+CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
+ ///< pass manager.
+
+#undef CODEGENOPT
Index: clang/lib/Driver/ToolChains/Flang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Flang.cpp
+++ clang/lib/Driver/ToolChains/Flang.cpp
@@ -135,6 +135,16 @@
A->render(Args, CmdArgs);
}
+ // Optimization level for CodeGen.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -721,14 +721,14 @@
MarshallingInfoFlag<DependencyOutputOpts<"OutputFormat">, "DependencyOutputFormat::Make">,
Normalizer<"makeFlagToValueNormalizer(DependencyOutputFormat::NMake)">;
def Mach : Flag<["-"], "Mach">, Group<Link_Group>;
-def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
-def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
+def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, FC1Option, HelpHidden]>;
+def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, FC1Option, HelpHidden]>;
def ObjCXX : Flag<["-"], "ObjC++">, Flags<[NoXarchOption]>,
HelpText<"Treat source input files as Objective-C++ inputs">;
def ObjC : Flag<["-"], "ObjC">, Flags<[NoXarchOption]>,
HelpText<"Treat source input files as Objective-C inputs">;
-def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option]>;
-def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["1"]>;
+def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option,FC1Option]>;
+def O_flag : Flag<["-"], "O">, Flags<[CC1Option,FC1Option]>, Alias<O>, AliasArgs<["1"]>;
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
def P : Flag<["-"], "P">, Flags<[CC1Option,FlangOption,FC1Option]>, Group<Preprocessor_Group>,
HelpText<"Disable linemarker output in -E mode">,
@@ -5461,10 +5461,6 @@
CodeGenOpts<"LTOUnit">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Emit IR to support LTO unit features (CFI, whole program vtable opt)">,
NegFlag<SetFalse>>;
-defm debug_pass_manager : BoolOption<"f", "debug-pass-manager",
- CodeGenOpts<"DebugPassManager">, DefaultFalse,
- PosFlag<SetTrue, [], "Prints debug information for the new pass manager">,
- NegFlag<SetFalse, [], "Disables debug printing for the new pass manager">>;
def fverify_debuginfo_preserve
: Flag<["-"], "fverify-debuginfo-preserve">,
HelpText<"Enable Debug Info Metadata preservation testing in "
@@ -6268,6 +6264,10 @@
HelpText<"Load the named plugin (dynamic shared object)">;
def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">,
HelpText<"Use the named plugin action instead of the default action (use \"help\" to list available options)">;
+defm debug_pass_manager : BoolOption<"f", "debug-pass-manager",
+ CodeGenOpts<"DebugPassManager">, DefaultFalse,
+ PosFlag<SetTrue, [], "Prints debug information for the new pass manager">,
+ NegFlag<SetFalse, [], "Disables debug printing for the new pass manager">>;
} // let Flags = [CC1Option, FC1Option, NoDriverOption]
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits