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

Reply via email to