[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