[llvm] [InstSimplify] Discard unnecessary `select` when the conditions are `ICmps` with EQ (PR #179183)
Gábor Spaits via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 10 04:02:16 PST 2026
https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/179183
>From c4a689a362f507a2decb492da141fd5b03ac571b Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 6 Feb 2026 17:05:34 +0100
Subject: [PATCH 1/3] Pre commit tests
---
.../Transforms/InstSimplify/select-select.ll | 83 +++++++++++++++++++
1 file changed, 83 insertions(+)
create mode 100644 llvm/test/Transforms/InstSimplify/select-select.ll
diff --git a/llvm/test/Transforms/InstSimplify/select-select.ll b/llvm/test/Transforms/InstSimplify/select-select.ll
new file mode 100644
index 0000000000000..18be61129e186
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/select-select.ll
@@ -0,0 +1,83 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+define i32 @foo(i32 %6, i32 %44) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = xor i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+
+define i32 @fooAndUsed(i32 %6, i32 %44) {
+; CHECK-LABEL: @fooAndUsed(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: call void @use32(i1 [[OR_COND_I]])
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = xor i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ call void @use32(i1 %or.cond.i)
+ ret i32 %.0.i8
+}
+
+define i32 @negSelectSelectICmpICmp(i32 %6, i32 %44) {
+; CHECK-LABEL: @negSelectSelectICmpICmp(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[DOT_I:%.*]] = select i1 [[TMP4]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[TMP3]], i32 [[TMP0]], i32 [[DOT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %..i = select i1 %47, i32 %44, i32 %6
+ %.0.i8 = select i1 %46, i32 %6, i32 %..i
+ ret i32 %.0.i8
+}
+
+define void @negRealExampleBefore(ptr %0, i32 %6, i32 %44) {
+; CHECK-LABEL: @negRealExampleBefore(
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP2:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[DOT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP2]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[TMP4]], i32 [[TMP1]], i32 [[DOT_I]]
+; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0:%.*]], i64 12
+; CHECK-NEXT: store i32 [[DOT0_I8]], ptr [[TMP6]], align 4
+; CHECK-NEXT: ret void
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %..i = select i1 %47, i32 %44, i32 %6
+ %.0.i8 = select i1 %46, i32 %6, i32 %..i
+ %50 = getelementptr inbounds nuw i8, ptr %0, i64 12
+ store i32 %.0.i8, ptr %50
+ ret void
+}
+
+declare void @use32(i1)
>From 02447b623f049092b065d9c0f3d1e253d4fec019 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 6 Feb 2026 17:10:32 +0100
Subject: [PATCH 2/3] Decompose and trees and call
simplifySelectWithEquivalence
---
llvm/lib/Analysis/InstructionSimplify.cpp | 27 +++++++++++++++++++
.../Transforms/InstSimplify/select-select.ll | 7 ++---
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 0e0c092271a38..bc437bd00cf6a 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4482,6 +4482,21 @@ static Value *simplifyWithOpsReplaced(Value *V,
if (NewOps.size() == 2 && match(NewOps[1], m_Zero()))
return NewOps[0];
}
+
+ if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
+ if (SI->hasPoisonGeneratingAnnotations()) {
+ if (!DropFlags)
+ return nullptr;
+
+ DropFlags->push_back(SI);
+ }
+
+ // If both of the arm give the same value and that value isn't poison we
+ // can simplify the select to that value.
+ if (isGuaranteedNotToBePoison(NewOps[1]) && NewOps[1] == NewOps[2])
+ return NewOps[1];
+ }
+
} else {
// The simplification queries below may return the original value. Consider:
// %div = udiv i32 %arg, %arg2
@@ -5142,6 +5157,18 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
return ConstantVector::get(NewC);
}
+ CmpPredicate Pred1, Pred2;
+ Value *V1, *V2, *EQV;
+ if (match(Cond, m_And(m_ICmp(Pred1, m_Value(V1), m_Value(EQV)),
+ m_ICmp(Pred2, m_Value(V2), m_Deferred(EQV))))) {
+ if (Pred1 == ICmpInst::ICMP_EQ && Pred2 == ICmpInst::ICMP_EQ) {
+ if (Value *V = simplifySelectWithEquivalence(
+ {{V2, EQV}, {V1, EQV}}, TrueVal, FalseVal, Q, MaxRecurse)) {
+ return V;
+ }
+ }
+ }
+
if (Value *V =
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
return V;
diff --git a/llvm/test/Transforms/InstSimplify/select-select.ll b/llvm/test/Transforms/InstSimplify/select-select.ll
index 18be61129e186..45d2f05016b5a 100644
--- a/llvm/test/Transforms/InstSimplify/select-select.ll
+++ b/llvm/test/Transforms/InstSimplify/select-select.ll
@@ -5,12 +5,10 @@ define i32 @foo(i32 %6, i32 %44) {
; CHECK-LABEL: @foo(
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
-; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
-; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
-; CHECK-NEXT: ret i32 [[DOT0_I8]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
;
%46 = icmp eq i32 %44, 4
%47 = icmp eq i32 %6, 4
@@ -31,9 +29,8 @@ define i32 @fooAndUsed(i32 %6, i32 %44) {
; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]]
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
-; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
; CHECK-NEXT: call void @use32(i1 [[OR_COND_I]])
-; CHECK-NEXT: ret i32 [[DOT0_I8]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
;
%46 = icmp eq i32 %44, 4
%47 = icmp eq i32 %6, 4
>From 156bf99df31d62956233ec2b559d9f6beacc45b8 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Tue, 10 Feb 2026 12:55:23 +0100
Subject: [PATCH 3/3] Address some of the reviews
I have addressed some of the reviews:
- Flags shall be only removed if there is simplification
- Poison checks
---
llvm/lib/Analysis/InstructionSimplify.cpp | 60 ++++++---
.../Transforms/InstSimplify/select-select.ll | 116 +++++++++++++++++-
2 files changed, 156 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index bc437bd00cf6a..5dcddf9ba938e 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -45,9 +45,14 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Statepoint.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/KnownFPClass.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
#include <optional>
using namespace llvm;
using namespace llvm::PatternMatch;
@@ -4484,17 +4489,22 @@ static Value *simplifyWithOpsReplaced(Value *V,
}
if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
- if (SI->hasPoisonGeneratingAnnotations()) {
- if (!DropFlags)
- return nullptr;
+ Value *SimplifiedValue = nullptr;
- DropFlags->push_back(SI);
- }
+ // Cond ? V : V -> V
+ if (NewOps[1] == NewOps[2] && !impliesPoison(SI, NewOps[0]))
+ SimplifiedValue = NewOps[1];
- // If both of the arm give the same value and that value isn't poison we
- // can simplify the select to that value.
- if (isGuaranteedNotToBePoison(NewOps[1]) && NewOps[1] == NewOps[2])
- return NewOps[1];
+ // If we could do any simplification check if it has any poison generating
+ // flags and handle them.
+ if (SimplifiedValue) {
+ if (SI->hasPoisonGeneratingAnnotations()) {
+ if (!DropFlags)
+ return nullptr;
+ DropFlags->push_back(SI);
+ }
+ return SimplifiedValue;
+ }
}
} else {
@@ -5159,16 +5169,34 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
CmpPredicate Pred1, Pred2;
Value *V1, *V2, *EQV;
- if (match(Cond, m_And(m_ICmp(Pred1, m_Value(V1), m_Value(EQV)),
- m_ICmp(Pred2, m_Value(V2), m_Deferred(EQV))))) {
- if (Pred1 == ICmpInst::ICMP_EQ && Pred2 == ICmpInst::ICMP_EQ) {
- if (Value *V = simplifySelectWithEquivalence(
- {{V2, EQV}, {V1, EQV}}, TrueVal, FalseVal, Q, MaxRecurse)) {
+ if (match(Cond,
+ m_And(m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(V1), m_Value(EQV)),
+ m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(V2),
+ m_Deferred(EQV)))))
+ if (Value *V = simplifySelectWithEquivalence(
+ {{V2, EQV}, {V1, EQV}}, TrueVal, FalseVal, Q, MaxRecurse)) {
+ // We should only throw away a select if we get a select in place of that
+ // because of the poison barrier property.
+ SelectInst *VasSI = dyn_cast<SelectInst>(V);
+ // Also we have to check if the removing of the current select doesn't
+ // introduce any new poison. We should only remove the current select if
+ // its condition is poison in every case where the new select condition is
+ // poison.
+ if (VasSI && impliesPoison(VasSI->getCondition(), Cond))
return V;
- }
}
- }
+// TODO: I'll have to finish this. There is still testing to be done here!
+// if (match(Cond,
+// m_Or(m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(V1), m_Value(EQV)),
+// m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(V2), m_Deferred(EQV))))) {
+//
+// if (Value *V = simplifySelectWithEquivalence({{V2, EQV}}, TrueVal, FalseVal, Q, MaxRecurse))
+// return V;
+// if (Value *V = simplifySelectWithEquivalence({{V1, EQV}}, TrueVal, FalseVal, Q, MaxRecurse))
+// return V;
+// }
+
if (Value *V =
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
return V;
diff --git a/llvm/test/Transforms/InstSimplify/select-select.ll b/llvm/test/Transforms/InstSimplify/select-select.ll
index 45d2f05016b5a..ebc2f988e4bbc 100644
--- a/llvm/test/Transforms/InstSimplify/select-select.ll
+++ b/llvm/test/Transforms/InstSimplify/select-select.ll
@@ -1,8 +1,27 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
-define i32 @foo(i32 %6, i32 %44) {
-; CHECK-LABEL: @foo(
+; FAILS! Because of poison.
+define i32 @selectSelectAndICmpFirstSelectParam(i32 %6, i32 %44, i1 %cond) {
+; CHECK-LABEL: @selectSelectAndICmpFirstSelectParam(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[COND:%.*]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %spec.select.i = select i1 %cond, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+
+define i32 @selectSelectAndICmp(i32 %6, i32 %44) {
+; CHECK-LABEL: @selectSelectAndICmp(
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
@@ -20,9 +39,78 @@ define i32 @foo(i32 %6, i32 %44) {
ret i32 %.0.i8
}
+define i32 @selectSelectAndICmpRemovedNonConst(i32 %6, i32 %44, i32 %val) {
+; CHECK-LABEL: @selectSelectAndICmpRemovedNonConst(
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], [[VAL:%.*]]
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1:%.*]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %46 = icmp eq i32 %44, %val
+ %47 = icmp eq i32 %6, %val
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = xor i1 %47, true
+ %spec.select.i = select i1 %48, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 %val, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @selectSelectAndICmpRemoved(i32 %6, i32 %44) {
+; CHECK-LABEL: @selectSelectAndICmpRemoved(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP4]], i32 [[TMP0]], i32 [[TMP1:%.*]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = xor i1 %47, true
+ %spec.select.i = select i1 %48, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+define i32 @selectSelectAndICmpAnd(i32 %6, i32 %44) {
+; CHECK-LABEL: @selectSelectAndICmpAnd(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP5]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP6]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = xor i1 %47, true
+ %49 = and i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
+
+define i32 @selectSelectAndICmpAnd2(i32 %6, i32 %44) {
+; CHECK-LABEL: @selectSelectAndICmpAnd2(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: ret i32 [[SPEC_SELECT_I]]
+;
+ %46 = icmp eq i32 %44, 4
+ %47 = icmp eq i32 %6, 4
+ %or.cond.i = and i1 %47, %46 ; Check if both values are 4.
+ %48 = and i1 %47, true
+ %49 = or i1 %46, %48
+ %spec.select.i = select i1 %49, i32 %6, i32 %44
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
-define i32 @fooAndUsed(i32 %6, i32 %44) {
-; CHECK-LABEL: @fooAndUsed(
+define i32 @selectSelectAndICmpUsed(i32 %6, i32 %44) {
+; CHECK-LABEL: @selectSelectAndICmpUsed(
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
@@ -43,6 +131,26 @@ define i32 @fooAndUsed(i32 %6, i32 %44) {
ret i32 %.0.i8
}
+define i32 @selectSelectAndICmpDisjointOr(i32 %0, i32 %1) {
+; CHECK-LABEL: @selectSelectAndICmpDisjointOr(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
+; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0:%.*]], 4
+; CHECK-NEXT: [[OR_COND_I:%.*]] = and i1 [[TMP4]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = or disjoint i1 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[TMP5]], i32 [[TMP0]], i32 [[TMP1]]
+; CHECK-NEXT: [[DOT0_I8:%.*]] = select i1 [[OR_COND_I]], i32 4, i32 [[SPEC_SELECT_I]]
+; CHECK-NEXT: ret i32 [[DOT0_I8]]
+;
+ %3 = icmp eq i32 %1, 4
+ %4 = icmp eq i32 %0, 4
+ %or.cond.i = and i1 %4, %3
+ %5 = and i1 %4, true
+ %6 = or disjoint i1 %3, %5
+ %spec.select.i = select i1 %6, i32 %0, i32 %1
+ %.0.i8 = select i1 %or.cond.i, i32 4, i32 %spec.select.i
+ ret i32 %.0.i8
+}
+
define i32 @negSelectSelectICmpICmp(i32 %6, i32 %44) {
; CHECK-LABEL: @negSelectSelectICmpICmp(
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP1:%.*]], 4
More information about the llvm-commits
mailing list