diff options
author | Diego Novillo <dnovillo@google.com> | 2014-05-29 19:55:06 +0000 |
---|---|---|
committer | Diego Novillo <dnovillo@google.com> | 2014-05-29 19:55:06 +0000 |
commit | a3f8ad86d837d139cf7f37b2fd7448000bc1d0e1 (patch) | |
tree | ab39ffdecd8d69bb87349738c7368362473f9ac4 | |
parent | a7e8472be21324151dd7cc75c595cd380548824d (diff) | |
download | clang-a3f8ad86d837d139cf7f37b2fd7448000bc1d0e1.tar.gz |
Add flags -Rpass-missed and -Rpass-analysis.
Summary:
These two flags are in the same family as -Rpass, but are used in
different situations.
-Rpass-missed is used by optimizers to inform the user when they tried
to apply an optimization but couldn't (or wouldn't).
-Rpass-analysis is used by optimizers to report analysis results back
to the user (e.g., why the transformation could not be applied).
Depends on D3682.
Reviewers: rsmith
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D3683
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209839 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticFrontendKinds.td | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 8 | ||||
-rw-r--r-- | include/clang/Frontend/CodeGenOptions.h | 15 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenAction.cpp | 125 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 28 | ||||
-rw-r--r-- | test/Frontend/optimization-remark.c | 23 |
8 files changed, 161 insertions, 50 deletions
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 91faa0a69c..03ed69116c 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -34,6 +34,10 @@ def note_fe_backend_plugin: Note<"%0">, CatBackend; def remark_fe_backend_optimization_remark : Remark<"%0">, CatBackend, InGroup<BackendOptimizationRemark>, DefaultRemark; +def remark_fe_backend_optimization_remark_missed : Remark<"%0">, CatBackend, + InGroup<BackendOptimizationRemarkMissed>, DefaultRemark; +def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, CatBackend, + InGroup<BackendOptimizationRemarkAnalysis>, DefaultRemark; def note_fe_backend_optimization_remark_missing_loc : Note<"use " "-gline-tables-only -gcolumn-info to track source location information " "for this optimization remark">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 230e021203..637d4fc956 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -685,6 +685,8 @@ def BackendFrameLargerThan : DiagGroup<"frame-larger-than">; def BackendPlugin : DiagGroup<"backend-plugin">; def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">; def BackendOptimizationRemark : DiagGroup<"pass">; +def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">; +def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">; // Instrumentation based profiling warnings. def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 0e251aa6b1..d277551964 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -257,6 +257,14 @@ def Q : Flag<["-"], "Q">; def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_Group>, Flags<[CC1Option]>, HelpText<"Report transformations performed by optimization passes whose " "name matches the given POSIX regular expression">; +def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_Group>, + Flags<[CC1Option]>, + HelpText<"Report missed transformations by optimization passes whose " + "name matches the given POSIX regular expression">; +def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_Group>, + Flags<[CC1Option]>, + HelpText<"Report transformation analysis from optimization passes whose " + "name matches the given POSIX regular expression">; def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run preprocess and compilation steps">; def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>; diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 9c8de1b5ce..c1ad408b75 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -153,6 +153,21 @@ public: /// -Rpass=regexp flag. std::shared_ptr<llvm::Regex> OptimizationRemarkPattern; + /// Regular expression to select optimizations for which we should enable + /// missed optimization remarks. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they tried but failed to perform a transformation. This is + /// enabled by the -Rpass-missed=regexp flag. + std::shared_ptr<llvm::Regex> OptimizationRemarkMissedPattern; + + /// Regular expression to select optimizations for which we should enable + /// optimization analyses. Transformation passes whose name matches this + /// expression (and support this feature), will emit a diagnostic + /// whenever they want to explain why they decided to apply or not apply + /// a given transformation. This is enabled by the -Rpass-analysis=regexp + /// flag. + std::shared_ptr<llvm::Regex> OptimizationRemarkAnalysisPattern; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index 4bb3895108..d337fa7c43 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -235,11 +235,18 @@ namespace clang { /// \return True if the diagnostic has been successfully reported, false /// otherwise. bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); - /// \brief Specialized handler for the optimization diagnostic. - /// Note that this handler only accepts remarks and it always handles + /// \brief Specialized handlers for optimization remarks. + /// Note that these handlers only accept remarks and they always handle /// them. void + EmitOptimizationRemark(const llvm::DiagnosticInfoOptimizationRemarkBase &D, + unsigned DiagID); + void OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D); + void OptimizationRemarkHandler( + const llvm::DiagnosticInfoOptimizationRemarkMissed &D); + void OptimizationRemarkHandler( + const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D); }; void BackendConsumer::anchor() {} @@ -394,49 +401,74 @@ BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { return true; } -void BackendConsumer::OptimizationRemarkHandler( - const llvm::DiagnosticInfoOptimizationRemark &D) { +void BackendConsumer::EmitOptimizationRemark( + const llvm::DiagnosticInfoOptimizationRemarkBase &D, unsigned DiagID) { // We only support remarks. assert(D.getSeverity() == llvm::DS_Remark); - // Optimization remarks are active only if -Rpass=regexp is given and the - // regular expression pattern in 'regexp' matches the name of the pass - // name in \p D. - if (CodeGenOpts.OptimizationRemarkPattern && - CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) { - SourceManager &SourceMgr = Context->getSourceManager(); - FileManager &FileMgr = SourceMgr.getFileManager(); - StringRef Filename; - unsigned Line, Column; - D.getLocation(&Filename, &Line, &Column); - SourceLocation Loc; - const FileEntry *FE = FileMgr.getFile(Filename); - if (FE && Line > 0) { - // If -gcolumn-info was not used, Column will be 0. This upsets the - // source manager, so if Column is not set, set it to 1. - if (Column == 0) - Column = 1; - Loc = SourceMgr.translateFileLineCol(FE, Line, Column); - } - Diags.Report(Loc, diag::remark_fe_backend_optimization_remark) - << AddFlagValue(D.getPassName()) << D.getMsg().str(); - - if (Line == 0) - // If we could not extract a source location for the diagnostic, - // inform the user how they can get source locations back. - // - // FIXME: We should really be generating !srcloc annotations when - // -Rpass is used. !srcloc annotations need to be emitted in - // approximately the same spots as !dbg nodes. - Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc); - else if (Loc.isInvalid()) - // If we were not able to translate the file:line:col information - // back to a SourceLocation, at least emit a note stating that - // we could not translate this location. This can happen in the - // case of #line directives. - Diags.Report(diag::note_fe_backend_optimization_remark_invalid_loc) - << Filename << Line << Column; + SourceManager &SourceMgr = Context->getSourceManager(); + FileManager &FileMgr = SourceMgr.getFileManager(); + StringRef Filename; + unsigned Line, Column; + D.getLocation(&Filename, &Line, &Column); + SourceLocation Loc; + const FileEntry *FE = FileMgr.getFile(Filename); + if (FE && Line > 0) { + // If -gcolumn-info was not used, Column will be 0. This upsets the + // source manager, so if Column is not set, set it to 1. + if (Column == 0) + Column = 1; + Loc = SourceMgr.translateFileLineCol(FE, Line, Column); } + Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName()) + << D.getMsg().str(); + + if (Line == 0) + // If we could not extract a source location for the diagnostic, + // inform the user how they can get source locations back. + // + // FIXME: We should really be generating !srcloc annotations when + // -Rpass is used. !srcloc annotations need to be emitted in + // approximately the same spots as !dbg nodes. + Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc); + else if (Loc.isInvalid()) + // If we were not able to translate the file:line:col information + // back to a SourceLocation, at least emit a note stating that + // we could not translate this location. This can happen in the + // case of #line directives. + Diags.Report(diag::note_fe_backend_optimization_remark_invalid_loc) + << Filename << Line << Column; +} + +void BackendConsumer::OptimizationRemarkHandler( + const llvm::DiagnosticInfoOptimizationRemark &D) { + // Optimization remarks are active only if the -Rpass flag has a regular + // expression that matches the name of the pass name in \p D. + if (CodeGenOpts.OptimizationRemarkPattern && + CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) + EmitOptimizationRemark(D, diag::remark_fe_backend_optimization_remark); +} + +void BackendConsumer::OptimizationRemarkHandler( + const llvm::DiagnosticInfoOptimizationRemarkMissed &D) { + // Missed optimization remarks are active only if the -Rpass-missed + // flag has a regular expression that matches the name of the pass + // name in \p D. + if (CodeGenOpts.OptimizationRemarkMissedPattern && + CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName())) + EmitOptimizationRemark(D, + diag::remark_fe_backend_optimization_remark_missed); +} + +void BackendConsumer::OptimizationRemarkHandler( + const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) { + // Optimization analysis remarks are active only if the -Rpass-analysis + // flag has a regular expression that matches the name of the pass + // name in \p D. + if (CodeGenOpts.OptimizationRemarkAnalysisPattern && + CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())) + EmitOptimizationRemark( + D, diag::remark_fe_backend_optimization_remark_analysis); } /// \brief This function is invoked when the backend needs @@ -462,10 +494,15 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI)); return; case llvm::DK_OptimizationRemarkMissed: + // Optimization remarks are always handled completely by this + // handler. There is no generic way of emitting them. + OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemarkMissed>(DI)); + return; case llvm::DK_OptimizationRemarkAnalysis: - // TODO: Do nothing for now. The implementation of these - // two remarks is still under review (http://reviews.llvm.org/D3683). - // Remove this once that patch lands. + // Optimization remarks are always handled completely by this + // handler. There is no generic way of emitting them. + OptimizationRemarkHandler( + cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI)); return; default: // Plugin IDs are not bound to any value as they are set dynamically. diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index b623e10d3b..ee3b7ff342 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -3469,6 +3469,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) A->render(Args, CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ)) + A->render(Args, CmdArgs); + + if (Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_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"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1ed24a7e43..70c2fec6ce 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -309,6 +309,22 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) { return "default"; } +/// \brief Create a new Regex instance out of the string value in \p RpassArg. +/// It returns a pointer to the newly generated Regex instance. +static std::shared_ptr<llvm::Regex> +GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args, + Arg *RpassArg) { + StringRef Val = RpassArg->getValue(); + std::string RegexError; + std::shared_ptr<llvm::Regex> Pattern = std::make_shared<llvm::Regex>(Val); + if (!Pattern->isValid(RegexError)) { + Diags.Report(diag::err_drv_optimization_remark_pattern) + << RegexError << RpassArg->getAsString(Args); + Pattern.reset(); + } + return Pattern; +} + static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const TargetOptions &TargetOpts) { @@ -545,6 +561,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } + if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) + Opts.OptimizationRemarkPattern = + GenerateOptimizationRemarkRegex(Diags, Args, A); + + if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) + Opts.OptimizationRemarkMissedPattern = + GenerateOptimizationRemarkRegex(Diags, Args, A); + + if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) + Opts.OptimizationRemarkAnalysisPattern = + GenerateOptimizationRemarkRegex(Diags, Args, A); + return Success; } diff --git a/test/Frontend/optimization-remark.c b/test/Frontend/optimization-remark.c index 3a62db0db0..c36a9d4292 100644 --- a/test/Frontend/optimization-remark.c +++ b/test/Frontend/optimization-remark.c @@ -1,18 +1,29 @@ -// This file tests the -Rpass= flag with the inliner. The test is -// designed to always trigger the inliner, so it should be independent -// of the optimization level. +// This file tests the -Rpass family of flags (-Rpass, -Rpass-missed +// and -Rpass-analysis) with the inliner. The test is designed to +// always trigger the inliner, so it should be independent of the +// optimization level. -// RUN: %clang_cc1 %s -Rpass=inline -O0 -gline-tables-only -emit-obj -verify -S -o /dev/null 2> %t.err +// RUN: %clang_cc1 %s -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline -O0 -gline-tables-only -emit-obj -verify -S -o /dev/null 2> %t.err // RUN: %clang -c %s -Rpass=inline -O0 -S -o /dev/null 2> %t.err // RUN: FileCheck < %t.err %s --check-prefix=INLINE-NO-LOC int foo(int x, int y) __attribute__((always_inline)); - int foo(int x, int y) { return x + y; } +float foz(int x, int y) __attribute__((noinline)); +float foz(int x, int y) { return x * y; } + +// The negative diagnostics are emitted twice because the inliner runs +// twice. +// +// expected-remark@+6 {{foz should never be inlined (cost=never)}} +// expected-remark@+5 {{foz will not be inlined into bar}} +// expected-remark@+4 {{foz should never be inlined}} +// expected-remark@+3 {{foz will not be inlined into bar}} +// expected-remark@+2 {{foo should always be inlined}} // expected-remark@+1 {{foo inlined into bar}} -int bar(int j) { return foo(j, j - 2); } +int bar(int j) { return foo(j, j - 2) * foz(j - 2, j); } // INLINE-NO-LOC: {{^remark: foo inlined into bar}} // INLINE-NO-LOC: note: use -gline-tables-only -gcolumn-info to track |