From 0d9b39884236fce8387d64e806985777664155b9 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 4 Jun 2025 17:38:45 +0800 Subject: [PATCH] [InstCombine] Avoid infinite loop in `foldSelectValueEquivalence` --- .../InstCombine/InstCombineSelect.cpp | 6 +++++- .../InstCombine/select-cmp-eq-op-fold.ll | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) 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(TrueVal) && + is_contained(cast(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 +}