Skip to content

Commit 92fb27e

Browse files
Fold A == MIN_INT ? B != MIN_INT : A < B to A < B
1 parent e306711 commit 92fb27e

File tree

2 files changed

+58
-61
lines changed

2 files changed

+58
-61
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4608,6 +4608,45 @@ static Value *simplifySelectWithEquivalence(Value *CmpLHS, Value *CmpRHS,
46084608
return nullptr;
46094609
}
46104610

4611+
/// `A == MIN_INT ? B != MIN_INT : A < B` --> `A < B`
4612+
/// `A == MAX_INT ? B != MAX_INT : A > B` --> `A > B`
4613+
static Value *foldSelectWithExtremeEqCond(Value *CmpLHS, Value *CmpRHS,
4614+
Value *TrueVal, Value *FalseVal) {
4615+
CmpPredicate Pred;
4616+
Value *A, *B;
4617+
4618+
if (!match(FalseVal, m_ICmp(Pred, m_Value(A), m_Value(B))))
4619+
return nullptr;
4620+
4621+
// make sure `CmpLHS` is on the LHS of `FalseVal`.
4622+
if (match(CmpLHS, m_Specific(B))) {
4623+
std::swap(A, B);
4624+
Pred = CmpInst::getSwappedPredicate(Pred);
4625+
}
4626+
4627+
APInt C;
4628+
unsigned NumBits = A->getType()->getScalarSizeInBits();
4629+
4630+
if (ICmpInst::isLT(Pred)) {
4631+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMinValue(NumBits)
4632+
: APInt::getMinValue(NumBits);
4633+
} else if (ICmpInst::isGT(Pred)) {
4634+
C = CmpInst::isSigned(Pred) ? APInt::getSignedMaxValue(NumBits)
4635+
: APInt::getMaxValue(NumBits);
4636+
} else {
4637+
return nullptr;
4638+
}
4639+
4640+
if (!match(CmpLHS, m_Specific(A)) || !match(CmpRHS, m_SpecificInt(C)))
4641+
return nullptr;
4642+
4643+
if (!match(TrueVal, m_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(B),
4644+
m_SpecificInt(C))))
4645+
return nullptr;
4646+
4647+
return FalseVal;
4648+
}
4649+
46114650
/// Try to simplify a select instruction when its condition operand is an
46124651
/// integer comparison.
46134652
static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
@@ -4728,6 +4767,10 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47284767
Q, MaxRecurse))
47294768
return V;
47304769
}
4770+
4771+
if (Value *V =
4772+
foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
4773+
return V;
47314774
}
47324775

47334776
return nullptr;
@@ -7141,7 +7184,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
71417184
NewOps[1], I->getFastMathFlags(), Q, MaxRecurse);
71427185
case Instruction::Select:
71437186
return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q, MaxRecurse);
7144-
break;
71457187
case Instruction::GetElementPtr: {
71467188
auto *GEPI = cast<GetElementPtrInst>(I);
71477189
return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0],

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

Lines changed: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ define i1 @compare_unsigned_min(i8 %0, i8 %1) {
55
; CHECK-LABEL: define i1 @compare_unsigned_min(
66
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
77
; CHECK-NEXT: [[START:.*:]]
8-
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i8 [[TMP0]], 0
9-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
108
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
11-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
12-
; CHECK-NEXT: ret i1 [[RESULT]]
9+
; CHECK-NEXT: ret i1 [[TMP2]]
1310
;
1411
start:
1512
%2 = icmp eq i8 %0, 0
@@ -23,11 +20,8 @@ define i1 @compare_signed_min(i8 %0, i8 %1) {
2320
; CHECK-LABEL: define i1 @compare_signed_min(
2421
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
2522
; CHECK-NEXT: [[START:.*:]]
26-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
27-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
2823
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
29-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
30-
; CHECK-NEXT: ret i1 [[RESULT]]
24+
; CHECK-NEXT: ret i1 [[TMP4]]
3125
;
3226
start:
3327
%2 = icmp eq i8 %0, -128
@@ -41,11 +35,8 @@ define i1 @compare_unsigned_max(i8 %0, i8 %1) {
4135
; CHECK-LABEL: define i1 @compare_unsigned_max(
4236
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
4337
; CHECK-NEXT: [[START:.*:]]
44-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
45-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
4638
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
47-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
48-
; CHECK-NEXT: ret i1 [[RESULT]]
39+
; CHECK-NEXT: ret i1 [[TMP4]]
4940
;
5041
start:
5142
%2 = icmp eq i8 %0, 255
@@ -59,11 +50,8 @@ define i1 @compare_signed_max(i8 %0, i8 %1) {
5950
; CHECK-LABEL: define i1 @compare_signed_max(
6051
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
6152
; CHECK-NEXT: [[START:.*:]]
62-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
63-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
6453
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
65-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
66-
; CHECK-NEXT: ret i1 [[RESULT]]
54+
; CHECK-NEXT: ret i1 [[TMP4]]
6755
;
6856
start:
6957
%2 = icmp eq i8 %0, 127
@@ -77,11 +65,8 @@ define i1 @relational_cmp_unsigned_min(i8 %0, i8 %1) {
7765
; CHECK-LABEL: define i1 @relational_cmp_unsigned_min(
7866
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
7967
; CHECK-NEXT: [[START:.*:]]
80-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
81-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
8268
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
83-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
84-
; CHECK-NEXT: ret i1 [[RESULT]]
69+
; CHECK-NEXT: ret i1 [[TMP4]]
8570
;
8671
start:
8772
%2 = icmp ule i8 %0, 0
@@ -95,11 +80,8 @@ define i1 @relational_cmp_signed_min(i8 %0, i8 %1) {
9580
; CHECK-LABEL: define i1 @relational_cmp_signed_min(
9681
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
9782
; CHECK-NEXT: [[START:.*:]]
98-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
99-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
10083
; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
101-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
102-
; CHECK-NEXT: ret i1 [[RESULT]]
84+
; CHECK-NEXT: ret i1 [[TMP4]]
10385
;
10486
start:
10587
%2 = icmp sle i8 %0, -128
@@ -113,11 +95,8 @@ define i1 @relational_cmp_unsigned_max(i8 %0, i8 %1) {
11395
; CHECK-LABEL: define i1 @relational_cmp_unsigned_max(
11496
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
11597
; CHECK-NEXT: [[START:.*:]]
116-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
117-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
11898
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
119-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
120-
; CHECK-NEXT: ret i1 [[RESULT]]
99+
; CHECK-NEXT: ret i1 [[TMP4]]
121100
;
122101
start:
123102
%2 = icmp uge i8 %0, 255
@@ -131,11 +110,8 @@ define i1 @relational_cmp_signed_max(i8 %0, i8 %1) {
131110
; CHECK-LABEL: define i1 @relational_cmp_signed_max(
132111
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
133112
; CHECK-NEXT: [[START:.*:]]
134-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
135-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
136113
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
137-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
138-
; CHECK-NEXT: ret i1 [[RESULT]]
114+
; CHECK-NEXT: ret i1 [[TMP4]]
139115
;
140116
start:
141117
%2 = icmp sge i8 %0, 127
@@ -151,12 +127,9 @@ define i1 @compare_signed_max_multiuse(i8 %0, i8 %1) {
151127
; CHECK-LABEL: define i1 @compare_signed_max_multiuse(
152128
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
153129
; CHECK-NEXT: [[START:.*:]]
154-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
155-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
156130
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
157131
; CHECK-NEXT: call void @use(i1 [[TMP4]])
158-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
159-
; CHECK-NEXT: ret i1 [[RESULT]]
132+
; CHECK-NEXT: ret i1 [[TMP4]]
160133
;
161134
start:
162135
%2 = icmp eq i8 %0, 127
@@ -171,11 +144,8 @@ define i1 @compare_signed_min_samesign(i8 %0, i8 %1) {
171144
; CHECK-LABEL: define i1 @compare_signed_min_samesign(
172145
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
173146
; CHECK-NEXT: [[START:.*:]]
174-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
175-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
176147
; CHECK-NEXT: [[TMP4:%.*]] = icmp samesign slt i8 [[TMP0]], [[TMP1]]
177-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
178-
; CHECK-NEXT: ret i1 [[RESULT]]
148+
; CHECK-NEXT: ret i1 [[TMP4]]
179149
;
180150
start:
181151
%2 = icmp eq i8 %0, -128
@@ -189,11 +159,8 @@ define i1 @compare_flipped(i8 %0, i8 %1) {
189159
; CHECK-LABEL: define i1 @compare_flipped(
190160
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
191161
; CHECK-NEXT: [[START:.*:]]
192-
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
193-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
194162
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[TMP1]], [[TMP0]]
195-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
196-
; CHECK-NEXT: ret i1 [[RESULT]]
163+
; CHECK-NEXT: ret i1 [[TMP4]]
197164
;
198165
start:
199166
%2 = icmp eq i8 %0, 0
@@ -207,11 +174,8 @@ define i1 @compare_swapped(i8 %0, i8 %1) {
207174
; CHECK-LABEL: define i1 @compare_swapped(
208175
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
209176
; CHECK-NEXT: [[START:.*:]]
210-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], 0
211-
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
212177
; CHECK-NEXT: [[RESULT:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
213-
; CHECK-NEXT: [[RESULT1:%.*]] = select i1 [[DOTNOT]], i1 [[TMP2]], i1 [[RESULT]]
214-
; CHECK-NEXT: ret i1 [[RESULT1]]
178+
; CHECK-NEXT: ret i1 [[RESULT]]
215179
;
216180
start:
217181
%2 = icmp ne i8 %0, 0
@@ -225,11 +189,8 @@ define i1 @compare_swapped_flipped_unsigned_max(i8 %0, i8 %1) {
225189
; CHECK-LABEL: define i1 @compare_swapped_flipped_unsigned_max(
226190
; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
227191
; CHECK-NEXT: [[START:.*:]]
228-
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], -1
229-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
230192
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[TMP0]]
231-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[DOTNOT]], i1 [[TMP3]], i1 [[TMP2]]
232-
; CHECK-NEXT: ret i1 [[RESULT]]
193+
; CHECK-NEXT: ret i1 [[TMP2]]
233194
;
234195
start:
235196
%2 = icmp ne i8 %0, 255
@@ -243,11 +204,8 @@ define i1 @compare_unsigned_min_illegal_type(i9 %0, i9 %1) {
243204
; CHECK-LABEL: define i1 @compare_unsigned_min_illegal_type(
244205
; CHECK-SAME: i9 [[TMP0:%.*]], i9 [[TMP1:%.*]]) {
245206
; CHECK-NEXT: [[START:.*:]]
246-
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i9 [[TMP0]], 0
247-
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i9 [[TMP1]], 0
248207
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i9 [[TMP0]], [[TMP1]]
249-
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
250-
; CHECK-NEXT: ret i1 [[RESULT]]
208+
; CHECK-NEXT: ret i1 [[TMP2]]
251209
;
252210
start:
253211
%2 = icmp eq i9 %0, 0
@@ -260,11 +218,8 @@ start:
260218
define <2 x i1> @compare_vector(<2 x i8> %x, <2 x i8> %y) {
261219
; CHECK-LABEL: define <2 x i1> @compare_vector(
262220
; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
263-
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
264-
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i8> [[Y]], zeroinitializer
265221
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]]
266-
; CHECK-NEXT: [[RESULT:%.*]] = select <2 x i1> [[TMP3]], <2 x i1> [[TMP2]], <2 x i1> [[TMP1]]
267-
; CHECK-NEXT: ret <2 x i1> [[RESULT]]
222+
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
268223
;
269224
%2 = icmp eq <2 x i8> %x, <i8 0, i8 0>
270225
%3 = icmp ne <2 x i8> %y, <i8 0, i8 0>

0 commit comments

Comments
 (0)