[llvm] c39f8b4 - [Instcombine] Fix infinite loop in visitSelectInst (#173704)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 9 01:31:15 PST 2026


Author: Justin Lebar
Date: 2026-01-09T10:31:11+01:00
New Revision: c39f8b47306e0ad494add86313deda07d5e5df3a

URL: https://github.com/llvm/llvm-project/commit/c39f8b47306e0ad494add86313deda07d5e5df3a
DIFF: https://github.com/llvm/llvm-project/commit/c39f8b47306e0ad494add86313deda07d5e5df3a.diff

LOG: [Instcombine] Fix infinite loop in visitSelectInst (#173704)

Doing a nop replaceOperand leads us into an infinite loop here.

This was found by a fuzzer I'm working on.  The high-level design is to
randomly generate LLVM IR, run a pass on it, and then run the original
and new IR through the interpreter.  They should produce the same
results.  Right now I'm only fuzzing instcombine.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/Transforms/InstCombine/2012-05-28-select-hang.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 480f319801392..1f415ffa8eed2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -4799,13 +4799,13 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
   // select (trunc nsw X to i1), X, Y --> select (trunc nsw X to i1), -1, Y
   // select (trunc nsw X to i1), Y, X --> select (trunc nsw X to i1), Y, 0
   Value *Trunc;
-  if (match(CondVal, m_NUWTrunc(m_Value(Trunc)))) {
+  if (match(CondVal, m_NUWTrunc(m_Value(Trunc))) && !isa<Constant>(Trunc)) {
     if (TrueVal == Trunc)
       return replaceOperand(SI, 1, ConstantInt::get(TrueVal->getType(), 1));
     if (FalseVal == Trunc)
       return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0));
   }
-  if (match(CondVal, m_NSWTrunc(m_Value(Trunc)))) {
+  if (match(CondVal, m_NSWTrunc(m_Value(Trunc))) && !isa<Constant>(Trunc)) {
     if (TrueVal == Trunc)
       return replaceOperand(SI, 1,
                             Constant::getAllOnesValue(TrueVal->getType()));

diff  --git a/llvm/test/Transforms/InstCombine/2012-05-28-select-hang.ll b/llvm/test/Transforms/InstCombine/2012-05-28-select-hang.ll
index b4efe6126763e..e596c22a31e69 100644
--- a/llvm/test/Transforms/InstCombine/2012-05-28-select-hang.ll
+++ b/llvm/test/Transforms/InstCombine/2012-05-28-select-hang.ll
@@ -37,3 +37,30 @@ land.end:                                         ; preds = %land.rhs, %entry
 ; CHECK-LABEL: @func(
 ; CHECK-NOT: select
 }
+
+define i1 @select_no_infinite_loop(i2 %arg0, i2 %arg1, i1 %arg2, i2 %arg3) {
+; CHECK-LABEL: define i1 @select_no_infinite_loop(
+; CHECK-SAME: i2 [[ARG0:%.*]], i2 [[ARG1:%.*]], i1 [[ARG2:%.*]], i2 [[ARG3:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[DOTFR:%.*]] = freeze i2 [[ARG3]]
+; CHECK-NEXT:    [[I:%.*]] = icmp ne i2 [[DOTFR]], -1
+; CHECK-NEXT:    ret i1 [[I]]
+;
+entry:
+  %cmp0 = icmp sgt i2 0, %arg0
+  %zext = zext i1 %arg2 to i2
+  %sel0 = select i1 %cmp0, i2 0, i2 %zext
+  %trunc = trunc i2 %sel0 to i1
+  %sel1 = select i1 %trunc, i2 %arg1, i2 0
+  %cmp1 = icmp sle i1 %cmp0, %trunc
+  %sel2 = select i1 %cmp1, i2 0, i2 %arg1
+  %and = and i2 %zext, %sel2
+  %sel3 = select i1 %arg2, i2 0, i2 %arg3
+  %div = sdiv i2 1, %sel3
+  %cmp2 = icmp uge i2 %sel1, %and
+  %sext = sext i1 %cmp2 to i2
+  %cmp3 = icmp sgt i2 %div, %sext
+  %cmp4 = icmp sgt i2 %sel0, 0
+  %lshr = lshr i1 %cmp3, %cmp4
+  ret i1 %lshr
+}


        


More information about the llvm-commits mailing list