-
Notifications
You must be signed in to change notification settings - Fork 13.9k
[ctx_prof] Fix ProfileAnnotator::allTakenPathsExit
#109183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ctx_prof] Fix ProfileAnnotator::allTakenPathsExit
#109183
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
2 similar comments
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Author: Mircea Trofin (mtrofin) ChangesAdded tests to the validator and fixed issues stemming from the previous skipping over BBs with single successors - which is incorrect. That would be now picked by added tests where the assertions are expected to be triggered. Full diff: https://github.com/llvm/llvm-project/pull/109183.diff 2 Files Affected:
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
|
@llvm/pr-subscribers-pgo Author: Mircea Trofin (mtrofin) ChangesAdded tests to the validator and fixed issues stemming from the previous skipping over BBs with single successors - which is incorrect. That would be now picked by added tests where the assertions are expected to be triggered. Full diff: https://github.com/llvm/llvm-project/pull/109183.diff 2 Files Affected:
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of small comments but otherwise lgtm
const auto &BBInfo = getBBInfo(*BB); | ||
bool Inserted = false; | ||
bool HasAWayOut = false; | ||
for (auto I = 0U; I < BB->getTerminator()->getNumSuccessors(); ++I) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this use succ_size as used above, for consistency? And maybe call that once and save the result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer using this current API (getNumSuccessors
) here, they should be the same, but this is "closer" to the API used below (BB->getTerminator()->getSuccessor
).
@@ -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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you are trying to say by "are not disconsidered" here, especially with the double-negative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clarified.
6d23eef
to
1c6e49a
Compare
3 similar comments
1c6e49a
to
bbb3ba0
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/6033 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/89/builds/6666 Here is the relevant piece of the build log for the reference
|
Added tests to the validator and fixed issues stemming from the previous skipping over BBs with single successors - which is incorrect. That would be now picked by added tests where the assertions are expected to be triggered.
Added tests to the validator and fixed issues stemming from the previous skipping over BBs with single successors - which is incorrect. That would be now picked by added tests where the assertions are expected to be triggered.