-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[InstCombine] Avoid infinite loop in foldSelectValueEquivalence
#142754
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
No real-world impact :) |
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesBefore this patch, InstCombine hung because it replaced a value with a more complex one:
This patch makes this replacement more conservative. It only performs the replacement iff the new value is one of the operands of the original value. Closes #142405. Full diff: https://github.com/llvm/llvm-project/pull/142754.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index d7d0431a5b8d0..257dc943bd5c1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1312,7 +1312,11 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
// If NewOp is a constant and OldOp is not replace iff NewOp doesn't
// contain and undef elements.
- if (match(NewOp, m_ImmConstant()) || NewOp == V) {
+ // Make sure that V is always simpler than TrueVal, otherwise we might
+ // end up in an infinite loop.
+ if (match(NewOp, m_ImmConstant()) ||
+ (isa<Instruction>(TrueVal) &&
+ is_contained(cast<Instruction>(TrueVal)->operands(), V))) {
if (isGuaranteedNotToBeUndef(NewOp, SQ.AC, &Sel, &DT))
return replaceOperand(Sel, Swapped ? 2 : 1, V);
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/select-cmp-eq-op-fold.ll b/llvm/test/Transforms/InstCombine/select-cmp-eq-op-fold.ll
index 760b1ef055ad3..2e6bbdf5da74d 100644
--- a/llvm/test/Transforms/InstCombine/select-cmp-eq-op-fold.ll
+++ b/llvm/test/Transforms/InstCombine/select-cmp-eq-op-fold.ll
@@ -182,3 +182,23 @@ define i8 @replace_with_y_for_simple_binop_fail(i8 %x, i8 noundef %y, i8 %z, i8
%sel = select i1 %cmp, i8 %mul, i8 %z
ret i8 %sel
}
+
+; Make sure we don't run into an infinite loop.
+define i32 @pr142405(i32 noundef %x) {
+; CHECK-LABEL: @pr142405(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 0)
+; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[SMAX]], 65535
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[MASKED]]
+; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[SMAX]], 1
+; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP]], i32 [[TMP0]], i32 0
+; CHECK-NEXT: ret i32 [[AND]]
+;
+entry:
+ %smax = call i32 @llvm.smax.i32(i32 %x, i32 0)
+ %masked = and i32 %smax, 65535
+ %cmp = icmp eq i32 %x, %masked
+ %sel = select i1 %cmp, i32 %smax, i32 0
+ %and = and i32 %sel, 1
+ ret i32 %and
+}
|
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.
LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/6652 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/169/builds/11978 Here is the relevant piece of the build log for the reference
|
Before this patch, InstCombine hung because it replaced a value with a more complex one:
This patch makes this replacement more conservative. It only performs the replacement iff the new value is one of the operands of the original value.
Closes #142405.