Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -111,6 +111,8 @@ "unknown or ill-formed Objective-C runtime '%0'">; def err_drv_emit_llvm_link : Error< "-emit-llvm cannot be used when linking">; +def err_drv_optimization_report_pattern : Error< + "%0 in '%1'">; def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">, Index: include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== --- include/clang/Basic/DiagnosticFrontendKinds.td +++ include/clang/Basic/DiagnosticFrontendKinds.td @@ -32,6 +32,9 @@ def remark_fe_backend_plugin: Remark<"%0">, CatBackend, InGroup; def note_fe_backend_plugin: Note<"%0">, CatBackend; +def remark_fe_backend_optimization_report: Remark<"%0">, CatBackend, + InGroup; + def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -662,3 +662,4 @@ def BackendFrameLargerThan : DiagGroup<"frame-larger-than">; def BackendPlugin : DiagGroup<"backend-plugin">; def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">; +def BackendOptimizationReport : DiagGroup<"Rpass">; Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -60,6 +60,7 @@ def M_Group : OptionGroup<"">, Group; def T_Group : OptionGroup<"">; def O_Group : OptionGroup<"">, Group; +def R_Group : OptionGroup<"">, Group; def W_Group : OptionGroup<"">, Group; def d_Group : OptionGroup<"">; def f_Group : OptionGroup<"">, Group; @@ -253,7 +254,8 @@ def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<["-"], "Q">; -def R : Flag<["-"], "R">; +def Rpass_EQ : Joined<["-"], "Rpass=">, Group, Flags<[CC1Option]>, + HelpText<"Report transformations performed by optimization passes">; def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group, HelpText<"Only run preprocess and compilation steps">; def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group; Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -16,6 +16,7 @@ #include #include +#include "llvm/Support/Regex.h" namespace clang { @@ -145,6 +146,13 @@ /// Name of the profile file to use as input for -fprofile-instr-use std::string InstrProfileInput; + /// Regular expression to select optimizations for which we should enable + /// optimization reports. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they perform a transformation. This is enabled by the + /// -Rpass=regexp flag. + llvm::Regex *OptimizationReportPattern; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -20,6 +20,7 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" @@ -220,6 +221,11 @@ /// \return True if the diagnostic has been successfully reported, false /// otherwise. bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); + /// \brief Specialized handler for the optimization report diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool + OptimizationReportHandler(const llvm::DiagnosticInfoOptimizationReport &D); }; void BackendConsumer::anchor() {} @@ -374,6 +380,22 @@ return true; } +bool BackendConsumer::OptimizationReportHandler( + const llvm::DiagnosticInfoOptimizationReport &D) { + if (CodeGenOpts.OptimizationReportPattern->match(D.getPassName())) { + SourceLocation Loc; + // FIXME: This should be done earlier. + Diags.setDiagnosticMapping(diag::remark_fe_backend_optimization_report, + diag::Mapping::MAP_REMARK, Loc); + // FIXME: There should be a way of transferring the DILocation + // content into a SourceLocation. We are building the location string + // unnecessarily. + Diags.Report(Loc, diag::remark_fe_backend_optimization_report) + << Twine(D.getLocationStr() + ": " + D.getMsg()).str(); + } + return true; +} + /// \brief This function is invoked when the backend needs /// to report something to the user. void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { @@ -391,6 +413,10 @@ return; ComputeDiagID(Severity, backend_frame_larger_than, DiagID); break; + case llvm::DK_OptimizationReport: + if (CodeGenOpts.OptimizationReportPattern) + OptimizationReportHandler(cast(DI)); + return; default: // Plugin IDs are not bound to any value as they are set dynamically. ComputeDiagRemarkID(Severity, backend_plugin, DiagID); Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -3359,6 +3359,10 @@ A->render(Args, CmdArgs); } + if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) { + A->render(Args, CmdArgs); + } + if (Args.hasArg(options::OPT_mkernel)) { if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType)) CmdArgs.push_back("-fapple-kext"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -520,6 +520,23 @@ Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib); + if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) { + StringRef Val = A->getValue(); + std::string RegexError; + Opts.OptimizationReportPattern = new llvm::Regex(Val); + if (!Opts.OptimizationReportPattern->isValid(RegexError)) { + Diags.Report(diag::err_drv_optimization_report_pattern) + << RegexError << A->getAsString(Args); + delete Opts.OptimizationReportPattern; + Opts.OptimizationReportPattern = 0; + } else { + // Optimization report diagnostics need to extract location information + // from the instructions they are emitted on. When -Rpass is used, + // enable line table generation. + Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly); + } + } + return Success; }