[clang] f04ccad - [Flang] Add support for fsave-optimization-record

Kiran Chandramohan via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 28 02:31:09 PDT 2023


Author: Victor Kingi
Date: 2023-07-28T09:26:40Z
New Revision: f04ccadf35441b2e13b3ab30edeef251818fa9c7

URL: https://github.com/llvm/llvm-project/commit/f04ccadf35441b2e13b3ab30edeef251818fa9c7
DIFF: https://github.com/llvm/llvm-project/commit/f04ccadf35441b2e13b3ab30edeef251818fa9c7.diff

LOG: [Flang] Add support for fsave-optimization-record

Add support for generating and saving the optimization record.
Optimization record lists the optimizations performed by LLVM.

This patch enables the flag in Flang. Clang handles this functionality
using the BackendConsumer which Flang doesn't have, hence, was
implemented in CodeGenAction::executeAction

FlangOption added to all variants of fsave-optimization-record in
clang/include/clang/Driver/Options.td . Clang handles it the
same way.

opt_record_file, opt_record_passes and opt_record_format flags
in Options.td were moved out of the group [CC1Option, NoDriverOption]
to allow flang -fc1 support.

The renderRemarksOptions and willEmitRemarks functions in
clang/lib/Driver/ToolChains/Flang.cpp follow same syntax as clang.
In flang/lib/Frontend/CompilerInvocation.cpp we update the field
OptRecordFile with the provided optimization file value. Clang
doesn't do this as it processes the Options.td, mapping the
OptRecordFile earlier on.

Reviewed By: awarzynski, tblah

Differential Revision: https://reviews.llvm.org/D155452

Added: 
    flang/test/Driver/fsave-optimization-record.f90

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 8be3fbf61ce106..9b44e11535c2a9 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3084,18 +3084,18 @@ def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, Group<f_
   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>">;
@@ -6390,14 +6390,6 @@ def arcmt_action_EQ : Joined<["-"], "arcmt-action=">, Flags<[CC1Option, NoDriver
   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">>;
@@ -6838,6 +6830,14 @@ defm debug_pass_manager : BoolOption<"f", "debug-pass-manager",
   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]
 
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index bdc75f51b7a288..a842bc25f29de1 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/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 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
     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 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   // 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);
 

diff  --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index 60aa38a4c1d75a..c56886890f2857 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -58,6 +58,17 @@ class CodeGenOptions : public CodeGenOptionsBase {
   /// 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)                             \

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index b1f0d27a925ed2..90b93b2923e257 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -163,13 +163,12 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
     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 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
       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();
 

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 0154fd29bf810e..6cf60dcfccc5a0 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/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 @@ void CodeGenAction::embedOffloadObjects() {
   }
 }
 
+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 @@ void CodeGenAction::executeAction() {
     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 @@ void CodeGenAction::executeAction() {
   }
 
   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 @@ void CodeGenAction::executeAction() {
   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 @@ void CodeGenAction::executeAction() {
   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 @@ void CodeGenAction::executeAction() {
   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;
   }

diff  --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index f8f1df7c8d4527..a61045dde60598 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/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

diff  --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index a80e6f55d6c1f8..a8e3bfd66d46b6 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/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

diff  --git a/flang/test/Driver/fsave-optimization-record.f90 b/flang/test/Driver/fsave-optimization-record.f90
new file mode 100644
index 00000000000000..c039a1495dacc4
--- /dev/null
+++ b/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


        


More information about the cfe-commits mailing list