summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h1
-rw-r--r--llvm/include/llvm/IR/DiagnosticInfo.h12
-rw-r--r--llvm/lib/IR/DiagnosticInfo.cpp24
-rw-r--r--llvm/lib/Transforms/Scalar/GVN.cpp13
-rw-r--r--llvm/test/Transforms/GVN/opt-remarks.ll6
5 files changed, 49 insertions, 7 deletions
diff --git a/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h b/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h
index b0653367c0c..fa0b3eede67 100644
--- a/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h
+++ b/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h
@@ -223,6 +223,7 @@ private:
namespace ore {
using NV = DiagnosticInfoOptimizationBase::Argument;
using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose;
+using setExtraArgs = DiagnosticInfoOptimizationBase::setExtraArgs;
}
/// OptimizationRemarkEmitter legacy analysis pass
diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index e739dfbd673..a93c180df1b 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -382,6 +382,12 @@ public:
/// \brief Used to set IsVerbose via the stream interface.
struct setIsVerbose {};
+ /// \brief When an instance of this is inserted into the stream, the arguments
+ /// following will not appear in the remark printed in the compiler output
+ /// (-Rpass) but only in the optimization record file
+ /// (-fsave-optimization-record).
+ struct setExtraArgs {};
+
/// \brief Used in the streaming interface as the general argument type. It
/// internally converts everything into a key-value pair.
struct Argument {
@@ -452,6 +458,7 @@ public:
DiagnosticInfoOptimizationBase &operator<<(StringRef S);
DiagnosticInfoOptimizationBase &operator<<(Argument A);
DiagnosticInfoOptimizationBase &operator<<(setIsVerbose V);
+ DiagnosticInfoOptimizationBase &operator<<(setExtraArgs EA);
/// \see DiagnosticInfo::print.
void print(DiagnosticPrinter &DP) const override;
@@ -501,6 +508,11 @@ private:
/// The remark is expected to be noisy.
bool IsVerbose = false;
+ /// \brief If positive, the index of the first argument that only appear in
+ /// the optimization records and not in the remark printed in the compiler
+ /// output.
+ int FirstExtraArgIndex = -1;
+
friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
};
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp
index 6a3fdcff233..ea71fde26e0 100644
--- a/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/llvm/lib/IR/DiagnosticInfo.cpp
@@ -170,14 +170,25 @@ const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const {
getLocation(&Filename, &Line, &Column);
return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
}
+
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Value *V)
- : Key(Key), Val(GlobalValue::getRealLinkageName(V->getName())) {
+ : Key(Key) {
if (auto *F = dyn_cast<Function>(V)) {
if (DISubprogram *SP = F->getSubprogram())
DLoc = DebugLoc::get(SP->getScopeLine(), 0, SP);
}
else if (auto *I = dyn_cast<Instruction>(V))
DLoc = I->getDebugLoc();
+
+ // Only include names that correspond to user variables. FIXME: we should use
+ // debug info if available to get the name of the user variable.
+ if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
+ Val = GlobalValue::getRealLinkageName(V->getName());
+ else if (isa<Constant>(V)) {
+ raw_string_ostream OS(Val);
+ V->printAsOperand(OS, /*PrintType=*/false);
+ } else if (auto *I = dyn_cast<Instruction>(V))
+ Val = I->getOpcodeName();
}
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Type *T)
@@ -359,10 +370,19 @@ operator<<(setIsVerbose V) {
return *this;
}
+DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
+operator<<(setExtraArgs EA) {
+ FirstExtraArgIndex = Args.size();
+ return *this;
+}
+
std::string DiagnosticInfoOptimizationBase::getMsg() const {
std::string Str;
raw_string_ostream OS(Str);
- for (const DiagnosticInfoOptimizationBase::Argument &Arg : Args)
+ for (const DiagnosticInfoOptimizationBase::Argument &Arg :
+ make_range(Args.begin(), FirstExtraArgIndex == -1
+ ? Args.end()
+ : Args.begin() + FirstExtraArgIndex))
OS << Arg.Val;
return OS.str();
}
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 050cc2ecc89..9a14fcb07f9 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -1591,10 +1591,13 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
return true;
}
-static void reportLoadElim(LoadInst *LI, OptimizationRemarkEmitter *ORE) {
+static void reportLoadElim(LoadInst *LI, Value *AvailableValue,
+ OptimizationRemarkEmitter *ORE) {
+ using namespace ore;
ORE->emit(OptimizationRemark(DEBUG_TYPE, "LoadElim", LI)
- << "load of type " << ore::NV("Type", LI->getType())
- << " eliminated");
+ << "load of type " << NV("Type", LI->getType()) << " eliminated"
+ << setExtraArgs() << " in favor of "
+ << NV("InfavorOfValue", AvailableValue));
}
/// Attempt to eliminate a load whose dependencies are
@@ -1667,7 +1670,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
MD->invalidateCachedPointerInfo(V);
markInstructionForDeletion(LI);
++NumGVNLoad;
- reportLoadElim(LI, ORE);
+ reportLoadElim(LI, V, ORE);
return true;
}
@@ -1814,7 +1817,7 @@ bool GVN::processLoad(LoadInst *L) {
patchAndReplaceAllUsesWith(L, AvailableValue);
markInstructionForDeletion(L);
++NumGVNLoad;
- reportLoadElim(L, ORE);
+ reportLoadElim(L, AvailableValue, ORE);
// Tell MDA to rexamine the reused pointer since we might have more
// information after forwarding it.
if (MD && AvailableValue->getType()->getScalarType()->isPointerTy())
diff --git a/llvm/test/Transforms/GVN/opt-remarks.ll b/llvm/test/Transforms/GVN/opt-remarks.ll
index c451833f765..14c1feff4a1 100644
--- a/llvm/test/Transforms/GVN/opt-remarks.ll
+++ b/llvm/test/Transforms/GVN/opt-remarks.ll
@@ -15,6 +15,8 @@
; YAML-NEXT: - String: 'load of type '
; YAML-NEXT: - Type: i32
; YAML-NEXT: - String: ' eliminated'
+; YAML-NEXT: - String: ' in favor of '
+; YAML-NEXT: - InfavorOfValue: i
; YAML-NEXT: ...
; YAML-NEXT: --- !Passed
; YAML-NEXT: Pass: gvn
@@ -24,6 +26,8 @@
; YAML-NEXT: - String: 'load of type '
; YAML-NEXT: - Type: i32
; YAML-NEXT: - String: ' eliminated'
+; YAML-NEXT: - String: ' in favor of '
+; YAML-NEXT: - InfavorOfValue: '4'
; YAML-NEXT: ...
; YAML-NEXT: --- !Passed
; YAML-NEXT: Pass: gvn
@@ -33,6 +37,8 @@
; YAML-NEXT: - String: 'load of type '
; YAML-NEXT: - Type: i32
; YAML-NEXT: - String: ' eliminated'
+; YAML-NEXT: - String: ' in favor of '
+; YAML-NEXT: - InfavorOfValue: load
; YAML-NEXT: ...
OpenPOWER on IntegriCloud