diff options
| author | Adam Nemet <anemet@apple.com> | 2016-07-15 17:23:20 +0000 |
|---|---|---|
| committer | Adam Nemet <anemet@apple.com> | 2016-07-15 17:23:20 +0000 |
| commit | aad816083e3e0b6a195e57a9eab0fa61afea2ab5 (patch) | |
| tree | 900f10703ddf216011bf6eba647993575ce19905 /llvm/lib | |
| parent | 5d9a17742e5c97ef252a86cdd5dc7db5dfc04c79 (diff) | |
| download | bcm5719-llvm-aad816083e3e0b6a195e57a9eab0fa61afea2ab5.tar.gz bcm5719-llvm-aad816083e3e0b6a195e57a9eab0fa61afea2ab5.zip | |
[OptRemark,LDist] RFC: Add hotness attribute
Summary:
This is the first set of changes implementing the RFC from
http://thread.gmane.org/gmane.comp.compilers.llvm.devel/98334
This is a cross-sectional patch; rather than implementing the hotness
attribute for all optimization remarks and all passes in a patch set, it
implements it for the 'missed-optimization' remark for Loop
Distribution. My goal is to shake out the design issues before scaling
it up to other types and passes.
Hotness is computed as an integer as the multiplication of the block
frequency with the function entry count. It's only printed in opt
currently since clang prints the diagnostic fields directly. E.g.:
remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info (hotness: 300)
A new API added is similar to emitOptimizationRemarkMissed. The
difference is that it additionally takes a code region that the
diagnostic corresponds to. From this, hotness is computed using BFI.
The new API is exposed via an analysis pass so that it can be made
dependent on LazyBFI. (Thanks to Hal for the analysis pass idea.)
This feature can all be enabled by setDiagnosticHotnessRequested in the
LLVM context. If this is off, LazyBFI is not calculated (D22141) so
there should be no overhead.
A new command-line option is added to turn this on in opt.
My plan is to switch all user of emitOptimizationRemark* to use this
module instead.
Reviewers: hfinkel
Subscribers: rcox2, mzolotukhin, llvm-commits
Differential Revision: http://reviews.llvm.org/D21771
llvm-svn: 275583
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Analysis/Analysis.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Analysis/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp | 69 | ||||
| -rw-r--r-- | llvm/lib/IR/DiagnosticInfo.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContext.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContextImpl.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 16 |
8 files changed, 93 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp index 2bcfe402e68..ffc4b2ef592 100644 --- a/llvm/lib/Analysis/Analysis.cpp +++ b/llvm/lib/Analysis/Analysis.cpp @@ -64,6 +64,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeModuleDebugInfoPrinterPass(Registry); initializeModuleSummaryIndexWrapperPassPass(Registry); initializeObjCARCAAWrapperPassPass(Registry); + initializeOptimizationRemarkEmitterPass(Registry); initializePostDominatorTreeWrapperPassPass(Registry); initializeRegionInfoPassPass(Registry); initializeRegionViewerPass(Registry); diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 5c6011d77ce..57ad437ef4f 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -57,6 +57,7 @@ add_llvm_library(LLVMAnalysis ObjCARCAliasAnalysis.cpp ObjCARCAnalysisUtils.cpp ObjCARCInstKind.cpp + OptimizationDiagnosticInfo.cpp OrderedBasicBlock.cpp PHITransAddr.cpp PostDominators.cpp diff --git a/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp b/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp new file mode 100644 index 00000000000..9a22633b6e4 --- /dev/null +++ b/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -0,0 +1,69 @@ +//===- OptimizationDiagnosticInfo.cpp - Optimization Diagnostic -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Optimization diagnostic interfaces. It's packaged as an analysis pass so +// that by using this service passes become dependent on BFI as well. BFI is +// used to compute the "hotness" of the diagnostic message. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" +#include "llvm/Analysis/LazyBlockFrequencyInfo.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/LLVMContext.h" + +using namespace llvm; + +OptimizationRemarkEmitter::OptimizationRemarkEmitter() : FunctionPass(ID) { + initializeOptimizationRemarkEmitterPass(*PassRegistry::getPassRegistry()); +} + +Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(Value *V) { + if (!BFI) + return None; + + return BFI->getBlockProfileCount(cast<BasicBlock>(V)); +} + +void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( + const char *PassName, const DebugLoc &DLoc, Value *V, const Twine &Msg) { + LLVMContext &Ctx = F->getContext(); + Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg, + computeHotness(V))); +} + +void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( + const char *PassName, Loop *L, const Twine &Msg) { + emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg); +} + +bool OptimizationRemarkEmitter::runOnFunction(Function &Fn) { + F = &Fn; + + if (Fn.getContext().getDiagnosticHotnessRequested()) + BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI(); + else + BFI = nullptr; + + return false; +} + +void OptimizationRemarkEmitter::getAnalysisUsage(AnalysisUsage &AU) const { + LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); + AU.setPreservesAll(); +} + +char OptimizationRemarkEmitter::ID = 0; +static const char ore_name[] = "Optimization Remark Emitter"; +#define ORE_NAME "opt-remark-emitter" + +INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitter, ORE_NAME, ore_name, false, + true) +INITIALIZE_PASS_DEPENDENCY(LazyBFIPass) +INITIALIZE_PASS_END(OptimizationRemarkEmitter, ORE_NAME, ore_name, false, true) diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp index a3214d72132..ce67be328ab 100644 --- a/llvm/lib/IR/DiagnosticInfo.cpp +++ b/llvm/lib/IR/DiagnosticInfo.cpp @@ -172,6 +172,8 @@ const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const { void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { DP << getLocationStr() << ": " << getMsg(); + if (Hotness) + DP << " (hotness: " << *Hotness << ")"; } bool DiagnosticInfoOptimizationRemark::isEnabled() const { diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index c7ba400ced1..d27fcfb1b7a 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -196,6 +196,13 @@ void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, pImpl->RespectDiagnosticFilters = RespectFilters; } +void LLVMContext::setDiagnosticHotnessRequested(bool Requested) { + pImpl->DiagnosticHotnessRequested = Requested; +} +bool LLVMContext::getDiagnosticHotnessRequested() const { + return pImpl->DiagnosticHotnessRequested; +} + LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { return pImpl->DiagnosticHandler; } diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 3e354b5e0cf..b0b2c61bdf1 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -45,6 +45,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) DiagnosticHandler = nullptr; DiagnosticContext = nullptr; RespectDiagnosticFilters = false; + DiagnosticHotnessRequested = false; YieldCallback = nullptr; YieldOpaqueHandle = nullptr; NamedStructTypesUniqueID = 0; diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index cb4e79ac74e..7820e2ab958 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1043,6 +1043,7 @@ public: LLVMContext::DiagnosticHandlerTy DiagnosticHandler; void *DiagnosticContext; bool RespectDiagnosticFilters; + bool DiagnosticHotnessRequested; LLVMContext::YieldCallbackTy YieldCallback; void *YieldOpaqueHandle; diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp index 6133c251f3b..e09b33b29f7 100644 --- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp @@ -26,8 +26,10 @@ #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/Pass.h" @@ -589,8 +591,8 @@ private: class LoopDistributeForLoop { public: LoopDistributeForLoop(Loop *L, Function *F, LoopInfo *LI, DominatorTree *DT, - ScalarEvolution *SE) - : L(L), F(F), LI(LI), LAI(nullptr), DT(DT), SE(SE) { + ScalarEvolution *SE, OptimizationRemarkEmitter *ORE) + : L(L), F(F), LI(LI), LAI(nullptr), DT(DT), SE(SE), ORE(ORE) { setForced(); } @@ -757,8 +759,8 @@ public: DEBUG(dbgs() << "Skipping; " << Message << "\n"); // With Rpass-missed report that distribution failed. - emitOptimizationRemarkMissed( - Ctx, LDIST_NAME, *F, L->getStartLoc(), + ORE->emitOptimizationRemarkMissed( + LDIST_NAME, L, "loop not distributed: use -Rpass-analysis=loop-distribute for more " "info"); @@ -847,6 +849,7 @@ private: const LoopAccessInfo *LAI; DominatorTree *DT; ScalarEvolution *SE; + OptimizationRemarkEmitter *ORE; /// \brief Indicates whether distribution is forced to be enabled/disabled for /// the loop. @@ -880,6 +883,7 @@ public: auto *LAA = &getAnalysis<LoopAccessLegacyAnalysis>(); auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); + auto *ORE = &getAnalysis<OptimizationRemarkEmitter>(); // Build up a worklist of inner-loops to vectorize. This is necessary as the // act of distributing a loop creates new loops and can invalidate iterators @@ -895,7 +899,7 @@ public: // Now walk the identified inner loops. bool Changed = false; for (Loop *L : Worklist) { - LoopDistributeForLoop LDL(L, &F, LI, DT, SE); + LoopDistributeForLoop LDL(L, &F, LI, DT, SE, ORE); // If distribution was forced for the specific loop to be // enabled/disabled, follow that. Otherwise use the global flag. @@ -914,6 +918,7 @@ public: AU.addRequired<LoopAccessLegacyAnalysis>(); AU.addRequired<DominatorTreeWrapperPass>(); AU.addPreserved<DominatorTreeWrapperPass>(); + AU.addRequired<OptimizationRemarkEmitter>(); } static char ID; @@ -933,6 +938,7 @@ INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) +INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitter) INITIALIZE_PASS_END(LoopDistribute, LDIST_NAME, ldist_name, false, false) namespace llvm { |

