-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Ensure collectTransitivePredecessors
returns Pred only from the Loop.
#113831
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
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Manish Kausik H (Nirhar) ChangesIt's possible that we encounter Irreducible control flow, due to which, we may find that a few predecessors of BB are not a part of the CurLoop. Currently we crash in the function for such cases. This patch ensures that we only return Predecessors that are a part of CurLoop and gracefully ignore other Predecessors. For example, consider Irreducible IR of this form:
This crashes when Full diff: https://github.com/llvm/llvm-project/pull/113831.diff 1 Files Affected:
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index caed62679a683c..8e233a5c8d7a54 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -162,6 +162,9 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
/// Collect all blocks from \p CurLoop which lie on all possible paths from
/// the header of \p CurLoop (inclusive) to BB (exclusive) into the set
/// \p Predecessors. If \p BB is the header, \p Predecessors will be empty.
+/// Note: It's possible that we encounter Irreducible control flow, due to
+/// which, we may find that a few predecessors of \p BB are not a part of the
+/// \p CurLoop. We only return Predecessors that are a part of \p CurLoop.
static void collectTransitivePredecessors(
const Loop *CurLoop, const BasicBlock *BB,
SmallPtrSetImpl<const BasicBlock *> &Predecessors) {
@@ -171,6 +174,8 @@ static void collectTransitivePredecessors(
return;
SmallVector<const BasicBlock *, 4> WorkList;
for (const auto *Pred : predecessors(BB)) {
+ if (!CurLoop->contains(Pred))
+ continue;
Predecessors.insert(Pred);
WorkList.push_back(Pred);
}
@@ -187,7 +192,7 @@ static void collectTransitivePredecessors(
// We can ignore backedge of all loops containing BB to get a sligtly more
// optimistic result.
for (const auto *PredPred : predecessors(Pred))
- if (Predecessors.insert(PredPred).second)
+ if (CurLoop->contains(PredPred) && Predecessors.insert(PredPred).second)
WorkList.push_back(PredPred);
}
}
|
9bb2c5e
to
e9731bd
Compare
Needs tests |
I'm not sure how I can write a lit test for this, reason being, most of the loop transformation passes run |
You can directly run the must-execute analysis printer and check the output. Tests ideally run in isolation, the context where it is used in the pass pipeline should not matter |
It's possible that we encounter Irreducible control flow, due to which, we may find that a few predecessors of BB are not a part of the CurLoop. Currently we crash in the function for such cases. This patch ensures that we only return Predecessors that are a part of CurLoop and gracefully ignore other Predecessors. For example, consider Irreducible IR of this form: ``` define i64 @baz() { bb: br label %bb1 bb1: ; preds = %bb3, %bb br label %bb3 bb2: ; No predecessors! br label %bb3 bb3: ; preds = %bb2, %bb1 %load = load ptr addrspace(1), ptr addrspace(1) null, align 8 br label %bb1 } ``` This crashes when `collectTransitivePredecessors` is called on the `%bb1<Header>, %bb3<latch>` loop, because the loop body has a predecessor `%bb2` which is not a part of the loop.
e9731bd
to
3ab467b
Compare
@arsenm Thanks for the idea! Have added a lit test. |
@arsenm Can you merge it? I don't have merge permissions. Thanks! |
…p. (llvm#113831) It's possible that we encounter Irreducible control flow, due to which, we may find that a few predecessors of BB are not a part of the CurLoop. Currently we crash in the function for such cases. This patch ensures that we only return Predecessors that are a part of CurLoop and gracefully ignore other Predecessors. For example, consider Irreducible IR of this form: ``` define i64 @baz() { bb: br label %bb1 bb1: ; preds = %bb3, %bb br label %bb3 bb2: ; No predecessors! br label %bb3 bb3: ; preds = %bb2, %bb1 %load = load ptr addrspace(1), ptr addrspace(1) null, align 8 br label %bb1 } ``` This crashes when `collectTransitivePredecessors` is called on the `%bb1<Header>, %bb3<latch>` loop, because the loop body has a predecessor `%bb2` which is not a part of the loop. See https://godbolt.org/z/E9fM1q3cT for the crash
…p. (llvm#113831) It's possible that we encounter Irreducible control flow, due to which, we may find that a few predecessors of BB are not a part of the CurLoop. Currently we crash in the function for such cases. This patch ensures that we only return Predecessors that are a part of CurLoop and gracefully ignore other Predecessors. For example, consider Irreducible IR of this form: ``` define i64 @baz() { bb: br label %bb1 bb1: ; preds = %bb3, %bb br label %bb3 bb2: ; No predecessors! br label %bb3 bb3: ; preds = %bb2, %bb1 %load = load ptr addrspace(1), ptr addrspace(1) null, align 8 br label %bb1 } ``` This crashes when `collectTransitivePredecessors` is called on the `%bb1<Header>, %bb3<latch>` loop, because the loop body has a predecessor `%bb2` which is not a part of the loop. See https://godbolt.org/z/E9fM1q3cT for the crash
It's possible that we encounter Irreducible control flow, due to which, we may find that a few predecessors of BB are not a part of the CurLoop. Currently we crash in the function for such cases. This patch ensures that we only return Predecessors that are a part of CurLoop and gracefully ignore other Predecessors.
For example, consider Irreducible IR of this form:
This crashes when
collectTransitivePredecessors
is called on the%bb1<Header>, %bb3<latch>
loop, because the loop body has a predecessor%bb2
which is not a part of the loop.See https://godbolt.org/z/E9fM1q3cT for the crash