victorkingi updated this revision to Diff 543571.
victorkingi marked 3 inline comments as done.
victorkingi added a comment.
minor cleanup
- dropped braces on single line if statements
- moved opt_record options into [CC1Option, FC1Option, NoDriverOption] Group in
clang/include/clang/Driver/Options.td
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/frontend-forwarding.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,42 @@
+! Tests for the '-f[no-]save-optimization-record[=<format>]' flag.
+
+! 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
+
+! 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/frontend-forwarding.f90
===================================================================
--- flang/test/Driver/frontend-forwarding.f90
+++ flang/test/Driver/frontend-forwarding.f90
@@ -15,6 +15,7 @@
! RUN: -fassociative-math \
! RUN: -freciprocal-math \
! RUN: -fpass-plugin=Bye%pluginext \
+! RUN: -fsave-optimization-record \
! RUN: -fversion-loops-for-stride \
! RUN: -flang-experimental-polymorphism \
! RUN: -mllvm -print-before-all \
@@ -22,6 +23,10 @@
! RUN: -P \
! RUN: | FileCheck %s
+! RUN: %flang -### %s 2>&1 \
+! RUN: -foptimization-record-file=%t.opt.yaml \
+! RUN: | FileCheck --check-prefix=YAML %s
+
! CHECK: "-P"
! CHECK: "-finput-charset=utf-8"
! CHECK: "-fdefault-double-8"
@@ -38,5 +43,10 @@
! CHECK: "-fpass-plugin=Bye
! CHECK: "-flang-experimental-polymorphism"
! CHECK: "-fversion-loops-for-stride"
+! CHECK: "-opt-record-file" "{{.+}}.opt.yaml"
+! CHECK: "-opt-record-format" "yaml"
! CHECK: "-mllvm" "-print-before-all"
! CHECK: "-save-temps=obj"
+
+! YAML: "-opt-record-file" "{{.+}}.opt.yaml"
+! YAML: "-opt-record-format" "yaml"
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits