[llvm] [ctx_prof] Fix `ProfileAnnotator::allTakenPathsExit` (PR #109183)

Mircea Trofin via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 18 12:49:10 PDT 2024


https://github.com/mtrofin created https://github.com/llvm/llvm-project/pull/109183

None

>From 6d23eef034b0b8dece993a8bd2294594f1c7992e Mon Sep 17 00:00:00 2001
From: Mircea Trofin <mtrofin at google.com>
Date: Tue, 17 Sep 2024 21:46:47 -0700
Subject: [PATCH] [ctx_prof] Fix `ProfileAnnotator::allTakenPathsExit`

---
 .../Instrumentation/PGOCtxProfFlattening.cpp  | 29 ++++---
 .../CtxProfAnalysis/flatten-check-path.ll     | 85 +++++++++++++++++++
 2 files changed, 104 insertions(+), 10 deletions(-)
 create mode 100644 llvm/test/Analysis/CtxProfAnalysis/flatten-check-path.ll

diff --git a/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp b/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
index e76689e2f5f0a5..91f950e2ba4c3e 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
@@ -233,28 +233,37 @@ class ProfileAnnotator final {
     std::deque<const BasicBlock *> Worklist;
     DenseSet<const BasicBlock *> Visited;
     Worklist.push_back(&F.getEntryBlock());
-    Visited.insert(&F.getEntryBlock());
+    bool HitExit = false;
     while (!Worklist.empty()) {
       const auto *BB = Worklist.front();
       Worklist.pop_front();
-      if (succ_size(BB) <= 1)
+      if (!Visited.insert(BB).second)
         continue;
+      if (succ_size(BB) == 0) {
+        if (isa<UnreachableInst>(BB->getTerminator()))
+          return false;
+        HitExit = true;
+        continue;
+      }
+      if (succ_size(BB) == 1) {
+        llvm::append_range(Worklist, successors(BB));
+        continue;
+      }
       const auto &BBInfo = getBBInfo(*BB);
-      bool Inserted = false;
+      bool HasAWayOut = false;
       for (auto I = 0U; I < BB->getTerminator()->getNumSuccessors(); ++I) {
         const auto *Succ = BB->getTerminator()->getSuccessor(I);
         if (!shouldExcludeEdge(*BB, *Succ)) {
-          if (BBInfo.getEdgeCount(I) > 0)
-            if (Visited.insert(Succ).second) {
-              Worklist.push_back(Succ);
-              Inserted = true;
-            }
+          if (BBInfo.getEdgeCount(I) > 0) {
+            HasAWayOut = true;
+            Worklist.push_back(Succ);
+          }
         }
       }
-      if (!Inserted)
+      if (!HasAWayOut)
         return false;
     }
-    return true;
+    return HitExit;
   }
 
 public:
diff --git a/llvm/test/Analysis/CtxProfAnalysis/flatten-check-path.ll b/llvm/test/Analysis/CtxProfAnalysis/flatten-check-path.ll
new file mode 100644
index 00000000000000..dbe14c3522a8a9
--- /dev/null
+++ b/llvm/test/Analysis/CtxProfAnalysis/flatten-check-path.ll
@@ -0,0 +1,85 @@
+; REQUIRES: asserts
+; Check that the profile annotator works: we hit an exit and non-zero paths to
+; already visited blocks are not disconsidered.
+;
+; RUN: split-file %s %t
+; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_ok.json --output=%t/profile_ok.ctxprofdata
+; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_pump.json --output=%t/profile_pump.ctxprofdata
+; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_unreachable.json --output=%t/profile_unreachable.ctxprofdata
+;
+; RUN: opt -passes=ctx-prof-flatten %t/example_ok.ll -use-ctx-profile=%t/profile_ok.ctxprofdata -S -o - | FileCheck %s
+; RUN: not --crash opt -passes=ctx-prof-flatten %t/message_pump.ll -use-ctx-profile=%t/profile_pump.ctxprofdata -S 2>&1 | FileCheck %s --check-prefix=ASSERTION
+; RUN: not --crash opt -passes=ctx-prof-flatten %t/unreachable.ll -use-ctx-profile=%t/profile_unreachable.ctxprofdata -S 2>&1 | FileCheck %s --check-prefix=ASSERTION
+
+; CHECK: br i1 %x, label %b1, label %exit, !prof ![[PROF1:[0-9]+]]
+; CHECK: br i1 %y, label %blk, label %exit, !prof ![[PROF2:[0-9]+]]
+; CHECK: ![[PROF1]] = !{!"branch_weights", i32 1, i32 1}
+; CHECK: ![[PROF2]] = !{!"branch_weights", i32 0, i32 1}
+; ASSERTION: Assertion `allTakenPathsExit()
+
+; b1->exit is the only way out from b1, but the exit block would have been
+; already visited from blk. That should not result in an assertion, though.
+;--- example_ok.ll
+define void @foo(i32 %t) !guid !0 {
+entry:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 0)
+  br label %blk
+blk:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 1)
+  %x = icmp eq i32 %t, 0
+  br i1 %x, label %b1, label %exit
+b1:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 2)
+  %y = icmp eq i32 %t, 0
+  br i1 %y, label %blk, label %exit
+exit:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 3)
+  ret void
+}
+!0 = !{i64 1234}
+
+;--- profile_ok.json
+[{"Guid":1234, "Counters":[2, 2, 1, 2]}]
+
+;--- message_pump.ll
+; This is a message pump: the loop never exits. This should result in an
+; assertion because we can't reach an exit BB
+
+define void @foo(i32 %t) !guid !0 {
+entry:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 0)  
+  br label %blk
+blk:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 1)
+  %x = icmp eq i32 %t, 0
+  br i1 %x, label %blk, label %exit
+exit:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 2)
+  ret void
+}
+!0 = !{i64 1234}
+
+;--- profile_pump.json
+[{"Guid":1234, "Counters":[2, 10, 0]}]
+
+;--- unreachable.ll
+; An unreachable block is reached, that's an error
+define void @foo(i32 %t) !guid !0 {
+entry:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 0)
+  br label %blk
+blk:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 1)
+  %x = icmp eq i32 %t, 0
+  br i1 %x, label %b1, label %exit
+b1:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 2)
+  unreachable
+exit:
+  call void @llvm.instrprof.increment(ptr @foo, i64 42, i32 42, i32 3)
+  ret void
+}
+!0 = !{i64 1234}
+
+;--- profile_unreachable.json
+[{"Guid":1234, "Counters":[2, 1, 1, 2]}]
\ No newline at end of file



More information about the llvm-commits mailing list