[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