diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h | 16 | ||||
| -rw-r--r-- | llvm/include/llvm/IR/DiagnosticHandler.h | 5 | ||||
| -rw-r--r-- | llvm/include/llvm/IR/DiagnosticInfo.h | 83 | ||||
| -rw-r--r-- | llvm/lib/IR/DiagnosticHandler.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/IR/DiagnosticInfo.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/Inliner.cpp | 18 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Utils/LoopUnroll.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 6 |
8 files changed, 138 insertions, 34 deletions
diff --git a/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h b/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h index 4c3b0fb949b..aae1b2c1b0c 100644 --- a/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h +++ b/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h @@ -24,7 +24,6 @@ namespace llvm { class DebugLoc; -class LLVMContext; class Loop; class Pass; class Twine; @@ -71,6 +70,21 @@ public: /// optimization record file. void emit(DiagnosticInfoOptimizationBase &OptDiag); + /// \brief Take a lambda that returns a remark which will be emitted. Second + /// argument is only used to restrict this to functions. + template <typename T> + void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { + // Avoid building the remark unless we know there are at least *some* + // remarks enabled. We can't currently check whether remarks are requested + // for the calling pass since that requires actually building the remark. + + if (F->getContext().getDiagnosticsOutputFile() || + F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { + auto R = RemarkBuilder(); + emit(R); + } + } + /// \brief Whether we allow for extra compile-time budget to perform more /// analysis to produce fewer false positives. /// diff --git a/llvm/include/llvm/IR/DiagnosticHandler.h b/llvm/include/llvm/IR/DiagnosticHandler.h index c9a606f02f7..9256d4850df 100644 --- a/llvm/include/llvm/IR/DiagnosticHandler.h +++ b/llvm/include/llvm/IR/DiagnosticHandler.h @@ -60,12 +60,15 @@ struct DiagnosticHandler { /// to provide different implementation. virtual bool isPassedOptRemarkEnabled(StringRef PassName) const; - /// Return true if any type of remarks are enabled. + /// Return true if any type of remarks are enabled for this pass. bool isAnyRemarkEnabled(StringRef PassName) const { return (isMissedOptRemarkEnabled(PassName) || isPassedOptRemarkEnabled(PassName) || isAnalysisRemarkEnabled(PassName)); } + + /// Return true if any type of remarks are enabled for any pass. + virtual bool isAnyRemarkEnabled() const; }; } // namespace llvm diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h index a2023554a89..1e9bcb67e28 100644 --- a/llvm/include/llvm/IR/DiagnosticInfo.h +++ b/llvm/include/llvm/IR/DiagnosticInfo.h @@ -438,10 +438,10 @@ public: : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc), PassName(PassName), RemarkName(RemarkName) {} - DiagnosticInfoOptimizationBase &operator<<(StringRef S); - DiagnosticInfoOptimizationBase &operator<<(Argument A); - DiagnosticInfoOptimizationBase &operator<<(setIsVerbose V); - DiagnosticInfoOptimizationBase &operator<<(setExtraArgs EA); + void insert(StringRef S); + void insert(Argument A); + void insert(setIsVerbose V); + void insert(setExtraArgs EA); /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; @@ -511,6 +511,81 @@ protected: friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>; }; +/// Allow the insertion operator to return the actual remark type rather than a +/// common base class. This allows returning the result of the insertion +/// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah". +template <class RemarkT> +RemarkT & +operator<<(RemarkT &R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + StringRef>::type S) { + R.insert(S); + return R; +} + +/// Also allow r-value for the remark to allow insertion into a +/// temporarily-constructed remark. +template <class RemarkT> +RemarkT & +operator<<(RemarkT &&R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + StringRef>::type S) { + R.insert(S); + return R; +} + +template <class RemarkT> +RemarkT & +operator<<(RemarkT &R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + DiagnosticInfoOptimizationBase::Argument>::type A) { + R.insert(A); + return R; +} + +template <class RemarkT> +RemarkT & +operator<<(RemarkT &&R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + DiagnosticInfoOptimizationBase::Argument>::type A) { + R.insert(A); + return R; +} + +template <class RemarkT> +RemarkT & +operator<<(RemarkT &R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + DiagnosticInfoOptimizationBase::setIsVerbose>::type V) { + R.insert(V); + return R; +} + +template <class RemarkT> +RemarkT & +operator<<(RemarkT &&R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + DiagnosticInfoOptimizationBase::setIsVerbose>::type V) { + R.insert(V); + return R; +} + +template <class RemarkT> +RemarkT & +operator<<(RemarkT &R, + typename std::enable_if< + std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, + DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) { + R.insert(EA); + return R; +} + /// \brief Common features for diagnostics dealing with optimization remarks /// that are used by IR passes. class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase { diff --git a/llvm/lib/IR/DiagnosticHandler.cpp b/llvm/lib/IR/DiagnosticHandler.cpp index ad4f5dac8d8..fb1ac438ffb 100644 --- a/llvm/lib/IR/DiagnosticHandler.cpp +++ b/llvm/lib/IR/DiagnosticHandler.cpp @@ -84,3 +84,8 @@ bool DiagnosticHandler::isPassedOptRemarkEnabled(StringRef PassName) const { return (PassRemarksPassedOptLoc.Pattern && PassRemarksPassedOptLoc.Pattern->match(PassName)); } + +bool DiagnosticHandler::isAnyRemarkEnabled() const { + return (PassRemarksPassedOptLoc.Pattern || PassRemarksMissedOptLoc.Pattern || + PassRemarksAnalysisOptLoc.Pattern); +} diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp index bb9e52abe53..b033f4d5453 100644 --- a/llvm/lib/IR/DiagnosticInfo.cpp +++ b/llvm/lib/IR/DiagnosticInfo.cpp @@ -315,28 +315,20 @@ void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { DP << "Instruction selection used fallback path for " << getFunction(); } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(StringRef S) { +void DiagnosticInfoOptimizationBase::insert(StringRef S) { Args.emplace_back(S); - return *this; } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(Argument A) { +void DiagnosticInfoOptimizationBase::insert(Argument A) { Args.push_back(std::move(A)); - return *this; } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(setIsVerbose V) { +void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) { IsVerbose = true; - return *this; } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(setExtraArgs EA) { +void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) { FirstExtraArgIndex = Args.size(); - return *this; } std::string DiagnosticInfoOptimizationBase::getMsg() const { diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp index 3c46913f8a8..4233ba9deec 100644 --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -356,10 +356,12 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, if (IC.isNever()) { DEBUG(dbgs() << " NOT Inlining: cost=never" << ", Call: " << *CS.getInstruction() << "\n"); - ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) + ORE.emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) << NV("Callee", Callee) << " not inlined into " << NV("Caller", Caller) - << " because it should never be inlined (cost=never)"); + << " because it should never be inlined (cost=never)"; + }); return None; } @@ -367,11 +369,13 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost() << ", thres=" << IC.getThreshold() << ", Call: " << *CS.getInstruction() << "\n"); - ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call) + ORE.emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call) << NV("Callee", Callee) << " not inlined into " << NV("Caller", Caller) << " because too costly to inline (cost=" << NV("Cost", IC.getCost()) - << ", threshold=" << NV("Threshold", IC.getThreshold()) << ")"); + << ", threshold=" << NV("Threshold", IC.getThreshold()) << ")"; + }); return None; } @@ -581,12 +585,14 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, << NV("Callee", Callee) << " inlined into " << NV("Caller", Caller) << " with cost=always"); else - ORE.emit(OptimizationRemark(DEBUG_TYPE, "Inlined", DLoc, Block) + ORE.emit([&]() { + return OptimizationRemark(DEBUG_TYPE, "Inlined", DLoc, Block) << NV("Callee", Callee) << " inlined into " << NV("Caller", Caller) << " with cost=" << NV("Cost", OIC->getCost()) << " (threshold=" << NV("Threshold", OIC->getThreshold()) - << ")"); + << ")"; + }); // If inlining this function gave us any new call sites, throw them // onto our worklist to process. They are useful inline candidates. diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp index 7759ac74d56..1fdc5e124e5 100644 --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -476,23 +476,30 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force, << " peeled loop by " << NV("PeelCount", PeelCount) << " iterations"); } else { - OptimizationRemark Diag(DEBUG_TYPE, "PartialUnrolled", L->getStartLoc(), - L->getHeader()); - Diag << "unrolled loop by a factor of " << NV("UnrollCount", Count); + auto DiagBuilder = [&]() { + OptimizationRemark Diag(DEBUG_TYPE, "PartialUnrolled", L->getStartLoc(), + L->getHeader()); + return Diag << "unrolled loop by a factor of " + << NV("UnrollCount", Count); + }; DEBUG(dbgs() << "UNROLLING loop %" << Header->getName() << " by " << Count); if (TripMultiple == 0 || BreakoutTrip != TripMultiple) { DEBUG(dbgs() << " with a breakout at trip " << BreakoutTrip); - ORE->emit(Diag << " with a breakout at trip " - << NV("BreakoutTrip", BreakoutTrip)); + ORE->emit([&]() { + return DiagBuilder() << " with a breakout at trip " + << NV("BreakoutTrip", BreakoutTrip); + }); } else if (TripMultiple != 1) { DEBUG(dbgs() << " with " << TripMultiple << " trips per branch"); - ORE->emit(Diag << " with " << NV("TripMultiple", TripMultiple) - << " trips per branch"); + ORE->emit([&]() { + return DiagBuilder() << " with " << NV("TripMultiple", TripMultiple) + << " trips per branch"; + }); } else if (RuntimeTripCount) { DEBUG(dbgs() << " with run-time trip count"); - ORE->emit(Diag << " with run-time trip count"); + ORE->emit([&]() { return DiagBuilder() << " with run-time trip count"; }); } DEBUG(dbgs() << "!\n"); } diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index d339143bf64..c14ae0d962c 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1231,12 +1231,14 @@ public: // FIXME: Add interleave.disable metadata. This will allow // vectorize.disable to be used without disabling the pass and errors // to differentiate between disabled vectorization and a width of 1. - ORE.emit(OptimizationRemarkAnalysis(vectorizeAnalysisPassName(), + ORE.emit([&]() { + return OptimizationRemarkAnalysis(vectorizeAnalysisPassName(), "AllDisabled", L->getStartLoc(), L->getHeader()) << "loop not vectorized: vectorization and interleaving are " "explicitly disabled, or the loop has already been " - "vectorized"); + "vectorized"; + }); return false; } |

