X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FSampleProfile.cpp;h=47250cccc4d4d5d58e1c7f1dca9373bef1c08c6e;hp=8fd81d62dd80073ffd68382b7f688e43023806b3;hb=bcb1df36b725ca52eedbecd6c331152e59d798a5;hpb=16624bec2f7d679beb71c8d8ed1a9f0d010b9ff3 diff --git a/lib/Transforms/IPO/SampleProfile.cpp b/lib/Transforms/IPO/SampleProfile.cpp index 8fd81d62dd8..47250cccc4d 100644 --- a/lib/Transforms/IPO/SampleProfile.cpp +++ b/lib/Transforms/IPO/SampleProfile.cpp @@ -63,6 +63,10 @@ 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.")); +static cl::opt SampleProfileCoverage( + "sample-profile-check-coverage", cl::init(0), cl::value_desc("N"), + cl::desc("Emit a warning if less than N% of samples in the input profile " + "are matched to the IR.")); namespace { typedef DenseMap BlockWeightMap; @@ -174,6 +178,64 @@ protected: /// \brief Flag indicating whether the profile input loaded successfully. bool ProfileIsValid; }; + +class SampleCoverageTracker { +public: + SampleCoverageTracker() : SampleCoverage() {} + + void markSamplesUsed(const FunctionSamples *Samples, uint32_t LineOffset, + uint32_t Discriminator); + unsigned computeCoverage(const FunctionSamples *Samples) const; + unsigned getNumUsedSamples(const FunctionSamples *Samples) const; + +private: + typedef DenseMap BodySampleCoverageMap; + typedef DenseMap + FunctionSamplesCoverageMap; + + /// Coverage map for sampling records. + /// + /// This map keeps a record of sampling records that have been matched to + /// an IR instruction. This is used to detect some form of staleness in + /// profiles (see flag -sample-profile-check-coverage). + /// + /// Each entry in the map corresponds to a FunctionSamples instance. This is + /// another map that counts how many times the sample record at the + /// given location has been used. + FunctionSamplesCoverageMap SampleCoverage; +}; + +SampleCoverageTracker CoverageTracker; +} + +/// Mark as used the sample record for the given function samples at +/// (LineOffset, Discriminator). +void SampleCoverageTracker::markSamplesUsed(const FunctionSamples *Samples, + uint32_t LineOffset, + uint32_t Discriminator) { + BodySampleCoverageMap &Coverage = SampleCoverage[Samples]; + Coverage[LineLocation(LineOffset, Discriminator)]++; +} + +/// Return the number of sample records that were applied from this profile. +unsigned +SampleCoverageTracker::getNumUsedSamples(const FunctionSamples *Samples) const { + auto I = SampleCoverage.find(Samples); + return (I != SampleCoverage.end()) ? I->second.size() : 0; +} + +/// Return the fraction of sample records used in this profile. +/// +/// The returned value is an unsigned integer in the range 0-100 indicating +/// the percentage of sample records that were used while applying this +/// profile to the associated function. +unsigned +SampleCoverageTracker::computeCoverage(const FunctionSamples *Samples) const { + uint32_t NumTotalRecords = Samples->getBodySamples().size(); + uint32_t NumUsedRecords = getNumUsedSamples(Samples); + assert(NumUsedRecords <= NumTotalRecords && + "number of used records cannot exceed the total number of records"); + return NumTotalRecords > 0 ? NumUsedRecords * 100 / NumTotalRecords : 100; } /// Clear all the per-function data used to load samples and propagate weights. @@ -257,13 +319,17 @@ SampleProfileLoader::getInstWeight(const Instruction &Inst) const { unsigned Lineno = DLoc.getLine(); unsigned HeaderLineno = DIL->getScope()->getSubprogram()->getLine(); - ErrorOr R = FS->findSamplesAt(getOffset(Lineno, HeaderLineno), - DIL->getDiscriminator()); - if (R) + uint32_t LineOffset = getOffset(Lineno, HeaderLineno); + uint32_t Discriminator = DIL->getDiscriminator(); + ErrorOr R = FS->findSamplesAt(LineOffset, Discriminator); + if (R) { + if (SampleProfileCoverage) + CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator); DEBUG(dbgs() << " " << Lineno << "." << DIL->getDiscriminator() << ":" << Inst << " (line offset: " << Lineno - HeaderLineno << "." << DIL->getDiscriminator() << " - weight: " << R.get() << ")\n"); + } return R; } @@ -311,6 +377,20 @@ bool SampleProfileLoader::computeBlockWeights(Function &F) { DEBUG(printBlockWeight(dbgs(), &BB)); } + if (SampleProfileCoverage) { + unsigned Coverage = CoverageTracker.computeCoverage(Samples); + if (Coverage < SampleProfileCoverage) { + const char *Filename = getDISubprogram(&F)->getFilename().str().c_str(); + F.getContext().diagnose(DiagnosticInfoSampleProfile( + Filename, getFunctionLoc(F), + Twine(CoverageTracker.getNumUsedSamples(Samples)) + " of " + + Twine(Samples->getBodySamples().size()) + + " available profile records (" + Twine(Coverage) + + "%) were applied", + DS_Warning)); + } + } + return Changed; }