Skip to content

Commit 5e2dcfe

Browse files
authored
[InstCombine] Avoid infinite loop in foldSelectValueEquivalence (#142754)
Before this patch, InstCombine hung because it replaced a value with a more complex one: ``` %sel = select i1 %cmp, i32 %smax, i32 0 -> %sel = select i1 %cmp, i32 %masked, i32 0 -> %sel = select i1 %cmp, i32 %smax, i32 0 -> ... ``` 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.
1 parent 20d7019 commit 5e2dcfe

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,11 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
13121312

13131313
// If NewOp is a constant and OldOp is not replace iff NewOp doesn't
13141314
// contain and undef elements.
1315-
if (match(NewOp, m_ImmConstant()) || NewOp == V) {
1315+
// Make sure that V is always simpler than TrueVal, otherwise we might
1316+
// end up in an infinite loop.
1317+
if (match(NewOp, m_ImmConstant()) ||
1318+
(isa<Instruction>(TrueVal) &&
1319+
is_contained(cast<Instruction>(TrueVal)->operands(), V))) {
13161320
if (isGuaranteedNotToBeUndef(NewOp, SQ.AC, &Sel, &DT))
13171321
return replaceOperand(Sel, Swapped ? 2 : 1, V);
13181322
return nullptr;

llvm/test/Transforms/InstCombine/select-cmp-eq-op-fold.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,23 @@ define i8 @replace_with_y_for_simple_binop_fail(i8 %x, i8 noundef %y, i8 %z, i8
182182
%sel = select i1 %cmp, i8 %mul, i8 %z
183183
ret i8 %sel
184184
}
185+
186+
; Make sure we don't run into an infinite loop.
187+
define i32 @pr142405(i32 noundef %x) {
188+
; CHECK-LABEL: @pr142405(
189+
; CHECK-NEXT: entry:
190+
; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 0)
191+
; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[SMAX]], 65535
192+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[MASKED]]
193+
; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[SMAX]], 1
194+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP]], i32 [[TMP0]], i32 0
195+
; CHECK-NEXT: ret i32 [[AND]]
196+
;
197+
entry:
198+
%smax = call i32 @llvm.smax.i32(i32 %x, i32 0)
199+
%masked = and i32 %smax, 65535
200+
%cmp = icmp eq i32 %x, %masked
201+
%sel = select i1 %cmp, i32 %smax, i32 0
202+
%and = and i32 %sel, 1
203+
ret i32 %and
204+
}

0 commit comments

Comments
 (0)