Index: lib/Transforms/IPO/SampleProfile.cpp =================================================================== --- lib/Transforms/IPO/SampleProfile.cpp +++ lib/Transforms/IPO/SampleProfile.cpp @@ -29,6 +29,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfo.h" @@ -159,25 +160,27 @@ protected: bool runOnFunction(Function &F); unsigned getFunctionLoc(Function &F); - bool emitAnnotations(Function &F); - ErrorOr getInstWeight(const Instruction &I); - ErrorOr getBlockWeight(const BasicBlock *BB); + bool emitAnnotations(Function &F, OptimizationRemarkEmitter &ORE); + ErrorOr getInstWeight(const Instruction &I, + OptimizationRemarkEmitter &ORE); + ErrorOr getBlockWeight(const BasicBlock *BB, + OptimizationRemarkEmitter &ORE); const FunctionSamples *findCalleeFunctionSamples(const Instruction &I) const; std::vector findIndirectCallFunctionSamples(const Instruction &I) const; const FunctionSamples *findFunctionSamples(const Instruction &I) const; - bool inlineHotFunctions(Function &F, - DenseSet &ImportGUIDs); + bool inlineHotFunctions(Function &F, DenseSet &ImportGUIDs, + OptimizationRemarkEmitter &ORE); void printEdgeWeight(raw_ostream &OS, Edge E); void printBlockWeight(raw_ostream &OS, const BasicBlock *BB) const; void printBlockEquivalence(raw_ostream &OS, const BasicBlock *BB); - bool computeBlockWeights(Function &F); + bool computeBlockWeights(Function &F, OptimizationRemarkEmitter &ORE); void findEquivalenceClasses(Function &F); template void findEquivalencesFor(BasicBlock *BB1, ArrayRef Descendants, DominatorTreeBase *DomTree); - void propagateWeights(Function &F); + void propagateWeights(Function &F, OptimizationRemarkEmitter &ORE); uint64_t visitEdge(Edge E, unsigned *NumUnknownEdges, Edge *UnknownEdge); void buildEdges(Function &F); bool propagateThroughEdges(Function &F, bool UpdateBlockCount); @@ -467,7 +470,9 @@ /// \param Inst Instruction to query. /// /// \returns the weight of \p Inst. -ErrorOr SampleProfileLoader::getInstWeight(const Instruction &Inst) { +ErrorOr +SampleProfileLoader::getInstWeight(const Instruction &Inst, + OptimizationRemarkEmitter &ORE) { const DebugLoc &DLoc = Inst.getDebugLoc(); if (!DLoc) return std::error_code(); @@ -497,13 +502,11 @@ bool FirstMark = CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator, R.get()); if (FirstMark) { - const Function *F = Inst.getParent()->getParent(); - LLVMContext &Ctx = F->getContext(); - emitOptimizationRemark( - Ctx, DEBUG_TYPE, *F, DLoc, - Twine("Applied ") + Twine(*R) + - " samples from profile (offset: " + Twine(LineOffset) + - ((Discriminator) ? Twine(".") + Twine(Discriminator) : "") + ")"); + ORE.emit(OptimizationRemark(DEBUG_TYPE, "AppliedSamples", &Inst) + << "Applied " << Twine(*R).str() + << " samples from profile (offset: " << Twine(LineOffset).str() + << ((Discriminator) ? "." + Twine(Discriminator).str() : "") + + ")"); } DEBUG(dbgs() << " " << DLoc.getLine() << "." << DIL->getBaseDiscriminator() << ":" << Inst @@ -522,11 +525,13 @@ /// \param BB The basic block to query. /// /// \returns the weight for \p BB. -ErrorOr SampleProfileLoader::getBlockWeight(const BasicBlock *BB) { +ErrorOr +SampleProfileLoader::getBlockWeight(const BasicBlock *BB, + OptimizationRemarkEmitter &ORE) { uint64_t Max = 0; bool HasWeight = false; for (auto &I : BB->getInstList()) { - const ErrorOr &R = getInstWeight(I); + const ErrorOr &R = getInstWeight(I, ORE); if (R) { Max = std::max(Max, R.get()); HasWeight = true; @@ -541,11 +546,12 @@ /// the weights of every basic block in the CFG. /// /// \param F The function to query. -bool SampleProfileLoader::computeBlockWeights(Function &F) { +bool SampleProfileLoader::computeBlockWeights(Function &F, + OptimizationRemarkEmitter &ORE) { bool Changed = false; DEBUG(dbgs() << "Block weights\n"); for (const auto &BB : F) { - ErrorOr Weight = getBlockWeight(&BB); + ErrorOr Weight = getBlockWeight(&BB, ORE); if (Weight) { BlockWeights[&BB] = Weight.get(); VisitedBlocks.insert(&BB); @@ -666,12 +672,14 @@ /// /// \returns True if there is any inline happened. bool SampleProfileLoader::inlineHotFunctions( - Function &F, DenseSet &ImportGUIDs) { + Function &F, DenseSet &ImportGUIDs, + OptimizationRemarkEmitter &ORE) { DenseSet PromotedInsns; bool Changed = false; - LLVMContext &Ctx = F.getContext(); - std::function GetAssumptionCache = [&]( - Function &F) -> AssumptionCache & { return ACT->getAssumptionCache(F); }; + std::function GetAssumptionCache = + [&](Function &F) -> AssumptionCache & { + return ACT->getAssumptionCache(F); + }; while (true) { bool LocalChanged = false; SmallVector CIS; @@ -737,12 +745,12 @@ continue; } DebugLoc DLoc = I->getDebugLoc(); + BasicBlock *BB = I->getParent(); if (InlineFunction(CallSite(DI), IFI)) { LocalChanged = true; - emitOptimizationRemark(Ctx, DEBUG_TYPE, F, DLoc, - Twine("inlined hot callee '") + - CalledFunction->getName() + "' into '" + - F.getName() + "'"); + ORE.emit(OptimizationRemark(DEBUG_TYPE, "HotInline", DLoc, BB) + << "inlined hot callee '" << CalledFunction->getName().str() + << "' into '" << F.getName() << "'"); } } if (LocalChanged) { @@ -1115,7 +1123,8 @@ /// known, the weight for that edge is set to the weight of the block /// minus the weight of the other incoming edges to that block (if /// known). -void SampleProfileLoader::propagateWeights(Function &F) { +void SampleProfileLoader::propagateWeights(Function &F, + OptimizationRemarkEmitter &ORE) { bool Changed = true; unsigned I = 0; @@ -1213,7 +1222,7 @@ << ".\n"); SmallVector Weights; uint32_t MaxWeight = 0; - DebugLoc MaxDestLoc; + Instruction *MaxDestInstr; for (unsigned I = 0; I < TI->getNumSuccessors(); ++I) { BasicBlock *Succ = TI->getSuccessor(I); Edge E = std::make_pair(BB, Succ); @@ -1232,7 +1241,7 @@ if (Weight != 0) { if (Weight > MaxWeight) { MaxWeight = Weight; - MaxDestLoc = Succ->getFirstNonPHIOrDbgOrLifetime()->getDebugLoc(); + MaxDestInstr = Succ->getFirstNonPHIOrDbgOrLifetime(); } } } @@ -1247,13 +1256,13 @@ DEBUG(dbgs() << "SUCCESS. Found non-zero weights.\n"); TI->setMetadata(llvm::LLVMContext::MD_prof, MDB.createBranchWeights(Weights)); - emitOptimizationRemark( - Ctx, DEBUG_TYPE, F, MaxDestLoc, - Twine("most popular destination for conditional branches at ") + - ((BranchLoc) ? Twine(BranchLoc->getFilename() + ":" + - Twine(BranchLoc.getLine()) + ":" + - Twine(BranchLoc.getCol())) - : Twine(""))); + ORE.emit(OptimizationRemark(DEBUG_TYPE, "PopularDest", MaxDestInstr) + << "most popular destination for conditional branches at " + << ((BranchLoc) ? Twine(BranchLoc->getFilename() + ":" + + Twine(BranchLoc.getLine()) + ":" + + Twine(BranchLoc.getCol())) + .str() + : Twine("").str())); } else { DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n"); } @@ -1344,7 +1353,8 @@ /// \param F The function to query. /// /// \returns true if \p F was modified. Returns false, otherwise. -bool SampleProfileLoader::emitAnnotations(Function &F) { +bool SampleProfileLoader::emitAnnotations(Function &F, + OptimizationRemarkEmitter &ORE) { bool Changed = false; if (getFunctionLoc(F) == 0) @@ -1354,10 +1364,10 @@ << ": " << getFunctionLoc(F) << "\n"); DenseSet ImportGUIDs; - Changed |= inlineHotFunctions(F, ImportGUIDs); + Changed |= inlineHotFunctions(F, ImportGUIDs, ORE); // Compute basic block weights. - Changed |= computeBlockWeights(F); + Changed |= computeBlockWeights(F, ORE); if (Changed) { // Add an entry count to the function using the samples gathered at the @@ -1373,7 +1383,7 @@ findEquivalenceClasses(F); // Propagate weights to all edges. - propagateWeights(F); + propagateWeights(F, ORE); } // If coverage checking was requested, compute it now. @@ -1479,18 +1489,19 @@ } bool SampleProfileLoader::runOnFunction(Function &F) { + OptimizationRemarkEmitter ORE(&F); F.setEntryCount(0); Samples = Reader->getSamplesFor(F); if (Samples && !Samples->empty()) - return emitAnnotations(F); + return emitAnnotations(F, ORE); return false; } PreservedAnalyses SampleProfileLoaderPass::run(Module &M, ModuleAnalysisManager &AM) { - SampleProfileLoader SampleLoader( - ProfileFileName.empty() ? SampleProfileFile : ProfileFileName); + SampleProfileLoader SampleLoader(ProfileFileName.empty() ? SampleProfileFile + : ProfileFileName); SampleLoader.doInitialization(M); Index: test/Transforms/SampleProfile/remarks.ll =================================================================== --- test/Transforms/SampleProfile/remarks.ll +++ test/Transforms/SampleProfile/remarks.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile 2>&1 | FileCheck %s +; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile -pass-remarks-output=%t.opt.yaml 2>&1 | FileCheck %s ; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/remarks.prof -S -pass-remarks=sample-profile 2>&1 | FileCheck %s -; +; RUN: cat %t.opt.yaml | FileCheck %s -check-prefix=YAML ; Original test case. ; ; 1 #include @@ -27,6 +27,17 @@ ; The predicate almost always chooses the 'else' branch. ; CHECK: remark: remarks.cc:9:15: most popular destination for conditional branches at remarks.cc:6:9 +; Checking to see if YAML file is generated and contains remarks +; YAML: --- !Passed +; YAML: Pass: sample-profile +; YAML: Name: HotInline +; YAML: --- !Passed +; YAML: Pass: sample-profile +; YAML: Name: AppliedSamples +; YAML: --- !Passed +; YAML: Pass: sample-profile +; YAML: Name: PopularDest + ; Function Attrs: nounwind uwtable define i64 @_Z3foov() #0 !dbg !4 { entry: