victorkingi updated this revision to Diff 543945.
victorkingi added a comment.

moved opt_record flags generation test from frontend-forwarding.f90
to fsave-optimization-record.f90


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D155452/new/

https://reviews.llvm.org/D155452

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Flang.cpp
  flang/include/flang/Frontend/CodeGenOptions.h
  flang/lib/Frontend/CompilerInvocation.cpp
  flang/lib/Frontend/FrontendActions.cpp
  flang/test/Driver/driver-help-hidden.f90
  flang/test/Driver/driver-help.f90
  flang/test/Driver/fsave-optimization-record.f90

Index: flang/test/Driver/fsave-optimization-record.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/fsave-optimization-record.f90
@@ -0,0 +1,59 @@
+! Tests for the '-f[no-]save-optimization-record[=<format>]' flag.
+
+! Test opt_record flags get generated for fc1
+! RUN: %flang -### %s 2>&1 \
+! RUN:     -foptimization-record-file=%t.opt.yaml \
+! RUN:   | FileCheck --check-prefix=YAML %s
+
+! RUN: %flang -### %s 2>&1 \
+! RUN:     -fsave-optimization-record \
+! RUN:   | FileCheck --check-prefix=YAML %s
+
+
+! Test -foptimization-record-file produces YAML file with given content
+! RUN: rm -f %t.opt.yaml
+! RUN: %flang -foptimization-record-file=%t.opt.yaml -c %s
+! RUN: cat %t.opt.yaml | FileCheck %s
+
+
+! Test -fsave-optimization-record produces YAML file with given content
+! RUN: rm -f %t.opt.yaml
+! RUN: %flang -fsave-optimization-record -c -o %t.o %s
+! RUN: cat %t.opt.yaml | FileCheck %s
+
+! RUN: rm -f %t.opt.yaml
+! RUN: %flang -fsave-optimization-record -S -o %t.s %s
+! RUN: cat %t.opt.yaml | FileCheck %s
+
+
+! Produces an empty file
+! RUN: rm -f %t.opt.yaml
+! RUN: %flang -fsave-optimization-record -S -emit-llvm -o %t.ll %s
+! RUN: cat %t.opt.yaml
+
+
+!Test unknown format produces error
+! RUN: not %flang -fsave-optimization-record=hello %s 2>&1 \
+! RUN:   | FileCheck --check-prefix=CHECK-FORMAT-ERROR %s
+
+
+! YAML: "-opt-record-file" "{{.+}}.opt.yaml"
+! YAML: "-opt-record-format" "yaml"
+
+! CHECK: --- !Analysis
+! CHECK: Pass:            prologepilog
+! CHECK: Name:            StackSize
+! CHECK: Function:        _QQmain
+! CHECK: Pass:            asm-printer
+! CHECK: Name:            InstructionMix
+! CHECK: Name:            InstructionCount
+
+! CHECK-FORMAT-ERROR: error: unknown remark serializer format: 'hello'
+
+program forttest
+    implicit none
+    integer :: n
+
+    n = 1 * 1
+
+end program forttest
Index: flang/test/Driver/driver-help.f90
===================================================================
--- flang/test/Driver/driver-help.f90
+++ flang/test/Driver/driver-help.f90
@@ -54,8 +54,16 @@
 ! HELP-NEXT: -fopenmp-version=<value>
 ! HELP-NEXT:                        Set OpenMP version (e.g. 45 for OpenMP 4.5, 50 for OpenMP 5.0). Default value is 50 for Clang and 11 for Flang
 ! HELP-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
+! HELP-NEXT: -foptimization-record-file=<file>
+! HELP-NEXT:                        Specify the output name of the file containing the optimization remarks. Implies -fsave-optimization-record. On Darwin platforms, this cannot be used with multiple -arch <arch> options.
+! HELP-NEXT: -foptimization-record-passes=<regex>
+! HELP-NEXT:                        Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)
 ! HELP-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! HELP-NEXT: -freciprocal-math      Allow division operations to be reassociated
+! HELP-NEXT: -fsave-optimization-record=<format>
+! HELP-NEXT:                        Generate an optimization record file in a specific format
+! HELP-NEXT: -fsave-optimization-record
+! HELP-NEXT:                        Generate a YAML optimization record file
 ! HELP-NEXT: -fstack-arrays         Attempt to allocate array temporaries on the stack, no matter their size
 ! HELP-NEXT: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! HELP-NEXT: -funderscoring         Appends one trailing underscore to external names
@@ -186,6 +194,12 @@
 ! HELP-FC1-NEXT: -mrelocation-model <value>
 ! HELP-FC1-NEXT:                        The relocation model to use
 ! HELP-FC1-NEXT: -nocpp                 Disable predefined and command line preprocessor macros
+! HELP-FC1-NEXT: -opt-record-file <value>
+! HELP-FC1-NEXT:                        File name to use for YAML optimization record output
+! HELP-FC1-NEXT: -opt-record-format <value>
+! HELP-FC1-NEXT:                        The format used for serializing remarks (default: YAML)
+! HELP-FC1-NEXT: -opt-record-passes <value>
+! HELP-FC1-NEXT:                        Only record remark information for passes whose names match the given regular expression
 ! HELP-FC1-NEXT: -o <file>              Write output to <file>
 ! HELP-FC1-NEXT: -pedantic              Warn on language extensions
 ! HELP-FC1-NEXT: -pic-is-pie             File is for a position independent executable
Index: flang/test/Driver/driver-help-hidden.f90
===================================================================
--- flang/test/Driver/driver-help-hidden.f90
+++ flang/test/Driver/driver-help-hidden.f90
@@ -58,8 +58,16 @@
 ! CHECK-NEXT: -fopenmp-version=<value>
 ! CHECK-NEXT:                        Set OpenMP version (e.g. 45 for OpenMP 4.5, 50 for OpenMP 5.0). Default value is 50 for Clang and 11 for Flang
 ! CHECK-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
+! CHECK-NEXT: -foptimization-record-file=<file>
+! CHECK-NEXT:                        Specify the output name of the file containing the optimization remarks. Implies -fsave-optimization-record. On Darwin platforms, this cannot be used with multiple -arch <arch> options.
+! CHECK-NEXT: -foptimization-record-passes=<regex>
+! CHECK-NEXT:                        Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)
 ! CHECK-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! CHECK-NEXT: -freciprocal-math      Allow division operations to be reassociated
+! CHECK-NEXT: -fsave-optimization-record=<format>
+! CHECK-NEXT:                        Generate an optimization record file in a specific format
+! CHECK-NEXT: -fsave-optimization-record
+! CHECK-NEXT:                        Generate a YAML optimization record file
 ! CHECK-NEXT: -fstack-arrays         Attempt to allocate array temporaries on the stack, no matter their size
 ! CHECK-NEXT: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! CHECK-NEXT: -funderscoring         Appends one trailing underscore to external names
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ flang/lib/Frontend/FrontendActions.cpp
@@ -42,11 +42,13 @@
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Driver/DriverDiagnostic.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IRReader/IRReader.h"
@@ -55,6 +57,7 @@
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Passes/PassPlugin.h"
 #include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
@@ -939,9 +942,32 @@
   }
 }
 
+static void reportOptRecordError(llvm::Error e, clang::DiagnosticsEngine &diags,
+                                 const CodeGenOptions &codeGenOpts) {
+  handleAllErrors(
+      std::move(e),
+      [&](const llvm::LLVMRemarkSetupFileError &e) {
+        diags.Report(clang::diag::err_cannot_open_file)
+            << codeGenOpts.OptRecordFile << e.message();
+      },
+      [&](const llvm::LLVMRemarkSetupPatternError &e) {
+        diags.Report(clang::diag::err_drv_optimization_remark_pattern)
+            << e.message() << codeGenOpts.OptRecordPasses;
+      },
+      [&](const llvm::LLVMRemarkSetupFormatError &e) {
+        diags.Report(clang::diag::err_drv_optimization_remark_format)
+            << codeGenOpts.OptRecordFormat;
+      });
+}
+
 void CodeGenAction::executeAction() {
   CompilerInstance &ci = this->getInstance();
 
+  clang::DiagnosticsEngine &diags = ci.getDiagnostics();
+  const CodeGenOptions &codeGenOpts = ci.getInvocation().getCodeGenOpts();
+  Fortran::lower::LoweringOptions &loweringOpts =
+      ci.getInvocation().getLoweringOpts();
+
   // If the output stream is a file, generate it and define the corresponding
   // output stream. If a pre-defined output stream is available, we will use
   // that instead.
@@ -959,15 +985,15 @@
     os = getOutputStream(ci, getCurrentFileOrBufferName(), action);
 
     if (!os) {
-      unsigned diagID = ci.getDiagnostics().getCustomDiagID(
+      unsigned diagID = diags.getCustomDiagID(
           clang::DiagnosticsEngine::Error, "failed to create the output file");
-      ci.getDiagnostics().Report(diagID);
+      diags.Report(diagID);
       return;
     }
   }
 
   if (action == BackendActionTy::Backend_EmitFIR) {
-    if (ci.getInvocation().getLoweringOpts().getLowerToHighLevelFIR()) {
+    if (loweringOpts.getLowerToHighLevelFIR()) {
       lowerHLFIRToFIR();
     }
     mlirModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream());
@@ -975,7 +1001,7 @@
   }
 
   if (action == BackendActionTy::Backend_EmitHLFIR) {
-    assert(ci.getInvocation().getLoweringOpts().getLowerToHighLevelFIR() &&
+    assert(loweringOpts.getLowerToHighLevelFIR() &&
            "Lowering must have been configured to emit HLFIR");
     mlirModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream());
     return;
@@ -994,8 +1020,7 @@
   const std::string &theTriple = tm->getTargetTriple().str();
 
   if (llvmModule->getTargetTriple() != theTriple) {
-    ci.getDiagnostics().Report(clang::diag::warn_fe_override_module)
-        << theTriple;
+    diags.Report(clang::diag::warn_fe_override_module) << theTriple;
   }
 
   // Always set the triple and data layout, to make sure they match and are set.
@@ -1005,9 +1030,30 @@
   llvmModule->setDataLayout(tm->createDataLayout());
 
   // Embed offload objects specified with -fembed-offload-object
-  if (!ci.getInvocation().getCodeGenOpts().OffloadObjects.empty())
+  if (!codeGenOpts.OffloadObjects.empty())
     embedOffloadObjects();
 
+  // write optimization-record
+  llvm::Expected<std::unique_ptr<llvm::ToolOutputFile>> optRecordFileOrErr =
+      setupLLVMOptimizationRemarks(
+          llvmModule->getContext(), codeGenOpts.OptRecordFile,
+          codeGenOpts.OptRecordPasses, codeGenOpts.OptRecordFormat,
+          /*DiagnosticsWithHotness=*/false,
+          /*DiagnosticsHotnessThreshold=*/0);
+
+  if (llvm::Error e = optRecordFileOrErr.takeError()) {
+    reportOptRecordError(std::move(e), diags, codeGenOpts);
+    return;
+  }
+
+  std::unique_ptr<llvm::ToolOutputFile> optRecordFile =
+      std::move(*optRecordFileOrErr);
+
+  if (optRecordFile) {
+    optRecordFile->keep();
+    optRecordFile->os().flush();
+  }
+
   // Run LLVM's middle-end (i.e. the optimizer).
   runOptimizationPipeline(ci.isOutputStreamNull() ? *os : ci.getOutputStream());
 
@@ -1026,7 +1072,7 @@
   if (action == BackendActionTy::Backend_EmitAssembly ||
       action == BackendActionTy::Backend_EmitObj) {
     generateMachineCodeOrAssemblyImpl(
-        ci.getDiagnostics(), *tm, action, *llvmModule,
+        diags, *tm, action, *llvmModule,
         ci.isOutputStreamNull() ? *os : ci.getOutputStream());
     return;
   }
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -163,13 +163,12 @@
     opts.DebugPassManager = 1;
 
   if (args.hasFlag(clang::driver::options::OPT_fstack_arrays,
-                   clang::driver::options::OPT_fno_stack_arrays, false)) {
+                   clang::driver::options::OPT_fno_stack_arrays, false))
     opts.StackArrays = 1;
-  }
+
   if (args.hasFlag(clang::driver::options::OPT_floop_versioning,
-                   clang::driver::options::OPT_fno_loop_versioning, false)) {
+                   clang::driver::options::OPT_fno_loop_versioning, false))
     opts.LoopVersioning = 1;
-  }
 
   for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
     opts.LLVMPassPlugins.push_back(a->getValue());
@@ -190,6 +189,19 @@
       opts.PrepareForThinLTO = true;
   }
 
+  // -f[no-]save-optimization-record[=<format>]
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_opt_record_file))
+    opts.OptRecordFile = a->getValue();
+
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_opt_record_format))
+    opts.OptRecordFormat = a->getValue();
+
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_opt_record_passes))
+    opts.OptRecordPasses = a->getValue();
+
   if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
     opts.SaveTempsDir = a->getValue();
 
Index: flang/include/flang/Frontend/CodeGenOptions.h
===================================================================
--- flang/include/flang/Frontend/CodeGenOptions.h
+++ flang/include/flang/Frontend/CodeGenOptions.h
@@ -58,6 +58,17 @@
   /// The directory where temp files are stored if specified by -save-temps
   std::optional<std::string> SaveTempsDir;
 
+  /// The name of the file to which the backend should save YAML optimization
+  /// records.
+  std::string OptRecordFile;
+
+  /// The regex that filters the passes that should be saved to the optimization
+  /// records.
+  std::string OptRecordPasses;
+
+  /// The format used for serializing remarks (default: YAML)
+  std::string OptRecordFormat;
+
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
 #define ENUM_CODEGENOPT(Name, Type, Bits, Default)                             \
Index: clang/lib/Driver/ToolChains/Flang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Flang.cpp
+++ clang/lib/Driver/ToolChains/Flang.cpp
@@ -12,6 +12,8 @@
 
 #include "clang/Driver/Options.h"
 #include "llvm/Frontend/Debug/Options.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 
 #include <cassert>
 
@@ -387,6 +389,50 @@
     CmdArgs.push_back("-freciprocal-math");
 }
 
+static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
+                                 const InputInfo &Input) {
+  StringRef Format = "yaml";
+  if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
+    Format = A->getValue();
+
+  CmdArgs.push_back("-opt-record-file");
+
+  const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+  if (A) {
+    CmdArgs.push_back(A->getValue());
+  } else {
+    SmallString<128> F;
+
+    if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
+      if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
+        F = FinalOutput->getValue();
+    }
+
+    if (F.empty()) {
+      // Use the input filename.
+      F = llvm::sys::path::stem(Input.getBaseInput());
+    }
+
+    SmallString<32> Extension;
+    Extension += "opt.";
+    Extension += Format;
+
+    llvm::sys::path::replace_extension(F, Extension);
+    CmdArgs.push_back(Args.MakeArgString(F));
+  }
+
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+    CmdArgs.push_back("-opt-record-passes");
+    CmdArgs.push_back(A->getValue());
+  }
+
+  if (!Format.empty()) {
+    CmdArgs.push_back("-opt-record-format");
+    CmdArgs.push_back(Format.data());
+  }
+}
+
 void Flang::ConstructJob(Compilation &C, const JobAction &JA,
                          const InputInfo &Output, const InputInfoList &Inputs,
                          const ArgList &Args, const char *LinkingOutput) const {
@@ -471,6 +517,10 @@
   // Add Codegen options
   addCodegenOptions(Args, CmdArgs);
 
+  // Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
+  if (willEmitRemarks(Args))
+    renderRemarksOptions(Args, CmdArgs, Input);
+
   // Add other compile options
   addOtherOptions(Args, CmdArgs);
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3079,18 +3079,18 @@
   HelpText<"Maximum number of 'operator->'s to call for a member access">,
   MarshallingInfoInt<LangOpts<"ArrowDepth">, "256">;
 
-def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">,
+def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">, Flags<[FlangOption]>,
   Group<f_Group>, HelpText<"Generate a YAML optimization record file">;
-def fsave_optimization_record_EQ : Joined<["-"], "fsave-optimization-record=">,
+def fsave_optimization_record_EQ : Joined<["-"], "fsave-optimization-record=">, Flags<[FlangOption]>,
   Group<f_Group>, HelpText<"Generate an optimization record file in a specific format">,
   MetaVarName<"<format>">;
 def fno_save_optimization_record : Flag<["-"], "fno-save-optimization-record">,
-  Group<f_Group>, Flags<[NoArgumentUnused]>;
-def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">,
+  Group<f_Group>, Flags<[FlangOption, NoArgumentUnused]>;
+def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">, Flags<[FlangOption]>,
   Group<f_Group>,
   HelpText<"Specify the output name of the file containing the optimization remarks. Implies -fsave-optimization-record. On Darwin platforms, this cannot be used with multiple -arch <arch> options.">,
   MetaVarName<"<file>">;
-def foptimization_record_passes_EQ : Joined<["-"], "foptimization-record-passes=">,
+def foptimization_record_passes_EQ : Joined<["-"], "foptimization-record-passes=">, Flags<[FlangOption]>,
   Group<f_Group>,
   HelpText<"Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)">,
   MetaVarName<"<regex>">;
@@ -6385,14 +6385,6 @@
   NormalizedValues<["ARCMT_Check", "ARCMT_Modify", "ARCMT_Migrate"]>,
   MarshallingInfoEnum<FrontendOpts<"ARCMTAction">, "ARCMT_None">;
 
-def opt_record_file : Separate<["-"], "opt-record-file">,
-  HelpText<"File name to use for YAML optimization record output">,
-  MarshallingInfoString<CodeGenOpts<"OptRecordFile">>;
-def opt_record_passes : Separate<["-"], "opt-record-passes">,
-  HelpText<"Only record remark information for passes whose names match the given regular expression">;
-def opt_record_format : Separate<["-"], "opt-record-format">,
-  HelpText<"The format used for serializing remarks (default: YAML)">;
-
 def print_stats : Flag<["-"], "print-stats">,
   HelpText<"Print performance metrics and statistics">,
   MarshallingInfoFlag<FrontendOpts<"ShowStats">>;
@@ -6832,6 +6824,14 @@
   PosFlag<SetTrue, [], "Prints debug information for the new pass manager">,
   NegFlag<SetFalse, [], "Disables debug printing for the new pass manager">>;
 
+def opt_record_file : Separate<["-"], "opt-record-file">,
+  HelpText<"File name to use for YAML optimization record output">,
+  MarshallingInfoString<CodeGenOpts<"OptRecordFile">>;
+def opt_record_passes : Separate<["-"], "opt-record-passes">,
+  HelpText<"Only record remark information for passes whose names match the given regular expression">;
+def opt_record_format : Separate<["-"], "opt-record-format">,
+  HelpText<"The format used for serializing remarks (default: YAML)">;
+
 } // 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