forked from OSchip/llvm-project
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 llvm-svn: 209839
This commit is contained in:
parent
20daf3276d
commit
d23ec94393
|
@ -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">;
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue