From: Diego Novillo Date: Tue, 25 Aug 2015 15:25:11 +0000 (+0000) Subject: Convert SampleProfile pass into a Module pass. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=eb6eb153d9dc22bf006f260d3975babe075da5f2;p=oota-llvm.git Convert SampleProfile pass into a Module pass. Eventually, we will need sample profiles to be incorporated into the inliner's cost models. To do this, we need the sample profile pass to be a module pass. This patch makes no functional changes beyond the mechanical adjustments needed to run SampleProfile as a module pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245940 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 2ea47301bb4..96ddc6eceed 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -16,6 +16,7 @@ #define LLVM_TRANSFORMS_IPO_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" namespace llvm { @@ -209,6 +210,12 @@ ModulePass *createBarrierNoopPass(); /// to bitsets. ModulePass *createLowerBitSetsPass(); +//===----------------------------------------------------------------------===// +// SampleProfilePass - Loads sample profile data from disk and generates +// IR metadata to reflect the profile. +ModulePass *createSampleProfileLoaderPass(); +ModulePass *createSampleProfileLoaderPass(StringRef Name); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 1d6d10f42a7..0a37d838a93 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -406,13 +406,6 @@ FunctionPass *createLowerExpectIntrinsicPass(); // FunctionPass *createPartiallyInlineLibCallsPass(); -//===----------------------------------------------------------------------===// -// -// SampleProfilePass - Loads sample profile data from disk and generates -// IR metadata to reflect the profile. -FunctionPass *createSampleProfileLoaderPass(); -FunctionPass *createSampleProfileLoaderPass(StringRef Name); - //===----------------------------------------------------------------------===// // // ScalarizerPass - Converts vector operations into scalar operations diff --git a/lib/Transforms/IPO/CMakeLists.txt b/lib/Transforms/IPO/CMakeLists.txt index 336dac45e13..8c777548137 100644 --- a/lib/Transforms/IPO/CMakeLists.txt +++ b/lib/Transforms/IPO/CMakeLists.txt @@ -20,6 +20,7 @@ add_llvm_library(LLVMipo PartialInlining.cpp PassManagerBuilder.cpp PruneEH.cpp + SampleProfile.cpp StripDeadPrototypes.cpp StripSymbols.cpp diff --git a/lib/Transforms/IPO/IPO.cpp b/lib/Transforms/IPO/IPO.cpp index 50f56b0f2af..6efa1193dc0 100644 --- a/lib/Transforms/IPO/IPO.cpp +++ b/lib/Transforms/IPO/IPO.cpp @@ -47,6 +47,7 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeStripNonDebugSymbolsPass(Registry); initializeBarrierNoopPass(Registry); initializeEliminateAvailableExternallyPass(Registry); + initializeSampleProfileLoaderPass(Registry); } void LLVMInitializeIPO(LLVMPassRegistryRef R) { diff --git a/lib/Transforms/IPO/SampleProfile.cpp b/lib/Transforms/IPO/SampleProfile.cpp new file mode 100644 index 00000000000..f6602fda430 --- /dev/null +++ b/lib/Transforms/IPO/SampleProfile.cpp @@ -0,0 +1,794 @@ +//===- SampleProfile.cpp - Incorporate sample profiles into the IR --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SampleProfileLoader transformation. This pass +// reads a profile file generated by a sampling profiler (e.g. Linux Perf - +// http://perf.wiki.kernel.org/) and generates IR metadata to reflect the +// profile information in the given profile. +// +// This pass generates branch weight annotations on the IR: +// +// - prof: Represents branch weights. This annotation is added to branches +// to indicate the weights of each edge coming out of the branch. +// The weight of each edge is the weight of the target block for +// that edge. The weight of a block B is computed as the maximum +// number of samples found in B. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO.h" +#include + +using namespace llvm; +using namespace sampleprof; + +#define DEBUG_TYPE "sample-profile" + +// Command line option to specify the file to read samples from. This is +// mainly used for debugging. +static cl::opt SampleProfileFile( + "sample-profile-file", cl::init(""), cl::value_desc("filename"), + cl::desc("Profile file loaded by -sample-profile"), cl::Hidden); +static cl::opt SampleProfileMaxPropagateIterations( + "sample-profile-max-propagate-iterations", cl::init(100), + cl::desc("Maximum number of iterations to go through when propagating " + "sample block/edge weights through the CFG.")); + +namespace { +typedef DenseMap BlockWeightMap; +typedef DenseMap EquivalenceClassMap; +typedef std::pair Edge; +typedef DenseMap EdgeWeightMap; +typedef DenseMap> BlockEdgeMap; + +/// \brief Sample profile pass. +/// +/// This pass reads profile data from the file specified by +/// -sample-profile-file and annotates every affected function with the +/// profile information found in that file. +class SampleProfileLoader : public ModulePass { +public: + // Class identification, replacement for typeinfo + static char ID; + + SampleProfileLoader(StringRef Name = SampleProfileFile) + : ModulePass(ID), DT(nullptr), PDT(nullptr), LI(nullptr), + Ctx(nullptr), Reader(), Samples(nullptr), Filename(Name), + ProfileIsValid(false) { + initializeSampleProfileLoaderPass(*PassRegistry::getPassRegistry()); + } + + bool doInitialization(Module &M) override; + + void dump() { Reader->dump(); } + + const char *getPassName() const override { return "Sample profile pass"; } + + bool runOnModule(Module &M) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + + AU.addRequired(); + AU.addPreserved(); + + AU.addRequired(); + AU.addPreserved(); + + AU.addRequired(); + AU.addPreserved(); + } + +protected: + bool runOnFunction(Function &F); + unsigned getFunctionLoc(Function &F); + bool emitAnnotations(Function &F); + unsigned getInstWeight(Instruction &I); + unsigned getBlockWeight(BasicBlock *BB); + void printEdgeWeight(raw_ostream &OS, Edge E); + void printBlockWeight(raw_ostream &OS, BasicBlock *BB); + void printBlockEquivalence(raw_ostream &OS, BasicBlock *BB); + bool computeBlockWeights(Function &F); + void findEquivalenceClasses(Function &F); + void findEquivalencesFor(BasicBlock *BB1, + SmallVector Descendants, + DominatorTreeBase *DomTree); + void propagateWeights(Function &F); + unsigned visitEdge(Edge E, unsigned *NumUnknownEdges, Edge *UnknownEdge); + void buildEdges(Function &F); + bool propagateThroughEdges(Function &F); + + /// \brief Line number for the function header. Used to compute absolute + /// line numbers from the relative line numbers found in the profile. + unsigned HeaderLineno; + + /// \brief Map basic blocks to their computed weights. + /// + /// The weight of a basic block is defined to be the maximum + /// of all the instruction weights in that block. + BlockWeightMap BlockWeights; + + /// \brief Map edges to their computed weights. + /// + /// Edge weights are computed by propagating basic block weights in + /// SampleProfile::propagateWeights. + EdgeWeightMap EdgeWeights; + + /// \brief Set of visited blocks during propagation. + SmallPtrSet VisitedBlocks; + + /// \brief Set of visited edges during propagation. + SmallSet VisitedEdges; + + /// \brief Equivalence classes for block weights. + /// + /// Two blocks BB1 and BB2 are in the same equivalence class if they + /// dominate and post-dominate each other, and they are in the same loop + /// nest. When this happens, the two blocks are guaranteed to execute + /// the same number of times. + EquivalenceClassMap EquivalenceClass; + + /// \brief Dominance, post-dominance and loop information. + DominatorTree *DT; + PostDominatorTree *PDT; + LoopInfo *LI; + + /// \brief Predecessors for each basic block in the CFG. + BlockEdgeMap Predecessors; + + /// \brief Successors for each basic block in the CFG. + BlockEdgeMap Successors; + + /// \brief LLVM context holding the debug data we need. + LLVMContext *Ctx; + + /// \brief Profile reader object. + std::unique_ptr Reader; + + /// \brief Samples collected for the body of this function. + FunctionSamples *Samples; + + /// \brief Name of the profile file to load. + StringRef Filename; + + /// \brief Flag indicating whether the profile input loaded successfully. + bool ProfileIsValid; +}; +} + +/// \brief Print the weight of edge \p E on stream \p OS. +/// +/// \param OS Stream to emit the output to. +/// \param E Edge to print. +void SampleProfileLoader::printEdgeWeight(raw_ostream &OS, Edge E) { + OS << "weight[" << E.first->getName() << "->" << E.second->getName() + << "]: " << EdgeWeights[E] << "\n"; +} + +/// \brief Print the equivalence class of block \p BB on stream \p OS. +/// +/// \param OS Stream to emit the output to. +/// \param BB Block to print. +void SampleProfileLoader::printBlockEquivalence(raw_ostream &OS, + BasicBlock *BB) { + BasicBlock *Equiv = EquivalenceClass[BB]; + OS << "equivalence[" << BB->getName() + << "]: " << ((Equiv) ? EquivalenceClass[BB]->getName() : "NONE") << "\n"; +} + +/// \brief Print the weight of block \p BB on stream \p OS. +/// +/// \param OS Stream to emit the output to. +/// \param BB Block to print. +void SampleProfileLoader::printBlockWeight(raw_ostream &OS, BasicBlock *BB) { + OS << "weight[" << BB->getName() << "]: " << BlockWeights[BB] << "\n"; +} + +/// \brief Get the weight for an instruction. +/// +/// The "weight" of an instruction \p Inst is the number of samples +/// collected on that instruction at runtime. To retrieve it, we +/// need to compute the line number of \p Inst relative to the start of its +/// function. We use HeaderLineno to compute the offset. We then +/// look up the samples collected for \p Inst using BodySamples. +/// +/// \param Inst Instruction to query. +/// +/// \returns The profiled weight of I. +unsigned SampleProfileLoader::getInstWeight(Instruction &Inst) { + DebugLoc DLoc = Inst.getDebugLoc(); + if (!DLoc) + return 0; + + unsigned Lineno = DLoc.getLine(); + if (Lineno < HeaderLineno) + return 0; + + const DILocation *DIL = DLoc; + int LOffset = Lineno - HeaderLineno; + unsigned Discriminator = DIL->getDiscriminator(); + unsigned Weight = Samples->samplesAt(LOffset, Discriminator); + DEBUG(dbgs() << " " << Lineno << "." << Discriminator << ":" << Inst + << " (line offset: " << LOffset << "." << Discriminator + << " - weight: " << Weight << ")\n"); + return Weight; +} + +/// \brief Compute the weight of a basic block. +/// +/// The weight of basic block \p BB is the maximum weight of all the +/// instructions in BB. The weight of \p BB is computed and cached in +/// the BlockWeights map. +/// +/// \param BB The basic block to query. +/// +/// \returns The computed weight of BB. +unsigned SampleProfileLoader::getBlockWeight(BasicBlock *BB) { + // If we've computed BB's weight before, return it. + std::pair Entry = + BlockWeights.insert(std::make_pair(BB, 0)); + if (!Entry.second) + return Entry.first->second; + + // Otherwise, compute and cache BB's weight. + unsigned Weight = 0; + for (auto &I : BB->getInstList()) { + unsigned InstWeight = getInstWeight(I); + if (InstWeight > Weight) + Weight = InstWeight; + } + Entry.first->second = Weight; + return Weight; +} + +/// \brief Compute and store the weights of every basic block. +/// +/// This populates the BlockWeights map by computing +/// the weights of every basic block in the CFG. +/// +/// \param F The function to query. +bool SampleProfileLoader::computeBlockWeights(Function &F) { + bool Changed = false; + DEBUG(dbgs() << "Block weights\n"); + for (auto &BB : F) { + unsigned Weight = getBlockWeight(&BB); + Changed |= (Weight > 0); + DEBUG(printBlockWeight(dbgs(), &BB)); + } + + return Changed; +} + +/// \brief Find equivalence classes for the given block. +/// +/// This finds all the blocks that are guaranteed to execute the same +/// number of times as \p BB1. To do this, it traverses all the +/// descendants of \p BB1 in the dominator or post-dominator tree. +/// +/// A block BB2 will be in the same equivalence class as \p BB1 if +/// the following holds: +/// +/// 1- \p BB1 is a descendant of BB2 in the opposite tree. So, if BB2 +/// is a descendant of \p BB1 in the dominator tree, then BB2 should +/// dominate BB1 in the post-dominator tree. +/// +/// 2- Both BB2 and \p BB1 must be in the same loop. +/// +/// For every block BB2 that meets those two requirements, we set BB2's +/// equivalence class to \p BB1. +/// +/// \param BB1 Block to check. +/// \param Descendants Descendants of \p BB1 in either the dom or pdom tree. +/// \param DomTree Opposite dominator tree. If \p Descendants is filled +/// with blocks from \p BB1's dominator tree, then +/// this is the post-dominator tree, and vice versa. +void SampleProfileLoader::findEquivalencesFor( + BasicBlock *BB1, SmallVector Descendants, + DominatorTreeBase *DomTree) { + for (auto *BB2 : Descendants) { + bool IsDomParent = DomTree->dominates(BB2, BB1); + bool IsInSameLoop = LI->getLoopFor(BB1) == LI->getLoopFor(BB2); + if (BB1 != BB2 && VisitedBlocks.insert(BB2).second && IsDomParent && + IsInSameLoop) { + EquivalenceClass[BB2] = BB1; + + // If BB2 is heavier than BB1, make BB2 have the same weight + // as BB1. + // + // Note that we don't worry about the opposite situation here + // (when BB2 is lighter than BB1). We will deal with this + // during the propagation phase. Right now, we just want to + // make sure that BB1 has the largest weight of all the + // members of its equivalence set. + unsigned &BB1Weight = BlockWeights[BB1]; + unsigned &BB2Weight = BlockWeights[BB2]; + BB1Weight = std::max(BB1Weight, BB2Weight); + } + } +} + +/// \brief Find equivalence classes. +/// +/// Since samples may be missing from blocks, we can fill in the gaps by setting +/// the weights of all the blocks in the same equivalence class to the same +/// weight. To compute the concept of equivalence, we use dominance and loop +/// information. Two blocks B1 and B2 are in the same equivalence class if B1 +/// dominates B2, B2 post-dominates B1 and both are in the same loop. +/// +/// \param F The function to query. +void SampleProfileLoader::findEquivalenceClasses(Function &F) { + SmallVector DominatedBBs; + DEBUG(dbgs() << "\nBlock equivalence classes\n"); + // Find equivalence sets based on dominance and post-dominance information. + for (auto &BB : F) { + BasicBlock *BB1 = &BB; + + // Compute BB1's equivalence class once. + if (EquivalenceClass.count(BB1)) { + DEBUG(printBlockEquivalence(dbgs(), BB1)); + continue; + } + + // By default, blocks are in their own equivalence class. + EquivalenceClass[BB1] = BB1; + + // Traverse all the blocks dominated by BB1. We are looking for + // every basic block BB2 such that: + // + // 1- BB1 dominates BB2. + // 2- BB2 post-dominates BB1. + // 3- BB1 and BB2 are in the same loop nest. + // + // If all those conditions hold, it means that BB2 is executed + // as many times as BB1, so they are placed in the same equivalence + // class by making BB2's equivalence class be BB1. + DominatedBBs.clear(); + DT->getDescendants(BB1, DominatedBBs); + findEquivalencesFor(BB1, DominatedBBs, PDT->DT); + + // Repeat the same logic for all the blocks post-dominated by BB1. + // We are looking for every basic block BB2 such that: + // + // 1- BB1 post-dominates BB2. + // 2- BB2 dominates BB1. + // 3- BB1 and BB2 are in the same loop nest. + // + // If all those conditions hold, BB2's equivalence class is BB1. + DominatedBBs.clear(); + PDT->getDescendants(BB1, DominatedBBs); + findEquivalencesFor(BB1, DominatedBBs, DT); + + DEBUG(printBlockEquivalence(dbgs(), BB1)); + } + + // Assign weights to equivalence classes. + // + // All the basic blocks in the same equivalence class will execute + // the same number of times. Since we know that the head block in + // each equivalence class has the largest weight, assign that weight + // to all the blocks in that equivalence class. + DEBUG(dbgs() << "\nAssign the same weight to all blocks in the same class\n"); + for (auto &BI : F) { + BasicBlock *BB = &BI; + BasicBlock *EquivBB = EquivalenceClass[BB]; + if (BB != EquivBB) + BlockWeights[BB] = BlockWeights[EquivBB]; + DEBUG(printBlockWeight(dbgs(), BB)); + } +} + +/// \brief Visit the given edge to decide if it has a valid weight. +/// +/// If \p E has not been visited before, we copy to \p UnknownEdge +/// and increment the count of unknown edges. +/// +/// \param E Edge to visit. +/// \param NumUnknownEdges Current number of unknown edges. +/// \param UnknownEdge Set if E has not been visited before. +/// +/// \returns E's weight, if known. Otherwise, return 0. +unsigned SampleProfileLoader::visitEdge(Edge E, unsigned *NumUnknownEdges, + Edge *UnknownEdge) { + if (!VisitedEdges.count(E)) { + (*NumUnknownEdges)++; + *UnknownEdge = E; + return 0; + } + + return EdgeWeights[E]; +} + +/// \brief Propagate weights through incoming/outgoing edges. +/// +/// If the weight of a basic block is known, and there is only one edge +/// with an unknown weight, we can calculate the weight of that edge. +/// +/// Similarly, if all the edges have a known count, we can calculate the +/// count of the basic block, if needed. +/// +/// \param F Function to process. +/// +/// \returns True if new weights were assigned to edges or blocks. +bool SampleProfileLoader::propagateThroughEdges(Function &F) { + bool Changed = false; + DEBUG(dbgs() << "\nPropagation through edges\n"); + for (auto &BI : F) { + BasicBlock *BB = &BI; + + // Visit all the predecessor and successor edges to determine + // which ones have a weight assigned already. Note that it doesn't + // matter that we only keep track of a single unknown edge. The + // only case we are interested in handling is when only a single + // edge is unknown (see setEdgeOrBlockWeight). + for (unsigned i = 0; i < 2; i++) { + unsigned TotalWeight = 0; + unsigned NumUnknownEdges = 0; + Edge UnknownEdge, SelfReferentialEdge; + + if (i == 0) { + // First, visit all predecessor edges. + for (auto *Pred : Predecessors[BB]) { + Edge E = std::make_pair(Pred, BB); + TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge); + if (E.first == E.second) + SelfReferentialEdge = E; + } + } else { + // On the second round, visit all successor edges. + for (auto *Succ : Successors[BB]) { + Edge E = std::make_pair(BB, Succ); + TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge); + } + } + + // After visiting all the edges, there are three cases that we + // can handle immediately: + // + // - All the edge weights are known (i.e., NumUnknownEdges == 0). + // In this case, we simply check that the sum of all the edges + // is the same as BB's weight. If not, we change BB's weight + // to match. Additionally, if BB had not been visited before, + // we mark it visited. + // + // - Only one edge is unknown and BB has already been visited. + // In this case, we can compute the weight of the edge by + // subtracting the total block weight from all the known + // edge weights. If the edges weight more than BB, then the + // edge of the last remaining edge is set to zero. + // + // - There exists a self-referential edge and the weight of BB is + // known. In this case, this edge can be based on BB's weight. + // We add up all the other known edges and set the weight on + // the self-referential edge as we did in the previous case. + // + // In any other case, we must continue iterating. Eventually, + // all edges will get a weight, or iteration will stop when + // it reaches SampleProfileMaxPropagateIterations. + if (NumUnknownEdges <= 1) { + unsigned &BBWeight = BlockWeights[BB]; + if (NumUnknownEdges == 0) { + // If we already know the weight of all edges, the weight of the + // basic block can be computed. It should be no larger than the sum + // of all edge weights. + if (TotalWeight > BBWeight) { + BBWeight = TotalWeight; + Changed = true; + DEBUG(dbgs() << "All edge weights for " << BB->getName() + << " known. Set weight for block: "; + printBlockWeight(dbgs(), BB);); + } + if (VisitedBlocks.insert(BB).second) + Changed = true; + } else if (NumUnknownEdges == 1 && VisitedBlocks.count(BB)) { + // If there is a single unknown edge and the block has been + // visited, then we can compute E's weight. + if (BBWeight >= TotalWeight) + EdgeWeights[UnknownEdge] = BBWeight - TotalWeight; + else + EdgeWeights[UnknownEdge] = 0; + VisitedEdges.insert(UnknownEdge); + Changed = true; + DEBUG(dbgs() << "Set weight for edge: "; + printEdgeWeight(dbgs(), UnknownEdge)); + } + } else if (SelfReferentialEdge.first && VisitedBlocks.count(BB)) { + unsigned &BBWeight = BlockWeights[BB]; + // We have a self-referential edge and the weight of BB is known. + if (BBWeight >= TotalWeight) + EdgeWeights[SelfReferentialEdge] = BBWeight - TotalWeight; + else + EdgeWeights[SelfReferentialEdge] = 0; + VisitedEdges.insert(SelfReferentialEdge); + Changed = true; + DEBUG(dbgs() << "Set self-referential edge weight to: "; + printEdgeWeight(dbgs(), SelfReferentialEdge)); + } + } + } + + return Changed; +} + +/// \brief Build in/out edge lists for each basic block in the CFG. +/// +/// We are interested in unique edges. If a block B1 has multiple +/// edges to another block B2, we only add a single B1->B2 edge. +void SampleProfileLoader::buildEdges(Function &F) { + for (auto &BI : F) { + BasicBlock *B1 = &BI; + + // Add predecessors for B1. + SmallPtrSet Visited; + if (!Predecessors[B1].empty()) + llvm_unreachable("Found a stale predecessors list in a basic block."); + for (pred_iterator PI = pred_begin(B1), PE = pred_end(B1); PI != PE; ++PI) { + BasicBlock *B2 = *PI; + if (Visited.insert(B2).second) + Predecessors[B1].push_back(B2); + } + + // Add successors for B1. + Visited.clear(); + if (!Successors[B1].empty()) + llvm_unreachable("Found a stale successors list in a basic block."); + for (succ_iterator SI = succ_begin(B1), SE = succ_end(B1); SI != SE; ++SI) { + BasicBlock *B2 = *SI; + if (Visited.insert(B2).second) + Successors[B1].push_back(B2); + } + } +} + +/// \brief Propagate weights into edges +/// +/// The following rules are applied to every block BB in the CFG: +/// +/// - If BB has a single predecessor/successor, then the weight +/// of that edge is the weight of the block. +/// +/// - If all incoming or outgoing edges are known except one, and the +/// weight of the block is already known, the weight of the unknown +/// edge will be the weight of the block minus the sum of all the known +/// edges. If the sum of all the known edges is larger than BB's weight, +/// we set the unknown edge weight to zero. +/// +/// - If there is a self-referential edge, and the weight of the block is +/// 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) { + bool Changed = true; + unsigned i = 0; + + // Add an entry count to the function using the samples gathered + // at the function entry. + F.setEntryCount(Samples->getHeadSamples()); + + // Before propagation starts, build, for each block, a list of + // unique predecessors and successors. This is necessary to handle + // identical edges in multiway branches. Since we visit all blocks and all + // edges of the CFG, it is cleaner to build these lists once at the start + // of the pass. + buildEdges(F); + + // Propagate until we converge or we go past the iteration limit. + while (Changed && i++ < SampleProfileMaxPropagateIterations) { + Changed = propagateThroughEdges(F); + } + + // Generate MD_prof metadata for every branch instruction using the + // edge weights computed during propagation. + DEBUG(dbgs() << "\nPropagation complete. Setting branch weights\n"); + MDBuilder MDB(F.getContext()); + for (auto &BI : F) { + BasicBlock *BB = &BI; + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumSuccessors() == 1) + continue; + if (!isa(TI) && !isa(TI)) + continue; + + DEBUG(dbgs() << "\nGetting weights for branch at line " + << TI->getDebugLoc().getLine() << ".\n"); + SmallVector Weights; + bool AllWeightsZero = true; + for (unsigned I = 0; I < TI->getNumSuccessors(); ++I) { + BasicBlock *Succ = TI->getSuccessor(I); + Edge E = std::make_pair(BB, Succ); + unsigned Weight = EdgeWeights[E]; + DEBUG(dbgs() << "\t"; printEdgeWeight(dbgs(), E)); + Weights.push_back(Weight); + if (Weight != 0) + AllWeightsZero = false; + } + + // Only set weights if there is at least one non-zero weight. + // In any other case, let the analyzer set weights. + if (!AllWeightsZero) { + DEBUG(dbgs() << "SUCCESS. Found non-zero weights.\n"); + TI->setMetadata(llvm::LLVMContext::MD_prof, + MDB.createBranchWeights(Weights)); + } else { + DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n"); + } + } +} + +/// \brief Get the line number for the function header. +/// +/// This looks up function \p F in the current compilation unit and +/// retrieves the line number where the function is defined. This is +/// line 0 for all the samples read from the profile file. Every line +/// number is relative to this line. +/// +/// \param F Function object to query. +/// +/// \returns the line number where \p F is defined. If it returns 0, +/// it means that there is no debug information available for \p F. +unsigned SampleProfileLoader::getFunctionLoc(Function &F) { + if (DISubprogram *S = getDISubprogram(&F)) + return S->getLine(); + + // If could not find the start of \p F, emit a diagnostic to inform the user + // about the missed opportunity. + F.getContext().diagnose(DiagnosticInfoSampleProfile( + "No debug information found in function " + F.getName() + + ": Function profile not used", + DS_Warning)); + return 0; +} + +/// \brief Generate branch weight metadata for all branches in \p F. +/// +/// Branch weights are computed out of instruction samples using a +/// propagation heuristic. Propagation proceeds in 3 phases: +/// +/// 1- Assignment of block weights. All the basic blocks in the function +/// are initial assigned the same weight as their most frequently +/// executed instruction. +/// +/// 2- Creation of equivalence classes. Since samples may be missing from +/// blocks, we can fill in the gaps by setting the weights of all the +/// blocks in the same equivalence class to the same weight. To compute +/// the concept of equivalence, we use dominance and loop information. +/// Two blocks B1 and B2 are in the same equivalence class if B1 +/// dominates B2, B2 post-dominates B1 and both are in the same loop. +/// +/// 3- Propagation of block weights into edges. This uses a simple +/// propagation heuristic. The following rules are applied to every +/// block BB in the CFG: +/// +/// - If BB has a single predecessor/successor, then the weight +/// of that edge is the weight of the block. +/// +/// - If all the edges are known except one, and the weight of the +/// block is already known, the weight of the unknown edge will +/// be the weight of the block minus the sum of all the known +/// edges. If the sum of all the known edges is larger than BB's weight, +/// we set the unknown edge weight to zero. +/// +/// - If there is a self-referential edge, and the weight of the block is +/// 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). +/// +/// Since this propagation is not guaranteed to finalize for every CFG, we +/// only allow it to proceed for a limited number of iterations (controlled +/// by -sample-profile-max-propagate-iterations). +/// +/// FIXME: Try to replace this propagation heuristic with a scheme +/// that is guaranteed to finalize. A work-list approach similar to +/// the standard value propagation algorithm used by SSA-CCP might +/// work here. +/// +/// Once all the branch weights are computed, we emit the MD_prof +/// metadata on BB using the computed values for each of its branches. +/// +/// \param F The function to query. +/// +/// \returns true if \p F was modified. Returns false, otherwise. +bool SampleProfileLoader::emitAnnotations(Function &F) { + bool Changed = false; + + // Initialize invariants used during computation and propagation. + HeaderLineno = getFunctionLoc(F); + if (HeaderLineno == 0) + return false; + + DEBUG(dbgs() << "Line number for the first instruction in " << F.getName() + << ": " << HeaderLineno << "\n"); + + // Compute basic block weights. + Changed |= computeBlockWeights(F); + + if (Changed) { + // Find equivalence classes. + findEquivalenceClasses(F); + + // Propagate weights to all edges. + propagateWeights(F); + } + + return Changed; +} + +char SampleProfileLoader::ID = 0; +INITIALIZE_PASS_BEGIN(SampleProfileLoader, "sample-profile", + "Sample Profile loader", false, false) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(AddDiscriminators) +INITIALIZE_PASS_END(SampleProfileLoader, "sample-profile", + "Sample Profile loader", false, false) + +bool SampleProfileLoader::doInitialization(Module &M) { + auto& Ctx = M.getContext(); + auto ReaderOrErr = SampleProfileReader::create(Filename, Ctx); + if (std::error_code EC = ReaderOrErr.getError()) { + std::string Msg = "Could not open profile: " + EC.message(); + Ctx.diagnose(DiagnosticInfoSampleProfile(Filename.data(), Msg)); + return false; + } + Reader = std::move(ReaderOrErr.get()); + ProfileIsValid = (Reader->read() == sampleprof_error::success); + return true; +} + +ModulePass *llvm::createSampleProfileLoaderPass() { + return new SampleProfileLoader(SampleProfileFile); +} + +ModulePass *llvm::createSampleProfileLoaderPass(StringRef Name) { + return new SampleProfileLoader(Name); +} + +bool SampleProfileLoader::runOnModule(Module &M) { + bool retval = false; + for (auto &F : M) + if (!F.isDeclaration()) + retval |= runOnFunction(F); + return retval; +} + +bool SampleProfileLoader::runOnFunction(Function &F) { + if (!ProfileIsValid) + return false; + + DT = &getAnalysis(F).getDomTree(); + PDT = &getAnalysis(F); + LI = &getAnalysis(F).getLoopInfo(); + Ctx = &F.getParent()->getContext(); + Samples = Reader->getSamplesFor(F); + if (!Samples->empty()) + return emitAnnotations(F); + return false; +} diff --git a/lib/Transforms/Scalar/CMakeLists.txt b/lib/Transforms/Scalar/CMakeLists.txt index 7ee279a5660..1bbbb0317de 100644 --- a/lib/Transforms/Scalar/CMakeLists.txt +++ b/lib/Transforms/Scalar/CMakeLists.txt @@ -38,7 +38,6 @@ add_llvm_library(LLVMScalarOpts RewriteStatepointsForGC.cpp SCCP.cpp SROA.cpp - SampleProfile.cpp Scalar.cpp ScalarReplAggregates.cpp Scalarizer.cpp diff --git a/lib/Transforms/Scalar/SampleProfile.cpp b/lib/Transforms/Scalar/SampleProfile.cpp deleted file mode 100644 index c8dfa54a4aa..00000000000 --- a/lib/Transforms/Scalar/SampleProfile.cpp +++ /dev/null @@ -1,777 +0,0 @@ -//===- SampleProfile.cpp - Incorporate sample profiles into the IR --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SampleProfileLoader transformation. This pass -// reads a profile file generated by a sampling profiler (e.g. Linux Perf - -// http://perf.wiki.kernel.org/) and generates IR metadata to reflect the -// profile information in the given profile. -// -// This pass generates branch weight annotations on the IR: -// -// - prof: Represents branch weights. This annotation is added to branches -// to indicate the weights of each edge coming out of the branch. -// The weight of each edge is the weight of the target block for -// that edge. The weight of a block B is computed as the maximum -// number of samples found in B. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Scalar.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" -#include "llvm/ProfileData/SampleProfReader.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace llvm; -using namespace sampleprof; - -#define DEBUG_TYPE "sample-profile" - -// Command line option to specify the file to read samples from. This is -// mainly used for debugging. -static cl::opt SampleProfileFile( - "sample-profile-file", cl::init(""), cl::value_desc("filename"), - cl::desc("Profile file loaded by -sample-profile"), cl::Hidden); -static cl::opt SampleProfileMaxPropagateIterations( - "sample-profile-max-propagate-iterations", cl::init(100), - cl::desc("Maximum number of iterations to go through when propagating " - "sample block/edge weights through the CFG.")); - -namespace { -typedef DenseMap BlockWeightMap; -typedef DenseMap EquivalenceClassMap; -typedef std::pair Edge; -typedef DenseMap EdgeWeightMap; -typedef DenseMap> BlockEdgeMap; - -/// \brief Sample profile pass. -/// -/// This pass reads profile data from the file specified by -/// -sample-profile-file and annotates every affected function with the -/// profile information found in that file. -class SampleProfileLoader : public FunctionPass { -public: - // Class identification, replacement for typeinfo - static char ID; - - SampleProfileLoader(StringRef Name = SampleProfileFile) - : FunctionPass(ID), DT(nullptr), PDT(nullptr), LI(nullptr), Ctx(nullptr), - Reader(), Samples(nullptr), Filename(Name), ProfileIsValid(false) { - initializeSampleProfileLoaderPass(*PassRegistry::getPassRegistry()); - } - - bool doInitialization(Module &M) override; - - void dump() { Reader->dump(); } - - const char *getPassName() const override { return "Sample profile pass"; } - - bool runOnFunction(Function &F) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - } - -protected: - unsigned getFunctionLoc(Function &F); - bool emitAnnotations(Function &F); - unsigned getInstWeight(Instruction &I); - unsigned getBlockWeight(BasicBlock *BB); - void printEdgeWeight(raw_ostream &OS, Edge E); - void printBlockWeight(raw_ostream &OS, BasicBlock *BB); - void printBlockEquivalence(raw_ostream &OS, BasicBlock *BB); - bool computeBlockWeights(Function &F); - void findEquivalenceClasses(Function &F); - void findEquivalencesFor(BasicBlock *BB1, - SmallVector Descendants, - DominatorTreeBase *DomTree); - void propagateWeights(Function &F); - unsigned visitEdge(Edge E, unsigned *NumUnknownEdges, Edge *UnknownEdge); - void buildEdges(Function &F); - bool propagateThroughEdges(Function &F); - - /// \brief Line number for the function header. Used to compute absolute - /// line numbers from the relative line numbers found in the profile. - unsigned HeaderLineno; - - /// \brief Map basic blocks to their computed weights. - /// - /// The weight of a basic block is defined to be the maximum - /// of all the instruction weights in that block. - BlockWeightMap BlockWeights; - - /// \brief Map edges to their computed weights. - /// - /// Edge weights are computed by propagating basic block weights in - /// SampleProfile::propagateWeights. - EdgeWeightMap EdgeWeights; - - /// \brief Set of visited blocks during propagation. - SmallPtrSet VisitedBlocks; - - /// \brief Set of visited edges during propagation. - SmallSet VisitedEdges; - - /// \brief Equivalence classes for block weights. - /// - /// Two blocks BB1 and BB2 are in the same equivalence class if they - /// dominate and post-dominate each other, and they are in the same loop - /// nest. When this happens, the two blocks are guaranteed to execute - /// the same number of times. - EquivalenceClassMap EquivalenceClass; - - /// \brief Dominance, post-dominance and loop information. - DominatorTree *DT; - PostDominatorTree *PDT; - LoopInfo *LI; - - /// \brief Predecessors for each basic block in the CFG. - BlockEdgeMap Predecessors; - - /// \brief Successors for each basic block in the CFG. - BlockEdgeMap Successors; - - /// \brief LLVM context holding the debug data we need. - LLVMContext *Ctx; - - /// \brief Profile reader object. - std::unique_ptr Reader; - - /// \brief Samples collected for the body of this function. - FunctionSamples *Samples; - - /// \brief Name of the profile file to load. - StringRef Filename; - - /// \brief Flag indicating whether the profile input loaded successfully. - bool ProfileIsValid; -}; -} - -/// \brief Print the weight of edge \p E on stream \p OS. -/// -/// \param OS Stream to emit the output to. -/// \param E Edge to print. -void SampleProfileLoader::printEdgeWeight(raw_ostream &OS, Edge E) { - OS << "weight[" << E.first->getName() << "->" << E.second->getName() - << "]: " << EdgeWeights[E] << "\n"; -} - -/// \brief Print the equivalence class of block \p BB on stream \p OS. -/// -/// \param OS Stream to emit the output to. -/// \param BB Block to print. -void SampleProfileLoader::printBlockEquivalence(raw_ostream &OS, - BasicBlock *BB) { - BasicBlock *Equiv = EquivalenceClass[BB]; - OS << "equivalence[" << BB->getName() - << "]: " << ((Equiv) ? EquivalenceClass[BB]->getName() : "NONE") << "\n"; -} - -/// \brief Print the weight of block \p BB on stream \p OS. -/// -/// \param OS Stream to emit the output to. -/// \param BB Block to print. -void SampleProfileLoader::printBlockWeight(raw_ostream &OS, BasicBlock *BB) { - OS << "weight[" << BB->getName() << "]: " << BlockWeights[BB] << "\n"; -} - -/// \brief Get the weight for an instruction. -/// -/// The "weight" of an instruction \p Inst is the number of samples -/// collected on that instruction at runtime. To retrieve it, we -/// need to compute the line number of \p Inst relative to the start of its -/// function. We use HeaderLineno to compute the offset. We then -/// look up the samples collected for \p Inst using BodySamples. -/// -/// \param Inst Instruction to query. -/// -/// \returns The profiled weight of I. -unsigned SampleProfileLoader::getInstWeight(Instruction &Inst) { - DebugLoc DLoc = Inst.getDebugLoc(); - if (!DLoc) - return 0; - - unsigned Lineno = DLoc.getLine(); - if (Lineno < HeaderLineno) - return 0; - - const DILocation *DIL = DLoc; - int LOffset = Lineno - HeaderLineno; - unsigned Discriminator = DIL->getDiscriminator(); - unsigned Weight = Samples->samplesAt(LOffset, Discriminator); - DEBUG(dbgs() << " " << Lineno << "." << Discriminator << ":" << Inst - << " (line offset: " << LOffset << "." << Discriminator - << " - weight: " << Weight << ")\n"); - return Weight; -} - -/// \brief Compute the weight of a basic block. -/// -/// The weight of basic block \p BB is the maximum weight of all the -/// instructions in BB. The weight of \p BB is computed and cached in -/// the BlockWeights map. -/// -/// \param BB The basic block to query. -/// -/// \returns The computed weight of BB. -unsigned SampleProfileLoader::getBlockWeight(BasicBlock *BB) { - // If we've computed BB's weight before, return it. - std::pair Entry = - BlockWeights.insert(std::make_pair(BB, 0)); - if (!Entry.second) - return Entry.first->second; - - // Otherwise, compute and cache BB's weight. - unsigned Weight = 0; - for (auto &I : BB->getInstList()) { - unsigned InstWeight = getInstWeight(I); - if (InstWeight > Weight) - Weight = InstWeight; - } - Entry.first->second = Weight; - return Weight; -} - -/// \brief Compute and store the weights of every basic block. -/// -/// This populates the BlockWeights map by computing -/// the weights of every basic block in the CFG. -/// -/// \param F The function to query. -bool SampleProfileLoader::computeBlockWeights(Function &F) { - bool Changed = false; - DEBUG(dbgs() << "Block weights\n"); - for (auto &BB : F) { - unsigned Weight = getBlockWeight(&BB); - Changed |= (Weight > 0); - DEBUG(printBlockWeight(dbgs(), &BB)); - } - - return Changed; -} - -/// \brief Find equivalence classes for the given block. -/// -/// This finds all the blocks that are guaranteed to execute the same -/// number of times as \p BB1. To do this, it traverses all the -/// descendants of \p BB1 in the dominator or post-dominator tree. -/// -/// A block BB2 will be in the same equivalence class as \p BB1 if -/// the following holds: -/// -/// 1- \p BB1 is a descendant of BB2 in the opposite tree. So, if BB2 -/// is a descendant of \p BB1 in the dominator tree, then BB2 should -/// dominate BB1 in the post-dominator tree. -/// -/// 2- Both BB2 and \p BB1 must be in the same loop. -/// -/// For every block BB2 that meets those two requirements, we set BB2's -/// equivalence class to \p BB1. -/// -/// \param BB1 Block to check. -/// \param Descendants Descendants of \p BB1 in either the dom or pdom tree. -/// \param DomTree Opposite dominator tree. If \p Descendants is filled -/// with blocks from \p BB1's dominator tree, then -/// this is the post-dominator tree, and vice versa. -void SampleProfileLoader::findEquivalencesFor( - BasicBlock *BB1, SmallVector Descendants, - DominatorTreeBase *DomTree) { - for (auto *BB2 : Descendants) { - bool IsDomParent = DomTree->dominates(BB2, BB1); - bool IsInSameLoop = LI->getLoopFor(BB1) == LI->getLoopFor(BB2); - if (BB1 != BB2 && VisitedBlocks.insert(BB2).second && IsDomParent && - IsInSameLoop) { - EquivalenceClass[BB2] = BB1; - - // If BB2 is heavier than BB1, make BB2 have the same weight - // as BB1. - // - // Note that we don't worry about the opposite situation here - // (when BB2 is lighter than BB1). We will deal with this - // during the propagation phase. Right now, we just want to - // make sure that BB1 has the largest weight of all the - // members of its equivalence set. - unsigned &BB1Weight = BlockWeights[BB1]; - unsigned &BB2Weight = BlockWeights[BB2]; - BB1Weight = std::max(BB1Weight, BB2Weight); - } - } -} - -/// \brief Find equivalence classes. -/// -/// Since samples may be missing from blocks, we can fill in the gaps by setting -/// the weights of all the blocks in the same equivalence class to the same -/// weight. To compute the concept of equivalence, we use dominance and loop -/// information. Two blocks B1 and B2 are in the same equivalence class if B1 -/// dominates B2, B2 post-dominates B1 and both are in the same loop. -/// -/// \param F The function to query. -void SampleProfileLoader::findEquivalenceClasses(Function &F) { - SmallVector DominatedBBs; - DEBUG(dbgs() << "\nBlock equivalence classes\n"); - // Find equivalence sets based on dominance and post-dominance information. - for (auto &BB : F) { - BasicBlock *BB1 = &BB; - - // Compute BB1's equivalence class once. - if (EquivalenceClass.count(BB1)) { - DEBUG(printBlockEquivalence(dbgs(), BB1)); - continue; - } - - // By default, blocks are in their own equivalence class. - EquivalenceClass[BB1] = BB1; - - // Traverse all the blocks dominated by BB1. We are looking for - // every basic block BB2 such that: - // - // 1- BB1 dominates BB2. - // 2- BB2 post-dominates BB1. - // 3- BB1 and BB2 are in the same loop nest. - // - // If all those conditions hold, it means that BB2 is executed - // as many times as BB1, so they are placed in the same equivalence - // class by making BB2's equivalence class be BB1. - DominatedBBs.clear(); - DT->getDescendants(BB1, DominatedBBs); - findEquivalencesFor(BB1, DominatedBBs, PDT->DT); - - // Repeat the same logic for all the blocks post-dominated by BB1. - // We are looking for every basic block BB2 such that: - // - // 1- BB1 post-dominates BB2. - // 2- BB2 dominates BB1. - // 3- BB1 and BB2 are in the same loop nest. - // - // If all those conditions hold, BB2's equivalence class is BB1. - DominatedBBs.clear(); - PDT->getDescendants(BB1, DominatedBBs); - findEquivalencesFor(BB1, DominatedBBs, DT); - - DEBUG(printBlockEquivalence(dbgs(), BB1)); - } - - // Assign weights to equivalence classes. - // - // All the basic blocks in the same equivalence class will execute - // the same number of times. Since we know that the head block in - // each equivalence class has the largest weight, assign that weight - // to all the blocks in that equivalence class. - DEBUG(dbgs() << "\nAssign the same weight to all blocks in the same class\n"); - for (auto &BI : F) { - BasicBlock *BB = &BI; - BasicBlock *EquivBB = EquivalenceClass[BB]; - if (BB != EquivBB) - BlockWeights[BB] = BlockWeights[EquivBB]; - DEBUG(printBlockWeight(dbgs(), BB)); - } -} - -/// \brief Visit the given edge to decide if it has a valid weight. -/// -/// If \p E has not been visited before, we copy to \p UnknownEdge -/// and increment the count of unknown edges. -/// -/// \param E Edge to visit. -/// \param NumUnknownEdges Current number of unknown edges. -/// \param UnknownEdge Set if E has not been visited before. -/// -/// \returns E's weight, if known. Otherwise, return 0. -unsigned SampleProfileLoader::visitEdge(Edge E, unsigned *NumUnknownEdges, - Edge *UnknownEdge) { - if (!VisitedEdges.count(E)) { - (*NumUnknownEdges)++; - *UnknownEdge = E; - return 0; - } - - return EdgeWeights[E]; -} - -/// \brief Propagate weights through incoming/outgoing edges. -/// -/// If the weight of a basic block is known, and there is only one edge -/// with an unknown weight, we can calculate the weight of that edge. -/// -/// Similarly, if all the edges have a known count, we can calculate the -/// count of the basic block, if needed. -/// -/// \param F Function to process. -/// -/// \returns True if new weights were assigned to edges or blocks. -bool SampleProfileLoader::propagateThroughEdges(Function &F) { - bool Changed = false; - DEBUG(dbgs() << "\nPropagation through edges\n"); - for (auto &BI : F) { - BasicBlock *BB = &BI; - - // Visit all the predecessor and successor edges to determine - // which ones have a weight assigned already. Note that it doesn't - // matter that we only keep track of a single unknown edge. The - // only case we are interested in handling is when only a single - // edge is unknown (see setEdgeOrBlockWeight). - for (unsigned i = 0; i < 2; i++) { - unsigned TotalWeight = 0; - unsigned NumUnknownEdges = 0; - Edge UnknownEdge, SelfReferentialEdge; - - if (i == 0) { - // First, visit all predecessor edges. - for (auto *Pred : Predecessors[BB]) { - Edge E = std::make_pair(Pred, BB); - TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge); - if (E.first == E.second) - SelfReferentialEdge = E; - } - } else { - // On the second round, visit all successor edges. - for (auto *Succ : Successors[BB]) { - Edge E = std::make_pair(BB, Succ); - TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge); - } - } - - // After visiting all the edges, there are three cases that we - // can handle immediately: - // - // - All the edge weights are known (i.e., NumUnknownEdges == 0). - // In this case, we simply check that the sum of all the edges - // is the same as BB's weight. If not, we change BB's weight - // to match. Additionally, if BB had not been visited before, - // we mark it visited. - // - // - Only one edge is unknown and BB has already been visited. - // In this case, we can compute the weight of the edge by - // subtracting the total block weight from all the known - // edge weights. If the edges weight more than BB, then the - // edge of the last remaining edge is set to zero. - // - // - There exists a self-referential edge and the weight of BB is - // known. In this case, this edge can be based on BB's weight. - // We add up all the other known edges and set the weight on - // the self-referential edge as we did in the previous case. - // - // In any other case, we must continue iterating. Eventually, - // all edges will get a weight, or iteration will stop when - // it reaches SampleProfileMaxPropagateIterations. - if (NumUnknownEdges <= 1) { - unsigned &BBWeight = BlockWeights[BB]; - if (NumUnknownEdges == 0) { - // If we already know the weight of all edges, the weight of the - // basic block can be computed. It should be no larger than the sum - // of all edge weights. - if (TotalWeight > BBWeight) { - BBWeight = TotalWeight; - Changed = true; - DEBUG(dbgs() << "All edge weights for " << BB->getName() - << " known. Set weight for block: "; - printBlockWeight(dbgs(), BB);); - } - if (VisitedBlocks.insert(BB).second) - Changed = true; - } else if (NumUnknownEdges == 1 && VisitedBlocks.count(BB)) { - // If there is a single unknown edge and the block has been - // visited, then we can compute E's weight. - if (BBWeight >= TotalWeight) - EdgeWeights[UnknownEdge] = BBWeight - TotalWeight; - else - EdgeWeights[UnknownEdge] = 0; - VisitedEdges.insert(UnknownEdge); - Changed = true; - DEBUG(dbgs() << "Set weight for edge: "; - printEdgeWeight(dbgs(), UnknownEdge)); - } - } else if (SelfReferentialEdge.first && VisitedBlocks.count(BB)) { - unsigned &BBWeight = BlockWeights[BB]; - // We have a self-referential edge and the weight of BB is known. - if (BBWeight >= TotalWeight) - EdgeWeights[SelfReferentialEdge] = BBWeight - TotalWeight; - else - EdgeWeights[SelfReferentialEdge] = 0; - VisitedEdges.insert(SelfReferentialEdge); - Changed = true; - DEBUG(dbgs() << "Set self-referential edge weight to: "; - printEdgeWeight(dbgs(), SelfReferentialEdge)); - } - } - } - - return Changed; -} - -/// \brief Build in/out edge lists for each basic block in the CFG. -/// -/// We are interested in unique edges. If a block B1 has multiple -/// edges to another block B2, we only add a single B1->B2 edge. -void SampleProfileLoader::buildEdges(Function &F) { - for (auto &BI : F) { - BasicBlock *B1 = &BI; - - // Add predecessors for B1. - SmallPtrSet Visited; - if (!Predecessors[B1].empty()) - llvm_unreachable("Found a stale predecessors list in a basic block."); - for (pred_iterator PI = pred_begin(B1), PE = pred_end(B1); PI != PE; ++PI) { - BasicBlock *B2 = *PI; - if (Visited.insert(B2).second) - Predecessors[B1].push_back(B2); - } - - // Add successors for B1. - Visited.clear(); - if (!Successors[B1].empty()) - llvm_unreachable("Found a stale successors list in a basic block."); - for (succ_iterator SI = succ_begin(B1), SE = succ_end(B1); SI != SE; ++SI) { - BasicBlock *B2 = *SI; - if (Visited.insert(B2).second) - Successors[B1].push_back(B2); - } - } -} - -/// \brief Propagate weights into edges -/// -/// The following rules are applied to every block BB in the CFG: -/// -/// - If BB has a single predecessor/successor, then the weight -/// of that edge is the weight of the block. -/// -/// - If all incoming or outgoing edges are known except one, and the -/// weight of the block is already known, the weight of the unknown -/// edge will be the weight of the block minus the sum of all the known -/// edges. If the sum of all the known edges is larger than BB's weight, -/// we set the unknown edge weight to zero. -/// -/// - If there is a self-referential edge, and the weight of the block is -/// 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) { - bool Changed = true; - unsigned i = 0; - - // Add an entry count to the function using the samples gathered - // at the function entry. - F.setEntryCount(Samples->getHeadSamples()); - - // Before propagation starts, build, for each block, a list of - // unique predecessors and successors. This is necessary to handle - // identical edges in multiway branches. Since we visit all blocks and all - // edges of the CFG, it is cleaner to build these lists once at the start - // of the pass. - buildEdges(F); - - // Propagate until we converge or we go past the iteration limit. - while (Changed && i++ < SampleProfileMaxPropagateIterations) { - Changed = propagateThroughEdges(F); - } - - // Generate MD_prof metadata for every branch instruction using the - // edge weights computed during propagation. - DEBUG(dbgs() << "\nPropagation complete. Setting branch weights\n"); - MDBuilder MDB(F.getContext()); - for (auto &BI : F) { - BasicBlock *BB = &BI; - TerminatorInst *TI = BB->getTerminator(); - if (TI->getNumSuccessors() == 1) - continue; - if (!isa(TI) && !isa(TI)) - continue; - - DEBUG(dbgs() << "\nGetting weights for branch at line " - << TI->getDebugLoc().getLine() << ".\n"); - SmallVector Weights; - bool AllWeightsZero = true; - for (unsigned I = 0; I < TI->getNumSuccessors(); ++I) { - BasicBlock *Succ = TI->getSuccessor(I); - Edge E = std::make_pair(BB, Succ); - unsigned Weight = EdgeWeights[E]; - DEBUG(dbgs() << "\t"; printEdgeWeight(dbgs(), E)); - Weights.push_back(Weight); - if (Weight != 0) - AllWeightsZero = false; - } - - // Only set weights if there is at least one non-zero weight. - // In any other case, let the analyzer set weights. - if (!AllWeightsZero) { - DEBUG(dbgs() << "SUCCESS. Found non-zero weights.\n"); - TI->setMetadata(llvm::LLVMContext::MD_prof, - MDB.createBranchWeights(Weights)); - } else { - DEBUG(dbgs() << "SKIPPED. All branch weights are zero.\n"); - } - } -} - -/// \brief Get the line number for the function header. -/// -/// This looks up function \p F in the current compilation unit and -/// retrieves the line number where the function is defined. This is -/// line 0 for all the samples read from the profile file. Every line -/// number is relative to this line. -/// -/// \param F Function object to query. -/// -/// \returns the line number where \p F is defined. If it returns 0, -/// it means that there is no debug information available for \p F. -unsigned SampleProfileLoader::getFunctionLoc(Function &F) { - if (DISubprogram *S = getDISubprogram(&F)) - return S->getLine(); - - // If could not find the start of \p F, emit a diagnostic to inform the user - // about the missed opportunity. - F.getContext().diagnose(DiagnosticInfoSampleProfile( - "No debug information found in function " + F.getName() + - ": Function profile not used", - DS_Warning)); - return 0; -} - -/// \brief Generate branch weight metadata for all branches in \p F. -/// -/// Branch weights are computed out of instruction samples using a -/// propagation heuristic. Propagation proceeds in 3 phases: -/// -/// 1- Assignment of block weights. All the basic blocks in the function -/// are initial assigned the same weight as their most frequently -/// executed instruction. -/// -/// 2- Creation of equivalence classes. Since samples may be missing from -/// blocks, we can fill in the gaps by setting the weights of all the -/// blocks in the same equivalence class to the same weight. To compute -/// the concept of equivalence, we use dominance and loop information. -/// Two blocks B1 and B2 are in the same equivalence class if B1 -/// dominates B2, B2 post-dominates B1 and both are in the same loop. -/// -/// 3- Propagation of block weights into edges. This uses a simple -/// propagation heuristic. The following rules are applied to every -/// block BB in the CFG: -/// -/// - If BB has a single predecessor/successor, then the weight -/// of that edge is the weight of the block. -/// -/// - If all the edges are known except one, and the weight of the -/// block is already known, the weight of the unknown edge will -/// be the weight of the block minus the sum of all the known -/// edges. If the sum of all the known edges is larger than BB's weight, -/// we set the unknown edge weight to zero. -/// -/// - If there is a self-referential edge, and the weight of the block is -/// 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). -/// -/// Since this propagation is not guaranteed to finalize for every CFG, we -/// only allow it to proceed for a limited number of iterations (controlled -/// by -sample-profile-max-propagate-iterations). -/// -/// FIXME: Try to replace this propagation heuristic with a scheme -/// that is guaranteed to finalize. A work-list approach similar to -/// the standard value propagation algorithm used by SSA-CCP might -/// work here. -/// -/// Once all the branch weights are computed, we emit the MD_prof -/// metadata on BB using the computed values for each of its branches. -/// -/// \param F The function to query. -/// -/// \returns true if \p F was modified. Returns false, otherwise. -bool SampleProfileLoader::emitAnnotations(Function &F) { - bool Changed = false; - - // Initialize invariants used during computation and propagation. - HeaderLineno = getFunctionLoc(F); - if (HeaderLineno == 0) - return false; - - DEBUG(dbgs() << "Line number for the first instruction in " << F.getName() - << ": " << HeaderLineno << "\n"); - - // Compute basic block weights. - Changed |= computeBlockWeights(F); - - if (Changed) { - // Find equivalence classes. - findEquivalenceClasses(F); - - // Propagate weights to all edges. - propagateWeights(F); - } - - return Changed; -} - -char SampleProfileLoader::ID = 0; -INITIALIZE_PASS_BEGIN(SampleProfileLoader, "sample-profile", - "Sample Profile loader", false, false) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(AddDiscriminators) -INITIALIZE_PASS_END(SampleProfileLoader, "sample-profile", - "Sample Profile loader", false, false) - -bool SampleProfileLoader::doInitialization(Module &M) { - auto ReaderOrErr = SampleProfileReader::create(Filename, M.getContext()); - if (std::error_code EC = ReaderOrErr.getError()) { - std::string Msg = "Could not open profile: " + EC.message(); - M.getContext().diagnose(DiagnosticInfoSampleProfile(Filename.data(), Msg)); - return false; - } - Reader = std::move(ReaderOrErr.get()); - ProfileIsValid = (Reader->read() == sampleprof_error::success); - return true; -} - -FunctionPass *llvm::createSampleProfileLoaderPass() { - return new SampleProfileLoader(SampleProfileFile); -} - -FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) { - return new SampleProfileLoader(Name); -} - -bool SampleProfileLoader::runOnFunction(Function &F) { - if (!ProfileIsValid) - return false; - - DT = &getAnalysis().getDomTree(); - PDT = &getAnalysis(); - LI = &getAnalysis().getLoopInfo(); - Ctx = &F.getParent()->getContext(); - Samples = Reader->getSamplesFor(F); - if (!Samples->empty()) - return emitAnnotations(F); - return false; -} diff --git a/lib/Transforms/Scalar/Scalar.cpp b/lib/Transforms/Scalar/Scalar.cpp index a0180f13c1d..54b78e36965 100644 --- a/lib/Transforms/Scalar/Scalar.cpp +++ b/lib/Transforms/Scalar/Scalar.cpp @@ -33,7 +33,6 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeADCEPass(Registry); initializeBDCEPass(Registry); initializeAlignmentFromAssumptionsPass(Registry); - initializeSampleProfileLoaderPass(Registry); initializeConstantHoistingPass(Registry); initializeConstantPropagationPass(Registry); initializeCorrelatedValuePropagationPass(Registry);