-
Notifications
You must be signed in to change notification settings - Fork 12k
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
[JumpThreading] Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed. #58812
Comments
Reduced: ; RUN: opt -S -jump-threading < %s
define void @test() {
entry:
br i1 false, label %loop, label %exit
loop:
%bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ]
%cmp = icmp eq i16 0, 1
%xor = xor i1 %cmp, %bool
br i1 %bool, label %loop.latch, label %exit
loop.latch:
%dummy = phi i16 [ 0, %loop ]
br label %loop
exit:
ret void
} |
Hi @nikic ! Thanks for this amazing reduced IR! This loop looks like dead code because the entry block jumps directly to exit. Should we arrange *DCE before JumpThreading in the pipeline? Locally I made a patch solved this issue that check diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 75bc4bb76260..43fdfd225150 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1932,7 +1932,7 @@ bool JumpThreadingPass::processBranchOnXOR(BinaryOperator *BO) {
// If all preds provide undef, just nuke the xor, because it is undef too.
BO->replaceAllUsesWith(UndefValue::get(BO->getType()));
BO->eraseFromParent();
- } else if (SplitVal->isZero()) {
+ } else if (SplitVal->isZero() && BO != BO->getOperand(isLHS)) {
// If all preds provide 0, replace the xor with the other input.
BO->replaceAllUsesWith(BO->getOperand(isLHS));
BO->eraseFromParent(); |
JumpThreading already removes unreachable blocks before it runs. However, new ones may be introduced as a result of transforms. It's either necessary to consistently remove them during transforms (this is probably hard because JT cannot use DT for compile-time reasons) or be robust against unreachable code. |
Reproducer: ; RUN: opt -S -jump-threading < %s define void @test() { entry: br i1 false, label %loop, label %exit loop: %bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ] %cmp = icmp eq i16 0, 1 %xor = xor i1 %cmp, %bool br i1 %bool, label %loop.latch, label %exit loop.latch: %dummy = phi i16 [ 0, %loop ] br label %loop exit: ret void } On this occassion, phi node %bool is actually %xor, and doing substitution causes assertion failure. Fixes: llvm/llvm-project#58812 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D139783
Reproducer: ; RUN: opt -S -jump-threading < %s define void @test() { entry: br i1 false, label %loop, label %exit loop: %bool = phi i1 [ %xor, %loop.latch ], [ false, %entry ] %cmp = icmp eq i16 0, 1 %xor = xor i1 %cmp, %bool br i1 %bool, label %loop.latch, label %exit loop.latch: %dummy = phi i16 [ 0, %loop ] br label %loop exit: ret void } On this occassion, phi node %bool is actually %xor, and doing substitution causes assertion failure. Fixes: llvm/llvm-project#58812 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D139783
Godbolt repro: https://godbolt.org/z/M4brh6cGo
Run clang++ on the following test:
Test.cpp.txt
Backtrace:
The text was updated successfully, but these errors were encountered: