Skip to content

Commit 20ae2d2

Browse files
committed
[InstCombine] Generalize foldAndOrOfICmpEqZeroAndICmp
This patch generalizes the fold implemented by foldAndOrOfICmpEqZeroAndICmp, which are: (icmp eq X, 0) | (icmp ult Other, X) -> (icmp ule Other, X-1) (icmp ne X, 0) & (icmp uge Other, X) -> (icmp ugt Other, X-1) to the following: (icmp eq X, C) | (icmp ult Other, (X - C)) -> (icmp ule Other, (X - (C + 1))) (icmp ne X, C) & (icmp uge Other, (X - C)) -> (icmp ugt Other, (X - (C + 1))) The function foldAndOrOfICmpEqZeroAndICmp is also renamed to foldAndOrOfICmpEqConstantAndICmp to reflect the changes. Proofs: https://alive2.llvm.org/ce/z/yXGv6q Fixes llvm#63749. Differential Revision: https://reviews.llvm.org/D154937
1 parent b336f9d commit 20ae2d2

File tree

2 files changed

+57
-49
lines changed

2 files changed

+57
-49
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,34 +2978,47 @@ Value *InstCombinerImpl::matchSelectFromAndOr(Value *A, Value *C, Value *B,
29782978
return nullptr;
29792979
}
29802980

2981-
// (icmp eq X, 0) | (icmp ult Other, X) -> (icmp ule Other, X-1)
2982-
// (icmp ne X, 0) & (icmp uge Other, X) -> (icmp ugt Other, X-1)
2983-
static Value *foldAndOrOfICmpEqZeroAndICmp(ICmpInst *LHS, ICmpInst *RHS,
2984-
bool IsAnd, bool IsLogical,
2985-
IRBuilderBase &Builder) {
2981+
// (icmp eq X, C) | (icmp ult Other, (X - C)) -> (icmp ule Other, (X - (C + 1)))
2982+
// (icmp ne X, C) & (icmp uge Other, (X - C)) -> (icmp ugt Other, (X - (C + 1)))
2983+
static Value *foldAndOrOfICmpEqConstantAndICmp(ICmpInst *LHS, ICmpInst *RHS,
2984+
bool IsAnd, bool IsLogical,
2985+
IRBuilderBase &Builder) {
2986+
Value *LHS0 = LHS->getOperand(0);
2987+
Value *RHS0 = RHS->getOperand(0);
2988+
Value *RHS1 = RHS->getOperand(1);
2989+
29862990
ICmpInst::Predicate LPred =
29872991
IsAnd ? LHS->getInversePredicate() : LHS->getPredicate();
29882992
ICmpInst::Predicate RPred =
29892993
IsAnd ? RHS->getInversePredicate() : RHS->getPredicate();
2990-
Value *LHS0 = LHS->getOperand(0);
2991-
if (LPred != ICmpInst::ICMP_EQ || !match(LHS->getOperand(1), m_Zero()) ||
2994+
2995+
const APInt *CInt;
2996+
if (LPred != ICmpInst::ICMP_EQ ||
2997+
!match(LHS->getOperand(1), m_APIntAllowUndef(CInt)) ||
29922998
!LHS0->getType()->isIntOrIntVectorTy() ||
29932999
!(LHS->hasOneUse() || RHS->hasOneUse()))
29943000
return nullptr;
29953001

3002+
auto MatchRHSOp = [LHS0, CInt](const Value *RHSOp) {
3003+
return match(RHSOp,
3004+
m_Add(m_Specific(LHS0), m_SpecificIntAllowUndef(-*CInt))) ||
3005+
(CInt->isZero() && RHSOp == LHS0);
3006+
};
3007+
29963008
Value *Other;
2997-
if (RPred == ICmpInst::ICMP_ULT && RHS->getOperand(1) == LHS0)
2998-
Other = RHS->getOperand(0);
2999-
else if (RPred == ICmpInst::ICMP_UGT && RHS->getOperand(0) == LHS0)
3000-
Other = RHS->getOperand(1);
3009+
if (RPred == ICmpInst::ICMP_ULT && MatchRHSOp(RHS1))
3010+
Other = RHS0;
3011+
else if (RPred == ICmpInst::ICMP_UGT && MatchRHSOp(RHS0))
3012+
Other = RHS1;
30013013
else
30023014
return nullptr;
30033015

30043016
if (IsLogical)
30053017
Other = Builder.CreateFreeze(Other);
3018+
30063019
return Builder.CreateICmp(
30073020
IsAnd ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_UGE,
3008-
Builder.CreateAdd(LHS0, Constant::getAllOnesValue(LHS0->getType())),
3021+
Builder.CreateSub(LHS0, ConstantInt::get(LHS0->getType(), *CInt + 1)),
30093022
Other);
30103023
}
30113024

@@ -3052,12 +3065,12 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
30523065
return V;
30533066

30543067
if (Value *V =
3055-
foldAndOrOfICmpEqZeroAndICmp(LHS, RHS, IsAnd, IsLogical, Builder))
3068+
foldAndOrOfICmpEqConstantAndICmp(LHS, RHS, IsAnd, IsLogical, Builder))
30563069
return V;
30573070
// We can treat logical like bitwise here, because both operands are used on
30583071
// the LHS, and as such poison from both will propagate.
3059-
if (Value *V = foldAndOrOfICmpEqZeroAndICmp(RHS, LHS, IsAnd,
3060-
/*IsLogical*/ false, Builder))
3072+
if (Value *V = foldAndOrOfICmpEqConstantAndICmp(RHS, LHS, IsAnd,
3073+
/*IsLogical*/ false, Builder))
30613074
return V;
30623075

30633076
if (Value *V =

llvm/test/Transforms/InstCombine/and-or-icmp-const-icmp.ll

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@ define i1 @eq_basic(i8 %x, i8 %y) {
2828
define i1 @ne_basic_equal_5(i8 %x, i8 %y) {
2929
; CHECK-LABEL: define i1 @ne_basic_equal_5
3030
; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
31-
; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X]], -5
32-
; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X]], 5
33-
; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[SUB]], [[Y]]
34-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C1]], [[C2]]
31+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], -6
32+
; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[TMP1]], [[Y]]
3533
; CHECK-NEXT: ret i1 [[AND]]
3634
;
3735
%sub = add i8 %x, -5
@@ -44,10 +42,7 @@ define i1 @ne_basic_equal_5(i8 %x, i8 %y) {
4442
define i1 @eq_basic_equal_minus_1(i8 %x, i8 %y) {
4543
; CHECK-LABEL: define i1 @eq_basic_equal_minus_1
4644
; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
47-
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 1
48-
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], -1
49-
; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[ADD]], [[Y]]
50-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C1]], [[C2]]
45+
; CHECK-NEXT: [[OR:%.*]] = icmp uge i8 [[X]], [[Y]]
5146
; CHECK-NEXT: ret i1 [[OR]]
5247
;
5348
%add = add i8 %x, 1
@@ -60,10 +55,8 @@ define i1 @eq_basic_equal_minus_1(i8 %x, i8 %y) {
6055
define i1 @ne_basic_equal_minus_7(i8 %x, i8 %y) {
6156
; CHECK-LABEL: define i1 @ne_basic_equal_minus_7
6257
; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
63-
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 7
64-
; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X]], -7
65-
; CHECK-NEXT: [[C2:%.*]] = icmp ule i8 [[ADD]], [[Y]]
66-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C1]], [[C2]]
58+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], 6
59+
; CHECK-NEXT: [[AND:%.*]] = icmp ult i8 [[TMP1]], [[Y]]
6760
; CHECK-NEXT: ret i1 [[AND]]
6861
;
6962
%add = add i8 %x, 7
@@ -159,10 +152,8 @@ define <2 x i1> @eq_vector(<2 x i8> %x, <2 x i8> %y) {
159152
define <2 x i1> @ne_vector_equal_5(<2 x i8> %x, <2 x i8> %y) {
160153
; CHECK-LABEL: define <2 x i1> @ne_vector_equal_5
161154
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
162-
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i8> [[X]], <i8 -5, i8 -5>
163-
; CHECK-NEXT: [[C1:%.*]] = icmp ne <2 x i8> [[X]], <i8 5, i8 5>
164-
; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[SUB]], [[Y]]
165-
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[C1]], [[C2]]
155+
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], <i8 -6, i8 -6>
156+
; CHECK-NEXT: [[AND:%.*]] = icmp ult <2 x i8> [[TMP1]], [[Y]]
166157
; CHECK-NEXT: ret <2 x i1> [[AND]]
167158
;
168159
%sub = add <2 x i8> %x, <i8 -5, i8 -5>
@@ -175,10 +166,7 @@ define <2 x i1> @ne_vector_equal_5(<2 x i8> %x, <2 x i8> %y) {
175166
define <2 x i1> @eq_vector_equal_minus_1(<2 x i8> %x, <2 x i8> %y) {
176167
; CHECK-LABEL: define <2 x i1> @eq_vector_equal_minus_1
177168
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
178-
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], <i8 1, i8 1>
179-
; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i8> [[X]], <i8 -1, i8 -1>
180-
; CHECK-NEXT: [[C2:%.*]] = icmp ugt <2 x i8> [[ADD]], [[Y]]
181-
; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[C1]], [[C2]]
169+
; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[X]], [[Y]]
182170
; CHECK-NEXT: ret <2 x i1> [[OR]]
183171
;
184172
%add = add <2 x i8> %x, <i8 1, i8 1>
@@ -191,10 +179,8 @@ define <2 x i1> @eq_vector_equal_minus_1(<2 x i8> %x, <2 x i8> %y) {
191179
define <2 x i1> @ne_vector_equal_minus_7(<2 x i8> %x, <2 x i8> %y) {
192180
; CHECK-LABEL: define <2 x i1> @ne_vector_equal_minus_7
193181
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
194-
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], <i8 7, i8 7>
195-
; CHECK-NEXT: [[C1:%.*]] = icmp ne <2 x i8> [[X]], <i8 -7, i8 -7>
196-
; CHECK-NEXT: [[C2:%.*]] = icmp ule <2 x i8> [[ADD]], [[Y]]
197-
; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[C1]], [[C2]]
182+
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], <i8 6, i8 6>
183+
; CHECK-NEXT: [[AND:%.*]] = icmp ult <2 x i8> [[TMP1]], [[Y]]
198184
; CHECK-NEXT: ret <2 x i1> [[AND]]
199185
;
200186
%add = add <2 x i8> %x, <i8 7, i8 7>
@@ -239,13 +225,11 @@ define <2 x i1> @ne_vector_unequal2(<2 x i8> %x, <2 x i8> %y) {
239225
; ==============================================================================
240226
; Tests with undef
241227
; ==============================================================================
242-
define <2 x i1> @eq_vector_undef(<2 x i8> %x, <2 x i8> %y) {
243-
; CHECK-LABEL: define <2 x i1> @eq_vector_undef
228+
define <2 x i1> @eq_vector_undef_icmp(<2 x i8> %x, <2 x i8> %y) {
229+
; CHECK-LABEL: define <2 x i1> @eq_vector_undef_icmp
244230
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
245-
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i8> [[X]], <i8 -5, i8 -5>
246-
; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i8> [[X]], <i8 5, i8 undef>
247-
; CHECK-NEXT: [[C2:%.*]] = icmp ugt <2 x i8> [[SUB]], [[Y]]
248-
; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[C1]], [[C2]]
231+
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], <i8 -6, i8 -6>
232+
; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[TMP1]], [[Y]]
249233
; CHECK-NEXT: ret <2 x i1> [[OR]]
250234
;
251235
%sub = add <2 x i8> %x, <i8 -5, i8 -5>
@@ -255,6 +239,20 @@ define <2 x i1> @eq_vector_undef(<2 x i8> %x, <2 x i8> %y) {
255239
ret <2 x i1> %or
256240
}
257241

242+
define <2 x i1> @eq_vector_undef_add(<2 x i8> %x, <2 x i8> %y) {
243+
; CHECK-LABEL: define <2 x i1> @eq_vector_undef_add
244+
; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
245+
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X]], <i8 -6, i8 -6>
246+
; CHECK-NEXT: [[OR:%.*]] = icmp uge <2 x i8> [[TMP1]], [[Y]]
247+
; CHECK-NEXT: ret <2 x i1> [[OR]]
248+
;
249+
%sub = add <2 x i8> %x, <i8 -5, i8 undef>
250+
%c1 = icmp eq <2 x i8> %x, <i8 5, i8 5>
251+
%c2 = icmp ugt <2 x i8> %sub, %y
252+
%or = or <2 x i1> %c1, %c2
253+
ret <2 x i1> %or
254+
}
255+
258256
; ==============================================================================
259257
; Tests with values commuted
260258
; ==============================================================================
@@ -277,10 +275,7 @@ define i1 @ne_commuted_equal_minus_1(i8 %x, i8 %py) {
277275
; CHECK-LABEL: define i1 @ne_commuted_equal_minus_1
278276
; CHECK-SAME: (i8 [[X:%.*]], i8 [[PY:%.*]]) {
279277
; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[PY]]
280-
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], 1
281-
; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X]], -1
282-
; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[Y]], [[ADD]]
283-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[C1]], [[C2]]
278+
; CHECK-NEXT: [[AND:%.*]] = icmp ugt i8 [[Y]], [[X]]
284279
; CHECK-NEXT: ret i1 [[AND]]
285280
;
286281
%y = sdiv i8 42, %py ; thwart complexity-based canonicalization

0 commit comments

Comments
 (0)