summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Diagnostic.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td6
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticIDs.h3
-rw-r--r--clang/include/clang/Driver/Options.td5
-rw-r--r--clang/include/clang/Frontend/CodeGenOptions.h8
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp49
-rw-r--r--clang/lib/Driver/Tools.cpp3
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp11
-rw-r--r--clang/lib/Frontend/TextDiagnosticPrinter.cpp3
-rw-r--r--clang/test/Frontend/optimization-remark.c19
13 files changed, 114 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td
index 61a4508615e..5bcc2d5c165 100644
--- a/clang/include/clang/Basic/Diagnostic.td
+++ b/clang/include/clang/Basic/Diagnostic.td
@@ -102,6 +102,7 @@ class DefaultWarnNoWerror {
class DefaultWarnShowInSystemHeader {
bit WarningShowInSystemHeader = 1;
}
+class DefaultRemark { DiagMapping DefaultMapping = MAP_REMARK; }
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index a64b1ae63ce..f65fecdcf69 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -114,6 +114,8 @@ def err_drv_unknown_objc_runtime : Error<
"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_remark_pattern : Error<
+ "%0 in '%1'">;
def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">,
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 32c824a9302..7b500eed5c0 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -32,6 +32,12 @@ def err_fe_backend_plugin: Error<"%0">, CatBackend;
def remark_fe_backend_plugin: Remark<"%0">, CatBackend, InGroup<RemarkBackendPlugin>;
def note_fe_backend_plugin: Note<"%0">, CatBackend;
+def remark_fe_backend_optimization_remark : Remark<"%0">, CatBackend,
+ InGroup<BackendOptimizationRemark>, 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">;
+
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">,
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index f707c989fc8..b47b871dbee 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -665,6 +665,7 @@ def BackendInlineAsm : DiagGroup<"inline-asm">;
def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
def BackendPlugin : DiagGroup<"backend-plugin">;
def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationRemark : DiagGroup<"pass">;
// Instrumentation based profiling warnings.
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index f9b845606bc..c952e49793b 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -154,6 +154,9 @@ public:
/// default.
static bool isDefaultMappingAsError(unsigned DiagID);
+ /// \brief Return true if the specified diagnostic is a Remark.
+ static bool isRemark(unsigned DiagID);
+
/// \brief Determine whether the given built-in diagnostic ID is a Note.
static bool isBuiltinNote(unsigned DiagID);
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 1c84d74b8cc..b734280a891 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -60,6 +60,7 @@ def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
def T_Group : OptionGroup<"<T group>">;
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
+def R_Group : OptionGroup<"<R group>">, Group<CompileOnly_Group>;
def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
def d_Group : OptionGroup<"<d group>">;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
@@ -253,7 +254,9 @@ def Qn : Flag<["-"], "Qn">;
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<R_Group>, Flags<[CC1Option]>,
+ HelpText<"Report transformations performed by 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/clang/include/clang/Frontend/CodeGenOptions.h b/clang/include/clang/Frontend/CodeGenOptions.h
index da97e5c956b..9c8de1b5cef 100644
--- a/clang/include/clang/Frontend/CodeGenOptions.h
+++ b/clang/include/clang/Frontend/CodeGenOptions.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "llvm/Support/Regex.h"
namespace clang {
@@ -145,6 +146,13 @@ public:
/// 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 remarks. 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.
+ std::shared_ptr<llvm::Regex> OptimizationRemarkPattern;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index cf6933aeb1c..5334ae88d1c 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -361,6 +361,11 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
}
+bool DiagnosticIDs::isRemark(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) == CLASS_REMARK;
+}
+
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 573f8e98e77..67859bad2b4 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/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 @@ 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
+ /// them.
+ void
+ OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
};
void BackendConsumer::anchor() {}
@@ -374,6 +380,44 @@ BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
return true;
}
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemark &D) {
+ // 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;
+ if (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(FileMgr.getFile(Filename), Line,
+ Column);
+ }
+ Diags.Report(Loc, diag::remark_fe_backend_optimization_remark)
+ << 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);
+ }
+}
+
/// \brief This function is invoked when the backend needs
/// to report something to the user.
void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -391,6 +435,11 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
return;
ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
break;
+ case llvm::DK_OptimizationRemark:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
+ return;
default:
// Plugin IDs are not bound to any value as they are set dynamically.
ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 018f9ba5748..9f64c3fa461 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -3417,6 +3417,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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");
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 6177a96fa7b..e51d2cf8529 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -520,6 +520,17 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
+ if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
+ StringRef Val = A->getValue();
+ std::string RegexError;
+ Opts.OptimizationRemarkPattern = std::make_shared<llvm::Regex>(Val);
+ if (!Opts.OptimizationRemarkPattern->isValid(RegexError)) {
+ Diags.Report(diag::err_drv_optimization_remark_pattern)
+ << RegexError << A->getAsString(Args);
+ Opts.OptimizationRemarkPattern.reset();
+ }
+ }
+
return Success;
}
diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 994a8f74ed4..3b5eca6dd9d 100644
--- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -81,7 +81,8 @@ static void printDiagnosticOptions(raw_ostream &OS,
StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
if (!Opt.empty()) {
- OS << (Started ? "," : " [") << "-W" << Opt;
+ OS << (Started ? "," : " [")
+ << (DiagnosticIDs::isRemark(Info.getID()) ? "-R" : "-W") << Opt;
Started = true;
}
}
diff --git a/clang/test/Frontend/optimization-remark.c b/clang/test/Frontend/optimization-remark.c
new file mode 100644
index 00000000000..d5345b546a5
--- /dev/null
+++ b/clang/test/Frontend/optimization-remark.c
@@ -0,0 +1,19 @@
+// 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.
+
+// RUN: %clang -c %s -Rpass=inline -O0 -gline-tables-only -o /dev/null 2> %t.err
+// RUN: FileCheck < %t.err %s --check-prefix=INLINE
+
+// RUN: %clang -c %s -Rpass=inline -O0 -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; }
+int bar(int j) { return foo(j, j - 2); }
+
+// INLINE: remark: foo inlined into bar [-Rpass]
+
+// INLINE-NO-LOC: {{^remark: foo inlined into bar}}
+// INLINE-NO-LOC: note: use -gline-tables-only -gcolumn-info to track
OpenPOWER on IntegriCloud