Skip to content

Commit 2280f2f

Browse files
Fold A == MIN_INT ? B != MIN_INT : A < B to A < B
1 parent 41a032d commit 2280f2f

File tree

3 files changed

+59
-60
lines changed

3 files changed

+59
-60
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7141,7 +7141,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
71417141
NewOps[1], I->getFastMathFlags(), Q, MaxRecurse);
71427142
case Instruction::Select:
71437143
return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q, MaxRecurse);
7144-
break;
71457144
case Instruction::GetElementPtr: {
71467145
auto *GEPI = cast<GetElementPtrInst>(I);
71477146
return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0],

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,46 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
17811781
return nullptr;
17821782
}
17831783

1784+
/// `A == MIN_INT ? B != MIN_INT : A < B` --> `A < B`
1785+
/// `A == MAX_INT ? B != MAX_INT : A > B` --> `A > B`
1786+
static Instruction *foldSelectWithExtremeEqCond(Value *CmpLHS, Value *CmpRHS,
1787+
Value *TrueVal,
1788+
Value *FalseVal) {
1789+
Type *Ty = CmpLHS->getType();
1790+
1791+
if (Ty->isPtrOrPtrVectorTy())
1792+
return nullptr;
1793+
1794+
CmpPredicate Pred;
1795+
Value *B;
1796+
1797+
if (!match(FalseVal, m_c_ICmp(Pred, m_Specific(CmpLHS), m_Value(B))))
1798+
return nullptr;
1799+
1800+
Value *TValRHS;
1801+
if (!match(TrueVal, m_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(B),
1802+
m_Value(TValRHS))))
1803+
return nullptr;
1804+
1805+
APInt C;
1806+
unsigned BitWidth = Ty->getScalarSizeInBits();
1807+
1808+
if (ICmpInst::isLT(Pred)) {
1809+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMinValue(BitWidth)
1810+
: APInt::getMinValue(BitWidth);
1811+
} else if (ICmpInst::isGT(Pred)) {
1812+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMaxValue(BitWidth)
1813+
: APInt::getMaxValue(BitWidth);
1814+
} else {
1815+
return nullptr;
1816+
}
1817+
1818+
if (!match(CmpRHS, m_SpecificInt(C)) || !match(TValRHS, m_SpecificInt(C)))
1819+
return nullptr;
1820+
1821+
return new ICmpInst(Pred, CmpLHS, B);
1822+
}
1823+
17841824
static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
17851825
InstCombinerImpl &IC) {
17861826
ICmpInst::Predicate Pred = ICI->getPredicate();
@@ -1795,6 +1835,10 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
17951835
if (Pred == ICmpInst::ICMP_NE)
17961836
std::swap(TrueVal, FalseVal);
17971837

1838+
if (Instruction *Res =
1839+
foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
1840+
return Res;
1841+
17981842
// Transform (X == C) ? X : Y -> (X == C) ? C : Y
17991843
// specific handling for Bitwise operation.
18001844
// x&y -> (x|y) ^ (x^y) or (x|y) & ~(x^y)

llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ define i1 @compare_unsigned_min(i8 %x, i8 %y) {
55
; CHECK-LABEL: define i1 @compare_unsigned_min(
66
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
77
; CHECK-NEXT: [[START:.*:]]
8-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
9-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
108
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[X]], [[Y]]
11-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP2]]
12-
; CHECK-NEXT: ret i1 [[RESULT]]
9+
; CHECK-NEXT: ret i1 [[TMP2]]
1310
;
1411
start:
1512
%cmp1 = icmp eq i8 %x, 0
@@ -23,11 +20,8 @@ define i1 @compare_signed_min(i8 %x, i8 %y) {
2320
; CHECK-LABEL: define i1 @compare_signed_min(
2421
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
2522
; CHECK-NEXT: [[START:.*:]]
26-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], -128
27-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -128
2823
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[X]], [[Y]]
29-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
30-
; CHECK-NEXT: ret i1 [[RESULT]]
24+
; CHECK-NEXT: ret i1 [[TMP4]]
3125
;
3226
start:
3327
%cmp1 = icmp eq i8 %x, -128
@@ -41,11 +35,8 @@ define i1 @compare_unsigned_max(i8 %x, i8 %y) {
4135
; CHECK-LABEL: define i1 @compare_unsigned_max(
4236
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
4337
; CHECK-NEXT: [[START:.*:]]
44-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], -1
45-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -1
4638
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], [[Y]]
47-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
48-
; CHECK-NEXT: ret i1 [[RESULT]]
39+
; CHECK-NEXT: ret i1 [[TMP4]]
4940
;
5041
start:
5142
%cmp1 = icmp eq i8 %x, 255
@@ -59,11 +50,8 @@ define i1 @compare_signed_max(i8 %x, i8 %y) {
5950
; CHECK-LABEL: define i1 @compare_signed_max(
6051
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
6152
; CHECK-NEXT: [[START:.*:]]
62-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 127
63-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 127
6453
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
65-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
66-
; CHECK-NEXT: ret i1 [[RESULT]]
54+
; CHECK-NEXT: ret i1 [[TMP4]]
6755
;
6856
start:
6957
%cmp1 = icmp eq i8 %x, 127
@@ -77,11 +65,8 @@ define i1 @relational_cmp_unsigned_min(i8 %x, i8 %y) {
7765
; CHECK-LABEL: define i1 @relational_cmp_unsigned_min(
7866
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
7967
; CHECK-NEXT: [[START:.*:]]
80-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
81-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
8268
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i8 [[X]], [[Y]]
83-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
84-
; CHECK-NEXT: ret i1 [[RESULT]]
69+
; CHECK-NEXT: ret i1 [[TMP4]]
8570
;
8671
start:
8772
%cmp1 = icmp ule i8 %x, 0
@@ -95,11 +80,8 @@ define i1 @relational_cmp_signed_min(i8 %x, i8 %y) {
9580
; CHECK-LABEL: define i1 @relational_cmp_signed_min(
9681
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
9782
; CHECK-NEXT: [[START:.*:]]
98-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], -128
99-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -128
10083
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[X]], [[Y]]
101-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
102-
; CHECK-NEXT: ret i1 [[RESULT]]
84+
; CHECK-NEXT: ret i1 [[TMP4]]
10385
;
10486
start:
10587
%cmp1 = icmp sle i8 %x, -128
@@ -113,11 +95,8 @@ define i1 @relational_cmp_unsigned_max(i8 %x, i8 %y) {
11395
; CHECK-LABEL: define i1 @relational_cmp_unsigned_max(
11496
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
11597
; CHECK-NEXT: [[START:.*:]]
116-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], -1
117-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -1
11898
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], [[Y]]
119-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
120-
; CHECK-NEXT: ret i1 [[RESULT]]
99+
; CHECK-NEXT: ret i1 [[TMP4]]
121100
;
122101
start:
123102
%cmp1 = icmp uge i8 %x, 255
@@ -131,11 +110,8 @@ define i1 @relational_cmp_signed_max(i8 %x, i8 %y) {
131110
; CHECK-LABEL: define i1 @relational_cmp_signed_max(
132111
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
133112
; CHECK-NEXT: [[START:.*:]]
134-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 127
135-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 127
136113
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
137-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
138-
; CHECK-NEXT: ret i1 [[RESULT]]
114+
; CHECK-NEXT: ret i1 [[TMP4]]
139115
;
140116
start:
141117
%cmp1 = icmp sge i8 %x, 127
@@ -151,11 +127,9 @@ define i1 @compare_signed_max_multiuse(i8 %x, i8 %y) {
151127
; CHECK-LABEL: define i1 @compare_signed_max_multiuse(
152128
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
153129
; CHECK-NEXT: [[START:.*:]]
154-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 127
155-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 127
156130
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[X]], [[Y]]
157131
; CHECK-NEXT: call void @use(i1 [[TMP4]])
158-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP4]]
132+
; CHECK-NEXT: [[RESULT:%.*]] = icmp sgt i8 [[X]], [[Y]]
159133
; CHECK-NEXT: ret i1 [[RESULT]]
160134
;
161135
start:
@@ -171,10 +145,7 @@ define i1 @compare_signed_min_samesign(i8 %x, i8 %y) {
171145
; CHECK-LABEL: define i1 @compare_signed_min_samesign(
172146
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
173147
; CHECK-NEXT: [[START:.*:]]
174-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], -128
175-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -128
176-
; CHECK-NEXT: [[CMP3:%.*]] = icmp samesign slt i8 [[X]], [[Y]]
177-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
148+
; CHECK-NEXT: [[RESULT:%.*]] = icmp slt i8 [[X]], [[Y]]
178149
; CHECK-NEXT: ret i1 [[RESULT]]
179150
;
180151
start:
@@ -189,10 +160,7 @@ define i1 @compare_flipped(i8 %x, i8 %y) {
189160
; CHECK-LABEL: define i1 @compare_flipped(
190161
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
191162
; CHECK-NEXT: [[START:.*:]]
192-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
193-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
194-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ugt i8 [[Y]], [[X]]
195-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
163+
; CHECK-NEXT: [[RESULT:%.*]] = icmp ult i8 [[X]], [[Y]]
196164
; CHECK-NEXT: ret i1 [[RESULT]]
197165
;
198166
start:
@@ -207,11 +175,8 @@ define i1 @compare_swapped(i8 %x, i8 %y) {
207175
; CHECK-LABEL: define i1 @compare_swapped(
208176
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
209177
; CHECK-NEXT: [[START:.*:]]
210-
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i8 [[X]], 0
211-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], 0
212178
; CHECK-NEXT: [[RESULT:%.*]] = icmp ult i8 [[X]], [[Y]]
213-
; CHECK-NEXT: [[RESULT1:%.*]] = select i1 [[CMP1_NOT]], i1 [[CMP2]], i1 [[RESULT]]
214-
; CHECK-NEXT: ret i1 [[RESULT1]]
179+
; CHECK-NEXT: ret i1 [[RESULT]]
215180
;
216181
start:
217182
%cmp1 = icmp ne i8 %x, 0
@@ -225,10 +190,7 @@ define i1 @compare_swapped_flipped_unsigned_max(i8 %x, i8 %y) {
225190
; CHECK-LABEL: define i1 @compare_swapped_flipped_unsigned_max(
226191
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
227192
; CHECK-NEXT: [[START:.*:]]
228-
; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i8 [[X]], -1
229-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[Y]], -1
230-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[Y]], [[X]]
231-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1_NOT]], i1 [[CMP2]], i1 [[CMP3]]
193+
; CHECK-NEXT: [[RESULT:%.*]] = icmp ugt i8 [[X]], [[Y]]
232194
; CHECK-NEXT: ret i1 [[RESULT]]
233195
;
234196
start:
@@ -243,11 +205,8 @@ define i1 @compare_unsigned_min_illegal_type(i9 %x, i9 %y) {
243205
; CHECK-LABEL: define i1 @compare_unsigned_min_illegal_type(
244206
; CHECK-SAME: i9 [[X:%.*]], i9 [[Y:%.*]]) {
245207
; CHECK-NEXT: [[START:.*:]]
246-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i9 [[X]], 0
247-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i9 [[Y]], 0
248208
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i9 [[X]], [[Y]]
249-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[TMP2]]
250-
; CHECK-NEXT: ret i1 [[RESULT]]
209+
; CHECK-NEXT: ret i1 [[TMP2]]
251210
;
252211
start:
253212
%cmp1 = icmp eq i9 %x, 0
@@ -275,11 +234,8 @@ start:
275234
define <2 x i1> @compare_vector(<2 x i8> %x, <2 x i8> %y) {
276235
; CHECK-LABEL: define <2 x i1> @compare_vector(
277236
; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
278-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
279-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne <2 x i8> [[Y]], zeroinitializer
280237
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]]
281-
; CHECK-NEXT: [[RESULT:%.*]] = select <2 x i1> [[CMP1]], <2 x i1> [[CMP2]], <2 x i1> [[TMP1]]
282-
; CHECK-NEXT: ret <2 x i1> [[RESULT]]
238+
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
283239
;
284240
%cmp1 = icmp eq <2 x i8> %x, zeroinitializer
285241
%cmp2 = icmp ne <2 x i8> %y, zeroinitializer

0 commit comments

Comments
 (0)