diff --git a/lib/Transforms/Scalar/SampleProfile.cpp b/lib/Transforms/Scalar/SampleProfile.cpp index 9bcd702a913..9856d7fbb28 100644 --- a/lib/Transforms/Scalar/SampleProfile.cpp +++ b/lib/Transforms/Scalar/SampleProfile.cpp @@ -54,6 +54,55 @@ static cl::opt SampleProfileFile( cl::desc("Profile file loaded by -sample-profile"), cl::Hidden); namespace { + +typedef DenseMap BodySampleMap; +typedef DenseMap BlockWeightMap; + +/// \brief Representation of the runtime profile for a function. +/// +/// This data structure contains the runtime profile for a given +/// function. It contains the total number of samples collected +/// in the function and a map of samples collected in every statement. +class SampleFunctionProfile { +public: + SampleFunctionProfile() : TotalSamples(0), TotalHeadSamples(0) {} + + bool emitAnnotations(Function &F); + uint32_t getInstWeight(Instruction &I, unsigned FirstLineno, + BodySampleMap &BodySamples); + uint32_t computeBlockWeight(BasicBlock *B, unsigned FirstLineno, + BodySampleMap &BodySamples); + void addTotalSamples(unsigned Num) { TotalSamples += Num; } + void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; } + void addBodySamples(unsigned LineOffset, unsigned Num) { + BodySamples[LineOffset] += Num; + } + void print(raw_ostream &OS); + +protected: + /// \brief Total number of samples collected inside this function. + /// + /// Samples are cumulative, they include all the samples collected + /// inside this function and all its inlined callees. + unsigned TotalSamples; + + // \brief Total number of samples collected at the head of the function. + unsigned TotalHeadSamples; + + /// \brief Map line offsets to collected samples. + /// + /// Each entry in this map contains the number of samples + /// collected at the corresponding line offset. All line locations + /// are an offset from the start of the function. + BodySampleMap BodySamples; + + /// \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 Sample-based profile reader. /// /// Each profile contains sample counts for all the functions @@ -77,61 +126,26 @@ namespace { /// 2. The samples collected at each line in F. To provide some /// protection against source code shuffling, line numbers should /// be relative to the start of the function. -class SampleProfile { +class SampleModuleProfile { public: - SampleProfile(StringRef F) : Profiles(0), Filename(F) {} + SampleModuleProfile(StringRef F) : Profiles(0), Filename(F) {} void dump(); void loadText(); void loadNative() { llvm_unreachable("not implemented"); } - bool emitAnnotations(Function &F); void printFunctionProfile(raw_ostream &OS, StringRef FName); void dumpFunctionProfile(StringRef FName); + SampleFunctionProfile &getProfile(const Function &F) { + return Profiles[F.getName()]; + } protected: - typedef DenseMap BodySampleMap; - typedef DenseMap BlockWeightMap; - - /// \brief Representation of the runtime profile for a function. - /// - /// This data structure contains the runtime profile for a given - /// function. It contains the total number of samples collected - /// in the function and a map of samples collected in every statement. - struct FunctionProfile { - /// \brief Total number of samples collected inside this function. - /// - /// Samples are cumulative, they include all the samples collected - /// inside this function and all its inlined callees. - unsigned TotalSamples; - - // \brief Total number of samples collected at the head of the function. - unsigned TotalHeadSamples; - - /// \brief Map line offsets to collected samples. - /// - /// Each entry in this map contains the number of samples - /// collected at the corresponding line offset. All line locations - /// are an offset from the start of the function. - BodySampleMap BodySamples; - - /// \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; - }; - - uint32_t getInstWeight(Instruction &I, unsigned FirstLineno, - BodySampleMap &BodySamples); - uint32_t computeBlockWeight(BasicBlock *B, unsigned FirstLineno, - BodySampleMap &BodySamples); - /// \brief Map every function to its associated profile. /// /// The profile of every function executed at runtime is collected - /// in the structure FunctionProfile. This maps function objects + /// in the structure SampleFunctionProfile. This maps function objects /// to their corresponding profiles. - StringMap Profiles; + StringMap Profiles; /// \brief Path name to the file holding the profile data. /// @@ -228,41 +242,48 @@ public: protected: /// \brief Profile reader object. - OwningPtr Profiler; + OwningPtr Profiler; /// \brief Name of the profile file to load. StringRef Filename; }; } -/// \brief Print the function profile for \p FName on stream \p OS. +/// \brief Print this function profile on stream \p OS. /// /// \param OS Stream to emit the output to. -/// \param FName Name of the function to print. -void SampleProfile::printFunctionProfile(raw_ostream &OS, StringRef FName) { - FunctionProfile FProfile = Profiles[FName]; - OS << "Function: " << FName << ", " << FProfile.TotalSamples << ", " - << FProfile.TotalHeadSamples << ", " << FProfile.BodySamples.size() +void SampleFunctionProfile::print(raw_ostream &OS) { + OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size() << " sampled lines\n"; - for (BodySampleMap::const_iterator SI = FProfile.BodySamples.begin(), - SE = FProfile.BodySamples.end(); + for (BodySampleMap::const_iterator SI = BodySamples.begin(), + SE = BodySamples.end(); SI != SE; ++SI) OS << "\tline offset: " << SI->first << ", number of samples: " << SI->second << "\n"; OS << "\n"; } +/// \brief Print the function profile for \p FName on stream \p OS. +/// +/// \param OS Stream to emit the output to. +/// \param FName Name of the function to print. +void SampleModuleProfile::printFunctionProfile(raw_ostream &OS, + StringRef FName) { + OS << "Function: " << FName << ":\n"; + Profiles[FName].print(OS); +} + /// \brief Dump the function profile for \p FName. /// /// \param FName Name of the function to print. -void SampleProfile::dumpFunctionProfile(StringRef FName) { +void SampleModuleProfile::dumpFunctionProfile(StringRef FName) { printFunctionProfile(dbgs(), FName); } /// \brief Dump all the function profiles found. -void SampleProfile::dump() { - for (StringMap::const_iterator I = Profiles.begin(), - E = Profiles.end(); +void SampleModuleProfile::dump() { + for (StringMap::const_iterator I = Profiles.begin(), + E = Profiles.end(); I != E; ++I) dumpFunctionProfile(I->getKey()); } @@ -297,7 +318,7 @@ void SampleProfile::dump() { /// for debugging purposes, but it should not be used to generate /// profiles for large programs, as the representation is extremely /// inefficient. -void SampleProfile::loadText() { +void SampleModuleProfile::loadText() { ExternalProfileTextLoader Loader(Filename); // Read the symbol table. @@ -308,13 +329,8 @@ void SampleProfile::loadText() { Line = Loader.readLine(); if (Line.getAsInteger(10, NumSymbols)) Loader.reportParseError("Expected a number, found " + Line); - for (int I = 0; I < NumSymbols; I++) { - StringRef FName = Loader.readLine(); - FunctionProfile &FProfile = Profiles[FName]; - FProfile.BodySamples.clear(); - FProfile.TotalSamples = 0; - FProfile.TotalHeadSamples = 0; - } + for (int I = 0; I < NumSymbols; I++) + Profiles[Loader.readLine()] = SampleFunctionProfile(); // Read the profile of each function. Since each function may be // mentioned more than once, and we are collecting flat profiles, @@ -333,10 +349,9 @@ void SampleProfile::loadText() { Matches[2].getAsInteger(10, NumSamples); Matches[3].getAsInteger(10, NumHeadSamples); Matches[4].getAsInteger(10, NumSampledLines); - FunctionProfile &FProfile = Profiles[FName]; - FProfile.TotalSamples += NumSamples; - FProfile.TotalHeadSamples += NumHeadSamples; - BodySampleMap &SampleMap = FProfile.BodySamples; + SampleFunctionProfile &FProfile = Profiles[FName]; + FProfile.addTotalSamples(NumSamples); + FProfile.addHeadSamples(NumHeadSamples); unsigned I; for (I = 0; I < NumSampledLines && !Loader.atEOF(); I++) { Line = Loader.readLine(); @@ -346,7 +361,7 @@ void SampleProfile::loadText() { unsigned LineOffset, NumSamples; Matches[1].getAsInteger(10, LineOffset); Matches[2].getAsInteger(10, NumSamples); - SampleMap[LineOffset] += NumSamples; + FProfile.addBodySamples(LineOffset, NumSamples); } if (I < NumSampledLines) @@ -354,6 +369,24 @@ void SampleProfile::loadText() { } } +char SampleProfileLoader::ID = 0; +INITIALIZE_PASS(SampleProfileLoader, "sample-profile", "Sample Profile loader", + false, false) + +bool SampleProfileLoader::doInitialization(Module &M) { + Profiler.reset(new SampleModuleProfile(Filename)); + Profiler->loadText(); + return true; +} + +FunctionPass *llvm::createSampleProfileLoaderPass() { + return new SampleProfileLoader(SampleProfileFile); +} + +FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) { + return new SampleProfileLoader(Name); +} + /// \brief Get the weight for an instruction. /// /// The "weight" of an instruction \p Inst is the number of samples @@ -367,8 +400,9 @@ void SampleProfile::loadText() { /// \param BodySamples Map of relative source line locations to samples. /// /// \returns The profiled weight of I. -uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno, - BodySampleMap &BodySamples) { +uint32_t SampleFunctionProfile::getInstWeight(Instruction &Inst, + unsigned FirstLineno, + BodySampleMap &BodySamples) { unsigned LOffset = Inst.getDebugLoc().getLine() - FirstLineno + 1; return BodySamples.lookup(LOffset); } @@ -385,13 +419,12 @@ uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno, /// function. /// /// \returns The computed weight of B. -uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno, - BodySampleMap &BodySamples) { +uint32_t SampleFunctionProfile::computeBlockWeight(BasicBlock *B, + unsigned FirstLineno, + BodySampleMap &BodySamples) { // If we've computed B's weight before, return it. - Function *F = B->getParent(); - FunctionProfile &FProfile = Profiles[F->getName()]; std::pair Entry = - FProfile.BlockWeights.insert(std::make_pair(B, 0)); + BlockWeights.insert(std::make_pair(B, 0)); if (!Entry.second) return Entry.first->second; @@ -420,14 +453,13 @@ uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno, /// metadata on B using the computed values. /// /// \param F The function to query. -bool SampleProfile::emitAnnotations(Function &F) { +bool SampleFunctionProfile::emitAnnotations(Function &F) { bool Changed = false; - FunctionProfile &FProfile = Profiles[F.getName()]; unsigned FirstLineno = inst_begin(F)->getDebugLoc().getLine(); MDBuilder MDB(F.getContext()); // Clear the block weights cache. - FProfile.BlockWeights.clear(); + BlockWeights.clear(); // When we find a branch instruction: For each edge E out of the branch, // the weight of E is the weight of the target block. @@ -443,8 +475,7 @@ bool SampleProfile::emitAnnotations(Function &F) { unsigned NSuccs = TI->getNumSuccessors(); for (unsigned I = 0; I < NSuccs; ++I) { BasicBlock *Succ = TI->getSuccessor(I); - uint32_t Weight = - computeBlockWeight(Succ, FirstLineno, FProfile.BodySamples); + uint32_t Weight = computeBlockWeight(Succ, FirstLineno, BodySamples); Weights.push_back(Weight); } @@ -456,24 +487,6 @@ bool SampleProfile::emitAnnotations(Function &F) { return Changed; } -char SampleProfileLoader::ID = 0; -INITIALIZE_PASS(SampleProfileLoader, "sample-profile", "Sample Profile loader", - false, false) - bool SampleProfileLoader::runOnFunction(Function &F) { - return Profiler->emitAnnotations(F); -} - -bool SampleProfileLoader::doInitialization(Module &M) { - Profiler.reset(new SampleProfile(Filename)); - Profiler->loadText(); - return true; -} - -FunctionPass *llvm::createSampleProfileLoaderPass() { - return new SampleProfileLoader(SampleProfileFile); -} - -FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) { - return new SampleProfileLoader(Name); + return Profiler->getProfile(F).emitAnnotations(F); }