victorkingi created this revision. Herald added a reviewer: sscalpone. Herald added a reviewer: awarzynski. Herald added a subscriber: sunshaoce. Herald added projects: Flang, All. victorkingi requested review of this revision. Herald added subscribers: cfe-commits, jdoerfert, MaskRay. Herald added a project: clang.
Add support for generating and saving the optimization record. Optimization record lists the optimizations performed by LLVM. This patch enables the flag in Flang. 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. Repository: rG LLVM Github Monorepo 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,21 @@ +! Tests for the '-f[no-]save-optimization-record[=<format>]' flag. + +! Test that the optimization file was generated with the needed name +! RUN: %flang -foptimization-record-file=%t.opt.yaml %s +! RUN: FileCheck %s < %t.opt.yaml + +! Test that no error or warning should be produced +! RUN: %flang -fsave-optimization-record=yaml %s +! RUN: %flang -fsave-optimization-record -S %s +! RUN: %flang -fsave-optimization-record -S -emit-llvm %s +! RUN: %flang -fsave-optimization-record -c %s + +! CHECK: --- !Analysis + +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 \ @@ -38,5 +39,7 @@ ! CHECK: "-fpass-plugin=Bye ! CHECK: "-flang-experimental-polymorphism" ! CHECK: "-fversion-loops-for-stride" +! CHECK: "-opt-record-file" +! CHECK: "-opt-record-format" ! CHECK: "-mllvm" "-print-before-all" ! CHECK: "-save-temps=obj" 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 @@ -47,6 +47,7 @@ #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 +56,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" @@ -1002,6 +1004,28 @@ if (!ci.getInvocation().getCodeGenOpts().OffloadObjects.empty()) embedOffloadObjects(); + // write optimization-record + const CodeGenOptions &CodeGenOpts = ci.getInvocation().getCodeGenOpts(); + + llvm::Expected<std::unique_ptr<llvm::ToolOutputFile>> RemarksFileOrErr = + setupLLVMOptimizationRemarks( + llvmModule->getContext(), CodeGenOpts.OptRecordFile, + CodeGenOpts.OptRecordPasses, CodeGenOpts.OptRecordFormat, + /*DiagnosticsWithHotness=*/false, + /*DiagnosticsHotnessThreshold=*/0); + + if (llvm::Error E = RemarksFileOrErr.takeError()) { + llvm::errs() << toString(std::move(E)) << '\n'; + return; + } + std::unique_ptr<llvm::ToolOutputFile> ToolRemarksFile = + std::move(*RemarksFileOrErr); + + if (ToolRemarksFile) { + ToolRemarksFile->keep(); + ToolRemarksFile->os().flush(); + } + // Run LLVM's middle-end (i.e. the optimizer). runOptimizationPipeline(ci.isOutputStreamNull() ? *os : ci.getOutputStream()); Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -190,6 +190,22 @@ 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,52 @@ CmdArgs.push_back("-freciprocal-math"); } +static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, + const llvm::Triple &Triple, + const InputInfo &Input, + const InputInfo &Output, const JobAction &JA) { + 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 +519,11 @@ // Add Codegen options addCodegenOptions(Args, CmdArgs); + // Remarks can be enabled with any of the `-f.*optimization-record.*` flags. + if (willEmitRemarks(Args)) { + renderRemarksOptions(Args, CmdArgs, Triple, Input, Output, JA); + } + // 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 @@ -3065,18 +3065,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>">; @@ -6364,14 +6364,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">>; @@ -6433,6 +6425,14 @@ } // let Flags = [CC1Option, NoDriverOption] +def opt_record_file : Separate<["-"], "opt-record-file">, Flags<[FC1Option, CC1Option]>, + HelpText<"File name to use for YAML optimization record output">, + MarshallingInfoString<CodeGenOpts<"OptRecordFile">>; +def opt_record_passes : Separate<["-"], "opt-record-passes">, Flags<[FC1Option, CC1Option]>, + HelpText<"Only record remark information for passes whose names match the given regular expression">; +def opt_record_format : Separate<["-"], "opt-record-format">, Flags<[FC1Option, CC1Option]>, + HelpText<"The format used for serializing remarks (default: YAML)">; + //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits