[llvm] r251568 - SamplePGO - Add flag to check sampling coverage.
Daniel Jasper via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 29 05:51:58 PDT 2015
On Wed, Oct 28, 2015 at 3:30 PM, Diego Novillo via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: dnovillo
> Date: Wed Oct 28 17:30:25 2015
> New Revision: 251568
>
> URL: http://llvm.org/viewvc/llvm-project?rev=251568&view=rev
> Log:
> SamplePGO - Add flag to check sampling coverage.
>
> This adds the flag -mllvm -sample-profile-check-coverage=N to the
> SampleProfile pass. N is the percent of input sample records that the
> user expects to apply. If the pass does not use N% (or more) of the
> sample records in the input, it emits a warning.
>
> This is useful to detect some forms of stale profiles. If the code has
> drifted enough from the original profile, there will be records that do
> not match the IR anymore.
>
> This will not detect cases where a sample profile record for line L is
> referring to some other instructions that also used to be at line L.
>
> Added:
> llvm/trunk/test/Transforms/SampleProfile/Inputs/coverage-warning.prof
> llvm/trunk/test/Transforms/SampleProfile/coverage-warning.ll
> Modified:
> llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp
>
> Modified: llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp?rev=251568&r1=251567&r2=251568&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp Wed Oct 28 17:30:25
> 2015
> @@ -63,6 +63,10 @@ static cl::opt<unsigned> SampleProfileMa
> "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<unsigned> 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<const BasicBlock *, uint64_t> 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<LineLocation, unsigned> BodySampleCoverageMap;
> + typedef DenseMap<const FunctionSamples *, BodySampleCoverageMap>
> + 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
> unsigned Lineno = DLoc.getLine();
> unsigned HeaderLineno = DIL->getScope()->getSubprogram()->getLine();
>
> - ErrorOr<uint64_t> R = FS->findSamplesAt(getOffset(Lineno, HeaderLineno),
> - DIL->getDiscriminator());
> - if (R)
> + uint32_t LineOffset = getOffset(Lineno, HeaderLineno);
> + uint32_t Discriminator = DIL->getDiscriminator();
> + ErrorOr<uint64_t> 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::computeBlockWe
> DEBUG(printBlockWeight(dbgs(), &BB));
> }
>
> + if (SampleProfileCoverage) {
> + unsigned Coverage = CoverageTracker.computeCoverage(Samples);
> + if (Coverage < SampleProfileCoverage) {
> + const char *Filename =
> getDISubprogram(&F)->getFilename().str().c_str();
>
This creates a pointer into a temporary string. Fixed in r251623.
> + 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;
> }
>
>
> Added:
> llvm/trunk/test/Transforms/SampleProfile/Inputs/coverage-warning.prof
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/coverage-warning.prof?rev=251568&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/SampleProfile/Inputs/coverage-warning.prof
> (added)
> +++ llvm/trunk/test/Transforms/SampleProfile/Inputs/coverage-warning.prof
> Wed Oct 28 17:30:25 2015
> @@ -0,0 +1,5 @@
> +foo:30000:100
> + 2: 28000
> + 3: 1000
> +# This profile is stale. Function foo() does not have a line 8 anymore.
> + 8: 1700
>
> Added: llvm/trunk/test/Transforms/SampleProfile/coverage-warning.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/coverage-warning.ll?rev=251568&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/SampleProfile/coverage-warning.ll (added)
> +++ llvm/trunk/test/Transforms/SampleProfile/coverage-warning.ll Wed Oct
> 28 17:30:25 2015
> @@ -0,0 +1,45 @@
> +; RUN: opt < %s -sample-profile
> -sample-profile-file=%S/Inputs/coverage-warning.prof
> -sample-profile-check-coverage=90 2>& 1 | FileCheck %s
> +define i32 @foo(i32 %i) {
> +; The profile has samples for line locations that are no longer present.
> +; Coverage does not reach 90%, so we should get this warning:
> +;
> +; CHECK: warning: coverage-warning.c:1: 2 of 3 available profile records
> (66%) were applied
> +entry:
> + %retval = alloca i32, align 4
> + %i.addr = alloca i32, align 4
> + store i32 %i, i32* %i.addr, align 4
> + %0 = load i32, i32* %i.addr, align 4, !dbg !9
> + %cmp = icmp sgt i32 %0, 1000, !dbg !10
> + br i1 %cmp, label %if.then, label %if.end, !dbg !9
> +
> +if.then: ; preds = %entry
> + store i32 30, i32* %retval, align 4, !dbg !11
> + br label %return, !dbg !11
> +
> +if.end: ; preds = %entry
> + store i32 3, i32* %retval, align 4, !dbg !12
> + br label %return, !dbg !12
> +
> +return: ; preds = %if.end,
> %if.then
> + %1 = load i32, i32* %retval, align 4, !dbg !13
> + ret i32 %1, !dbg !13
> +}
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!6, !7}
> +!llvm.ident = !{!8}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer:
> "clang version 3.8.0 (trunk 251524) (llvm/trunk 251531)", isOptimized:
> false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3)
> +!1 = !DIFile(filename: "coverage-warning.c", directory: ".")
> +!2 = !{}
> +!3 = !{!4}
> +!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1,
> type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags:
> DIFlagPrototyped, isOptimized: false, function: i32 (i32)* @foo, variables:
> !2)
> +!5 = !DISubroutineType(types: !2)
> +!6 = !{i32 2, !"Dwarf Version", i32 4}
> +!7 = !{i32 2, !"Debug Info Version", i32 3}
> +!8 = !{!"clang version 3.8.0 (trunk 251524) (llvm/trunk 251531)"}
> +!9 = !DILocation(line: 2, column: 7, scope: !4)
> +!10 = !DILocation(line: 2, column: 9, scope: !4)
> +!11 = !DILocation(line: 3, column: 5, scope: !4)
> +!12 = !DILocation(line: 4, column: 3, scope: !4)
> +!13 = !DILocation(line: 5, column: 1, scope: !4)
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151029/965570c2/attachment-0001.html>
More information about the llvm-commits
mailing list