[llvm] [InstCombine] Combine select into select if one of the values match in both of them (PR #177410)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 23 01:08:06 PST 2026


https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/177410

>From 29ada10e4cdfbf8edeed8c08245b4a79ec6659af Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Wed, 21 Jan 2026 12:49:10 +0100
Subject: [PATCH 1/2] Pre commit tests

---
 .../Transforms/InstCombine/select-select.ll   | 144 ++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/select-select.ll b/llvm/test/Transforms/InstCombine/select-select.ll
index 94e88c2f6cbe6..910b1f7ffe656 100644
--- a/llvm/test/Transforms/InstCombine/select-select.ll
+++ b/llvm/test/Transforms/InstCombine/select-select.ll
@@ -531,7 +531,151 @@ define <2 x i8> @strong_order_cmp_eq_ugt_vector_poison3(<2 x i32> %a, <2 x i32>
   ret <2 x i8> %sel.gt
 }
 
+; Minimal code that triigers the optimizations.
 
+define i32 @selectSelect11(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect11(
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[COND2:%.*]], i1 true, i1 [[COND1:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[TMP1]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL:%.*]]
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %defaultVal, i32 %var
+  %sel2 = select i1 %cond2, i32 %defaultVal, i32 %sel1
+  ret i32 %sel2
+}
+
+define i32 @selectSelect22(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect22(
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[COND2:%.*]], i1 [[COND1:%.*]], i1 false
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[TMP1]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL:%.*]]
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %var, i32 %defaultVal
+  %sel2 = select i1 %cond2, i32 %sel1, i32 %defaultVal
+  ret i32 %sel2
+}
+
+define i32 @selectSelect12(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect12(
+; CHECK-NEXT:    [[SEL3:%.*]] = select i1 [[TMP1:%.*]], i32 [[DEFAULTVAL:%.*]], i32 [[VAR:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[SEL3]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %defaultVal,i32 %var
+  %sel2 = select i1 %cond2, i32 %sel1, i32 %defaultVal
+  ret i32 %sel2
+}
+
+define i32 @selectSelect21(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect21(
+; CHECK-NEXT:    [[DEFAULTVAL:%.*]] = select i1 [[TMP1:%.*]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL1:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[DEFAULTVAL1]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %var, i32 %defaultVal
+  %sel2 = select i1 %cond2, i32 %defaultVal, i32 %sel1
+  ret i32 %sel2
+}
+
+define i32 @selectSelect11Use(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect11Use(
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[DEFAULTVAL:%.*]], i32 [[VAR:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[DEFAULTVAL]], i32 [[SEL1]]
+; CHECK-NEXT:    call void @use32(i32 [[SEL1]])
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %defaultVal, i32 %var
+  %sel2 = select i1 %cond2, i32 %defaultVal, i32 %sel1
+  call void @use32(i32 %sel1)
+  ret i32 %sel2
+}
+
+define i32 @selectSelect22Use(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect22Use(
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[SEL1]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    call void @use32(i32 [[SEL1]])
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %var, i32 %defaultVal
+  %sel2 = select i1 %cond2, i32 %sel1, i32 %defaultVal
+  call void @use32(i32 %sel1)
+  ret i32 %sel2
+}
+
+define i32 @selectSelect12Use(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect12Use(
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[DEFAULTVAL:%.*]], i32 [[VAR:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[SEL1]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    call void @use32(i32 [[SEL1]])
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %defaultVal,i32 %var
+  %sel2 = select i1 %cond2, i32 %sel1, i32 %defaultVal
+  call void @use32(i32 %sel1)
+  ret i32 %sel2
+}
+
+define i32 @selectSelect21Use(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
+; CHECK-LABEL: @selectSelect21Use(
+; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[DEFAULTVAL]], i32 [[SEL1]]
+; CHECK-NEXT:    call void @use32(i32 [[SEL1]])
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %sel1 = select i1 %cond1, i32 %var, i32 %defaultVal
+  %sel2 = select i1 %cond2, i32 %defaultVal, i32 %sel1
+  call void @use32(i32 %sel1)
+  ret i32 %sel2
+}
+
+; Examples from real world prgrams.
+
+define i32 @abseil_cpp_example(i32 %a, i64 %b, i32 %c) {
+; CHECK-LABEL: @abseil_cpp_example(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64 [[B:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[B]], 0
+; CHECK-NEXT:    [[SPEC_SELECT632:%.*]] = select i1 [[CMP2]], i32 0, i32 [[A:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP1]], i32 [[A]], i32 [[SPEC_SELECT632]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %cmp1 = icmp eq i64 %b, 0
+  %cmp2 = icmp slt i64 %b, 0
+  %spec.select632 = select i1 %cmp2, i32 0, i32 %a
+  %85 = select i1 %cmp1, i32 %a, i32 %spec.select632
+  ret i32 %85
+}
+
+define i32 @hermes_example(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @hermes_example(
+; CHECK-NEXT:    [[CMP108_I:%.*]] = icmp slt i32 [[A:%.*]], 9
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[A]], 17
+; CHECK-NEXT:    [[Z_5_I:%.*]] = select i1 [[TMP2]], i32 [[B:%.*]], i32 [[C:%.*]]
+; CHECK-NEXT:    [[Z_5_I1:%.*]] = select i1 [[CMP108_I]], i32 [[C]], i32 [[Z_5_I]]
+; CHECK-NEXT:    ret i32 [[Z_5_I1]]
+;
+  %cmp108.i = icmp slt i32 %a, 9
+  %cmp113.i = icmp slt i32 %a, 17
+  %spec.select.i = select i1 %cmp113.i, i32 %c, i32 %b
+  %z.5.i = select i1 %cmp108.i, i32 %b, i32 %spec.select.i
+  ret i32 %z.5.i
+}
+
+define i64 @hermes_example2(i32 %a, i64 %b, i64 %c) {
+; CHECK-LABEL: @hermes_example2(
+; CHECK-NEXT:    [[CMP16_I_I:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP20_I_I:%.*]] = icmp ugt i32 [[A]], 511
+; CHECK-NEXT:    [[RETVAL_0_I_I:%.*]] = select i1 [[CMP20_I_I]], i64 [[C:%.*]], i64 [[B:%.*]]
+; CHECK-NEXT:    [[RETVAL_0_I_I1:%.*]] = select i1 [[CMP16_I_I]], i64 [[B]], i64 [[RETVAL_0_I_I]]
+; CHECK-NEXT:    ret i64 [[RETVAL_0_I_I1]]
+;
+  %cmp16.i.i = icmp eq i32 %a, 0
+  %cmp20.i.i = icmp ugt i32 %a, 511
+  %spec.select11.i = select i1 %cmp20.i.i, i64 %b, i64 %c
+  %retval.0.i.i = select i1 %cmp16.i.i, i64 %c, i64 %spec.select11.i
+  ret i64 %retval.0.i.i
+}
 
 declare void @use1(i1)
 declare void @use8(i8)
+declare void @use32(i32)

>From aa9ead9b233d3ec3a6ff14bb53018c7e62e69c66 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Thu, 22 Jan 2026 18:36:13 +0100
Subject: [PATCH 2/2] [InstCombine] Combine select into select if one of the
 values match in both of them

Address cases like:
```
select(C0, select(C1, b, a), b) -> select(C0&!C1, a, b)
select(C0, a, select(C1, b, a)) -> select(C0|!C1, a, b)
```

It seem that it generates better code for the few targets I have checked: https://godbolt.org/z/KeEMd9b8E .
On the most generic case it generates the same code for the sources and targets for all targets, expect RISC-V, where the targets seem shoretr and better (less branching).

Proofs: https://alive2.llvm.org/ce/z/DoL3zQ
---
 .../InstCombine/InstCombineSelect.cpp         | 16 +++++++
 llvm/test/Transforms/InstCombine/pr63791.ll   |  2 +-
 .../select-of-symmetric-selects.ll            |  5 ++-
 .../Transforms/InstCombine/select-select.ll   | 42 ++++++++++++-------
 llvm/test/Transforms/InstCombine/select.ll    | 12 +++---
 5 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index d4604e05de688..4f700c0cdf7c0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -4525,6 +4525,14 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
         replaceOperand(SI, 1, TrueSI->getTrueValue());
         return &SI;
       }
+      // select(C0, select(C1, b, a), b) -> select(C0&!C1, a, b)
+      if (TrueSI->getTrueValue() == FalseVal && TrueSI->hasOneUse()) {
+        Value *Negation = Builder.CreateNot(TrueSI->getCondition());
+        Value *And = Builder.CreateLogicalAnd(CondVal, Negation);
+        replaceOperand(SI, 0, And);
+        replaceOperand(SI, 1, TrueSI->getFalseValue());
+        return &SI;
+      }
     }
   }
   if (SelectInst *FalseSI = dyn_cast<SelectInst>(FalseVal)) {
@@ -4542,6 +4550,14 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
         replaceOperand(SI, 2, FalseSI->getFalseValue());
         return &SI;
       }
+      // select(C0, a, select(C1, b, a)) -> select(C0|!C1, a, b)
+      if (FalseSI->getFalseValue() == TrueVal && FalseSI->hasOneUse()) {
+        Value *Negation = Builder.CreateNot(FalseSI->getCondition());
+        Value *Or = Builder.CreateLogicalOr(CondVal, Negation);
+        replaceOperand(SI, 0, Or);
+        replaceOperand(SI, 2, FalseSI->getTrueValue());
+        return &SI;
+      }
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/pr63791.ll b/llvm/test/Transforms/InstCombine/pr63791.ll
index 78cc1130fb33f..73a559f989261 100644
--- a/llvm/test/Transforms/InstCombine/pr63791.ll
+++ b/llvm/test/Transforms/InstCombine/pr63791.ll
@@ -15,7 +15,7 @@ define void @y() {
 ; CHECK-NEXT:    store i1 true, ptr poison, align 1
 ; CHECK-NEXT:    br i1 poison, label [[FOR_COND_I]], label [[FOR_COND5_PREHEADER_I]]
 ; CHECK:       for.cond5.preheader.i:
-; CHECK-NEXT:    br i1 false, label [[FOR_INC19_I:%.*]], label [[FOR_COND1_LOOPEXIT_I:%.*]]
+; CHECK-NEXT:    br i1 true, label [[FOR_COND1_LOOPEXIT_I:%.*]], label [[FOR_INC19_I:%.*]]
 ; CHECK:       for.inc19.i:
 ; CHECK-NEXT:    br i1 poison, label [[FOR_INC19_I]], label [[FOR_COND1_LOOPEXIT_I]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/select-of-symmetric-selects.ll b/llvm/test/Transforms/InstCombine/select-of-symmetric-selects.ll
index 0936f58ac9443..70c89109f3dbc 100644
--- a/llvm/test/Transforms/InstCombine/select-of-symmetric-selects.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-symmetric-selects.ll
@@ -15,8 +15,9 @@ define i32 @select_of_symmetric_selects(i32 %a, i32 %b, i1 %c1, i1 %c2) {
 
 define i32 @select_of_symmetric_selects_negative1(i32 %a, i32 %b, i1 %c1, i1 %c2) {
 ; CHECK-LABEL: @select_of_symmetric_selects_negative1(
-; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[C1:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = select i1 [[C2:%.*]], i32 [[SEL1]], i32 [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[C1:%.*]], true
+; CHECK-NEXT:    [[C2:%.*]] = select i1 [[C3:%.*]], i1 [[TMP1]], i1 false
+; CHECK-NEXT:    [[RET:%.*]] = select i1 [[C2]], i32 [[SEL1:%.*]], i32 [[A:%.*]]
 ; CHECK-NEXT:    ret i32 [[RET]]
 ;
   %sel1 = select i1 %c1, i32 %a, i32 %b
diff --git a/llvm/test/Transforms/InstCombine/select-select.ll b/llvm/test/Transforms/InstCombine/select-select.ll
index 910b1f7ffe656..7a63e8efed104 100644
--- a/llvm/test/Transforms/InstCombine/select-select.ll
+++ b/llvm/test/Transforms/InstCombine/select-select.ll
@@ -557,8 +557,9 @@ define i32 @selectSelect22(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
 
 define i32 @selectSelect12(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
 ; CHECK-LABEL: @selectSelect12(
-; CHECK-NEXT:    [[SEL3:%.*]] = select i1 [[TMP1:%.*]], i32 [[DEFAULTVAL:%.*]], i32 [[VAR:%.*]]
-; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[SEL3]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[COND1:%.*]], true
+; CHECK-NEXT:    [[COND2:%.*]] = select i1 [[COND3:%.*]], i1 [[TMP1]], i1 false
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2]], i32 [[SEL3:%.*]], i32 [[DEFAULTVAL:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL2]]
 ;
   %sel1 = select i1 %cond1, i32 %defaultVal,i32 %var
@@ -568,8 +569,9 @@ define i32 @selectSelect12(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
 
 define i32 @selectSelect21(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
 ; CHECK-LABEL: @selectSelect21(
-; CHECK-NEXT:    [[DEFAULTVAL:%.*]] = select i1 [[TMP1:%.*]], i32 [[VAR:%.*]], i32 [[DEFAULTVAL1:%.*]]
-; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 [[DEFAULTVAL1]], i32 [[DEFAULTVAL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[COND1:%.*]], true
+; CHECK-NEXT:    [[COND2:%.*]] = select i1 [[COND3:%.*]], i1 true, i1 [[TMP1]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[COND2]], i32 [[DEFAULTVAL1:%.*]], i32 [[DEFAULTVAL:%.*]]
 ; CHECK-NEXT:    ret i32 [[SEL2]]
 ;
   %sel1 = select i1 %cond1, i32 %var, i32 %defaultVal
@@ -633,10 +635,8 @@ define i32 @selectSelect21Use(i1 %cond1, i1 %cond2, i32 %var, i32 %defaultVal) {
 
 define i32 @abseil_cpp_example(i32 %a, i64 %b, i32 %c) {
 ; CHECK-LABEL: @abseil_cpp_example(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64 [[B:%.*]], 0
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[B]], 0
-; CHECK-NEXT:    [[SPEC_SELECT632:%.*]] = select i1 [[CMP2]], i32 0, i32 [[A:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP1]], i32 [[A]], i32 [[SPEC_SELECT632]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[B:%.*]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP2]], i32 [[A:%.*]], i32 0
 ; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
   %cmp1 = icmp eq i64 %b, 0
@@ -648,10 +648,9 @@ define i32 @abseil_cpp_example(i32 %a, i64 %b, i32 %c) {
 
 define i32 @hermes_example(i32 %a, i32 %b, i32 %c) {
 ; CHECK-LABEL: @hermes_example(
-; CHECK-NEXT:    [[CMP108_I:%.*]] = icmp slt i32 [[A:%.*]], 9
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[A]], 17
-; CHECK-NEXT:    [[Z_5_I:%.*]] = select i1 [[TMP2]], i32 [[B:%.*]], i32 [[C:%.*]]
-; CHECK-NEXT:    [[Z_5_I1:%.*]] = select i1 [[CMP108_I]], i32 [[C]], i32 [[Z_5_I]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -17
+; CHECK-NEXT:    [[CMP108_I:%.*]] = icmp ult i32 [[TMP1]], -8
+; CHECK-NEXT:    [[Z_5_I1:%.*]] = select i1 [[CMP108_I]], i32 [[C:%.*]], i32 [[Z_5_I:%.*]]
 ; CHECK-NEXT:    ret i32 [[Z_5_I1]]
 ;
   %cmp108.i = icmp slt i32 %a, 9
@@ -663,10 +662,8 @@ define i32 @hermes_example(i32 %a, i32 %b, i32 %c) {
 
 define i64 @hermes_example2(i32 %a, i64 %b, i64 %c) {
 ; CHECK-LABEL: @hermes_example2(
-; CHECK-NEXT:    [[CMP16_I_I:%.*]] = icmp eq i32 [[A:%.*]], 0
-; CHECK-NEXT:    [[CMP20_I_I:%.*]] = icmp ugt i32 [[A]], 511
-; CHECK-NEXT:    [[RETVAL_0_I_I:%.*]] = select i1 [[CMP20_I_I]], i64 [[C:%.*]], i64 [[B:%.*]]
-; CHECK-NEXT:    [[RETVAL_0_I_I1:%.*]] = select i1 [[CMP16_I_I]], i64 [[B]], i64 [[RETVAL_0_I_I]]
+; CHECK-NEXT:    [[CMP16_I_I:%.*]] = icmp ult i32 [[A:%.*]], 512
+; CHECK-NEXT:    [[RETVAL_0_I_I1:%.*]] = select i1 [[CMP16_I_I]], i64 [[B:%.*]], i64 [[RETVAL_0_I_I:%.*]]
 ; CHECK-NEXT:    ret i64 [[RETVAL_0_I_I1]]
 ;
   %cmp16.i.i = icmp eq i32 %a, 0
@@ -676,6 +673,19 @@ define i64 @hermes_example2(i32 %a, i64 %b, i64 %c) {
   ret i64 %retval.0.i.i
 }
 
+define i32 @gh82350(i32 %x, i32 %y, i32 %z, i1 %cmp1) {
+; CHECK-LABEL: @gh82350(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[Z:%.*]], 0
+; CHECK-NEXT:    [[DOTNOT:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP1:%.*]]
+; CHECK-NEXT:    [[SEL2:%.*]] = select i1 [[DOTNOT]], i32 [[X:%.*]], i32 [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[SEL2]]
+;
+  %cmp2 = icmp eq i32 %z, 0
+  %sel1 = select i1 %cmp1, i32 %x, i32 %y
+  %sel2 = select i1 %cmp2, i32 %sel1, i32 %x
+  ret i32 %sel2
+}
+
 declare void @use1(i1)
 declare void @use8(i8)
 declare void @use32(i32)
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index db117aa28cad6..6076a18b6501c 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -1400,10 +1400,10 @@ define i128 @test86(i1 %flag) {
 define i32 @test_select_select0(i32 %a, i32 %r0, i32 %r1, i32 %v1, i32 %v2) {
 ; CHECK-LABEL: define i32 @test_select_select0(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[R0:%.*]], i32 [[R1:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]]) {
-; CHECK-NEXT:    [[C0_NOT:%.*]] = icmp slt i32 [[A]], [[V1]]
-; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C0_NOT]], i32 [[R1]], i32 [[R0]]
+; CHECK-NEXT:    [[C0_NOT:%.*]] = icmp sge i32 [[A]], [[V1]]
 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[A]], [[V2]]
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 [[R1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[C1]], i1 [[C0_NOT]], i1 false
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[TMP1]], i32 [[R0]], i32 [[R1]]
 ; CHECK-NEXT:    ret i32 [[S1]]
 ;
   %c0 = icmp sge i32 %a, %v1
@@ -1416,10 +1416,10 @@ define i32 @test_select_select0(i32 %a, i32 %r0, i32 %r1, i32 %v1, i32 %v2) {
 define i32 @test_select_select1(i32 %a, i32 %r0, i32 %r1, i32 %v1, i32 %v2) {
 ; CHECK-LABEL: define i32 @test_select_select1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[R0:%.*]], i32 [[R1:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]]) {
-; CHECK-NEXT:    [[C0_NOT:%.*]] = icmp slt i32 [[A]], [[V1]]
-; CHECK-NEXT:    [[S0:%.*]] = select i1 [[C0_NOT]], i32 [[R1]], i32 [[R0]]
+; CHECK-NEXT:    [[C0_NOT:%.*]] = icmp sge i32 [[A]], [[V1]]
 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 [[A]], [[V2]]
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[C1]], i32 [[R0]], i32 [[S0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[C1]], i1 true, i1 [[C0_NOT]]
+; CHECK-NEXT:    [[S1:%.*]] = select i1 [[TMP1]], i32 [[R0]], i32 [[R1]]
 ; CHECK-NEXT:    ret i32 [[S1]]
 ;
   %c0 = icmp sge i32 %a, %v1



More information about the llvm-commits mailing list