[llvm] r251568 - SamplePGO - Add flag to check sampling coverage.
Diego Novillo via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 29 06:14:00 PDT 2015
Thanks!
On Thu, Oct 29, 2015 at 5:51 AM, Daniel Jasper <djasper at google.com> wrote:
>
>
> 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/3e20ee51/attachment.html>
More information about the llvm-commits
mailing list