[llvm] r250873 - Tolerate negative offset when matching sample profile.

Dehao Chen via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 20 18:22:27 PDT 2015


Author: dehao
Date: Tue Oct 20 20:22:27 2015
New Revision: 250873

URL: http://llvm.org/viewvc/llvm-project?rev=250873&view=rev
Log:
Tolerate negative offset when matching sample profile.

In some cases (as illustrated in the unittest), lineno can be less than the heade_lineno because the function body are included from some other files. In this case, offset will be negative. This patch makes clang still able to match the profile to IR in this situation.

http://reviews.llvm.org/D13914


Added:
    llvm/trunk/test/Transforms/SampleProfile/Inputs/offset.prof
    llvm/trunk/test/Transforms/SampleProfile/offset.ll
Modified:
    llvm/trunk/lib/ProfileData/SampleProfReader.cpp
    llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp

Modified: llvm/trunk/lib/ProfileData/SampleProfReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=250873&r1=250872&r2=250873&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp Tue Oct 20 20:22:27 2015
@@ -100,6 +100,12 @@ static bool ParseHead(const StringRef &I
   return true;
 }
 
+
+/// \brief Returns true if line offset \p L is legal (only has 16 bits).
+static bool isOffsetLegal(unsigned L) {
+  return (L & 0xffff) == L;
+}
+
 /// \brief Parse \p Input as line sample.
 ///
 /// \param Input input line.
@@ -124,7 +130,7 @@ static bool ParseLine(const StringRef &I
   StringRef Loc = Input.substr(Depth, n1 - Depth);
   size_t n2 = Loc.find('.');
   if (n2 == StringRef::npos) {
-    if (Loc.getAsInteger(10, LineOffset))
+    if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset))
       return false;
     Discriminator = 0;
   } else {
@@ -308,6 +314,10 @@ SampleProfileReaderBinary::readProfile(F
     if (std::error_code EC = LineOffset.getError())
       return EC;
 
+    if (!isOffsetLegal(*LineOffset)) {
+      return std::error_code();
+    }
+
     auto Discriminator = readNumber<uint64_t>();
     if (std::error_code EC = Discriminator.getError())
       return EC;

Modified: llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp?rev=250873&r1=250872&r2=250873&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp Tue Oct 20 20:22:27 2015
@@ -122,6 +122,7 @@ protected:
   void buildEdges(Function &F);
   bool propagateThroughEdges(Function &F);
   void computeDominanceAndLoopInfo(Function &F);
+  unsigned getOffset(unsigned L, unsigned H) const;
 
   /// \brief Map basic blocks to their computed weights.
   ///
@@ -174,6 +175,17 @@ protected:
 };
 }
 
+/// \brief Returns the offset of lineno \p L to head_lineno \p H
+///
+/// \param L  Lineno
+/// \param H  Header lineno of the function
+///
+/// \returns offset to the header lineno. 16 bits are used to represent offset.
+/// We assume that a single function will not exceed 65535 LOC.
+unsigned SampleProfileLoader::getOffset(unsigned L, unsigned H) const {
+  return (L - H) & 0xffff;
+}
+
 /// \brief Print the weight of edge \p E on stream \p OS.
 ///
 /// \param OS  Stream to emit the output to.
@@ -229,11 +241,9 @@ SampleProfileLoader::getInstWeight(const
   const DILocation *DIL = DLoc;
   unsigned Lineno = DLoc.getLine();
   unsigned HeaderLineno = DIL->getScope()->getSubprogram()->getLine();
-  if (Lineno < HeaderLineno)
-    return std::error_code();
 
-  ErrorOr<uint64_t> R =
-      FS->findSamplesAt(Lineno - HeaderLineno, DIL->getDiscriminator());
+  ErrorOr<uint64_t> R = FS->findSamplesAt(getOffset(Lineno, HeaderLineno),
+                                          DIL->getDiscriminator());
   if (R)
     DEBUG(dbgs() << "    " << Lineno << "." << DIL->getDiscriminator() << ":"
                  << Inst << " (line offset: " << Lineno - HeaderLineno << "."
@@ -308,7 +318,7 @@ SampleProfileLoader::findCalleeFunctionS
     return nullptr;
   }
   DISubprogram *SP = DIL->getScope()->getSubprogram();
-  if (!SP || DIL->getLine() < SP->getLine())
+  if (!SP)
     return nullptr;
 
   Function *CalleeFunc = Inst.getCalledFunction();
@@ -321,8 +331,9 @@ SampleProfileLoader::findCalleeFunctionS
   if (FS == nullptr)
     return nullptr;
 
-  return FS->findFunctionSamplesAt(CallsiteLocation(
-      DIL->getLine() - SP->getLine(), DIL->getDiscriminator(), CalleeName));
+  return FS->findFunctionSamplesAt(
+      CallsiteLocation(getOffset(DIL->getLine(), SP->getLine()),
+                       DIL->getDiscriminator(), CalleeName));
 }
 
 /// \brief Get the FunctionSamples for an instruction.
@@ -345,10 +356,10 @@ SampleProfileLoader::findFunctionSamples
   for (const DILocation *DIL = Inst.getDebugLoc(); DIL;
        DIL = DIL->getInlinedAt()) {
     DISubprogram *SP = DIL->getScope()->getSubprogram();
-    if (!SP || DIL->getLine() < SP->getLine())
+    if (!SP)
       return nullptr;
     if (!CalleeName.empty()) {
-      S.push_back(CallsiteLocation(DIL->getLine() - SP->getLine(),
+      S.push_back(CallsiteLocation(getOffset(DIL->getLine(), SP->getLine()),
                                    DIL->getDiscriminator(), CalleeName));
     }
     CalleeName = SP->getLinkageName();

Added: llvm/trunk/test/Transforms/SampleProfile/Inputs/offset.prof
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/offset.prof?rev=250873&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SampleProfile/Inputs/offset.prof (added)
+++ llvm/trunk/test/Transforms/SampleProfile/Inputs/offset.prof Tue Oct 20 20:22:27 2015
@@ -0,0 +1,4 @@
+_Z3fooi:300:1
+ 65532: 1000
+ 65533: 10
+ 65535: 990

Added: llvm/trunk/test/Transforms/SampleProfile/offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/offset.ll?rev=250873&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SampleProfile/offset.ll (added)
+++ llvm/trunk/test/Transforms/SampleProfile/offset.ll Tue Oct 20 20:22:27 2015
@@ -0,0 +1,82 @@
+; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/offset.prof | opt -analyze -branch-prob | FileCheck %s
+
+; Original C++ code for this test case:
+;
+; a.cc:
+; #1
+; #2
+; #3
+; #4
+; #5 int foo(int a) {
+; #6 #include "a.b"
+; #7}
+;
+; a.b:
+; #1 if (a > 0) {
+; #2   return 10;
+; #3 } else {
+; #4   return 20;
+; #5 }
+
+; Function Attrs: nounwind uwtable
+define i32 @_Z3fooi(i32 %a) #0 {
+entry:
+  %retval = alloca i32, align 4
+  %a.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !11, metadata !12), !dbg !13
+  %0 = load i32, i32* %a.addr, align 4, !dbg !14
+  %cmp = icmp sgt i32 %0, 0, !dbg !18
+  br i1 %cmp, label %if.then, label %if.else, !dbg !19
+; CHECK: edge entry -> if.then probability is 0x0147ae14 / 0x80000000 = 1.00%
+; CHECK: edge entry -> if.else probability is 0x7eb851ec / 0x80000000 = 99.00% [HOT edge]
+
+if.then:                                          ; preds = %entry
+  store i32 10, i32* %retval, align 4, !dbg !20
+  br label %return, !dbg !20
+
+if.else:                                          ; preds = %entry
+  store i32 20, i32* %retval, align 4, !dbg !22
+  br label %return, !dbg !22
+
+return:                                           ; preds = %if.else, %if.then
+  %1 = load i32, i32* %retval, align 4, !dbg !24
+  ret i32 %1, !dbg !24
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 250750)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
+!1 = !DIFile(filename: "a.cc", directory: "/tmp")
+!2 = !{}
+!3 = !{!4}
+!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, function: i32 (i32)* @_Z3fooi, variables: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7, !7}
+!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{!"clang version 3.8.0 (trunk 250750)"}
+!11 = !DILocalVariable(name: "a", arg: 1, scope: !4, file: !1, line: 5, type: !7)
+!12 = !DIExpression()
+!13 = !DILocation(line: 5, column: 13, scope: !4)
+!14 = !DILocation(line: 1, column: 5, scope: !15)
+!15 = distinct !DILexicalBlock(scope: !17, file: !16, line: 1, column: 5)
+!16 = !DIFile(filename: "./a.b", directory: "/tmp")
+!17 = !DILexicalBlockFile(scope: !4, file: !16, discriminator: 0)
+!18 = !DILocation(line: 1, column: 7, scope: !15)
+!19 = !DILocation(line: 1, column: 5, scope: !17)
+!20 = !DILocation(line: 2, column: 3, scope: !21)
+!21 = distinct !DILexicalBlock(scope: !15, file: !16, line: 1, column: 12)
+!22 = !DILocation(line: 4, column: 3, scope: !23)
+!23 = distinct !DILexicalBlock(scope: !15, file: !16, line: 3, column: 8)
+!24 = !DILocation(line: 7, column: 1, scope: !25)
+!25 = !DILexicalBlockFile(scope: !4, file: !1, discriminator: 0)




More information about the llvm-commits mailing list