This revision was automatically updated to reflect the committed changes. Closed by commit rG869385b11c32: [flang][driver] Add support for `-O{0|1|2|3}` (authored by awarzynski).
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">, @@ -5473,10 +5473,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 " @@ -6280,6 +6276,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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits