[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