[PGO] Fix insane counts due to nonreturn calls
authorRong Xu <xur@google.com>
Tue, 13 Dec 2016 06:41:14 +0000 (06:41 +0000)
committerRong Xu <xur@google.com>
Tue, 13 Dec 2016 06:41:14 +0000 (06:41 +0000)
Summary:
Since we don't break BBs for function calls. We might get some insane counts
(wrap of unsigned) in the presence of noreturn calls.

This patch sets these counts to zero instead of the wrapped number.

Reviewers: davidxl

Subscribers: xur, eraman, llvm-commits

Differential Revision: https://reviews.llvm.org/D27602

llvm-svn: 289521

llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
llvm/test/Transforms/PGOProfile/Inputs/noreturncall.proftext [new file with mode: 0644]
llvm/test/Transforms/PGOProfile/noreturncall.ll [new file with mode: 0644]

index d802295..28f4f7e 100644 (file)
@@ -884,12 +884,21 @@ void PGOUseFunc::populateCounters() {
       }
       if (Count->CountValid) {
         if (Count->UnknownCountOutEdge == 1) {
-          uint64_t Total = Count->CountValue - sumEdgeCount(Count->OutEdges);
+          uint64_t Total = 0;
+          uint64_t OutSum = sumEdgeCount(Count->OutEdges);
+          // If the one of the successor block can early terminate (no-return),
+          // we can end up with situation where out edge sum count is larger as
+          // the source BB's count is collected by a post-dominated block.
+          if (Count->CountValue > OutSum)
+            Total = Count->CountValue - OutSum;
           setEdgeCount(Count->OutEdges, Total);
           Changes = true;
         }
         if (Count->UnknownCountInEdge == 1) {
-          uint64_t Total = Count->CountValue - sumEdgeCount(Count->InEdges);
+          uint64_t Total = 0;
+          uint64_t InSum = sumEdgeCount(Count->InEdges);
+          if (Count->CountValue > InSum)
+            Total = Count->CountValue - InSum;
           setEdgeCount(Count->InEdges, Total);
           Changes = true;
         }
diff --git a/llvm/test/Transforms/PGOProfile/Inputs/noreturncall.proftext b/llvm/test/Transforms/PGOProfile/Inputs/noreturncall.proftext
new file mode 100644 (file)
index 0000000..73ee83f
--- /dev/null
@@ -0,0 +1,11 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+36496524737
+# Num Counters:
+3
+# Counter Values:
+20
+21
+0
diff --git a/llvm/test/Transforms/PGOProfile/noreturncall.ll b/llvm/test/Transforms/PGOProfile/noreturncall.ll
new file mode 100644 (file)
index 0000000..602ebeb
--- /dev/null
@@ -0,0 +1,46 @@
+; RUN: llvm-profdata merge %S/Inputs/noreturncall.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -debug-only=pgo-instrumentation 2>&1 | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S -debug-only=pgo-instrumentation 2>&1 | FileCheck %s --check-prefix=USE
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @bar0(i32)
+
+define i32 @bar2(i32 %i) {
+entry:
+  unreachable
+}
+
+define i32 @foo(i32 %i, i32 %j, i32 %k) {
+entry:
+  %cmp = icmp slt i32 %i, 999
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %call = call i32 @bar0(i32 %i)
+  br label %if.end
+
+if.end:
+  %ret.0 = phi i32 [ %call, %if.then ], [ 0, %entry ]
+  %cmp1 = icmp sgt i32 %j, 1000
+  %cmp3 = icmp sgt i32 %k, 99
+  %or.cond = and i1 %cmp1, %cmp3
+  br i1 %or.cond, label %if.then4, label %if.end7
+
+if.then4:
+  %call5 = call i32 @bar2(i32 undef)
+  br label %if.end7
+
+if.end7:
+  %mul = mul nsw i32 %ret.0, %ret.0
+  ret i32 %mul
+}
+; USE:  Edge 0: 1-->3  c  W=8000  Count=0
+; USE:  Edge 1: 3-->5  c  W=8000  Count=20
+; USE:  Edge 2: 0-->1     W=16  Count=21
+; USE:  Edge 3: 5-->0 *   W=16  Count=20
+; USE:  Edge 4: 1-->2     W=8  Count=21
+; USE:  Edge 5: 2-->3 *   W=8  Count=21
+; USE:  Edge 6: 3-->4     W=8  Count=0
+; USE:  Edge 7: 4-->5 *   W=8  Count=0