Skip to content

Commit c63dbd2

Browse files
committed
[InstCombine] Make the (icmp eq/ne (and X, Y), X) canonicalization work for non-const operands
We currently do: `(icmp eq/ne (and X, Y), Y)` -> `(icmp eq/ne (and ~X, Y), 0)` if `X` is constant. We can make this more general and do it if `X` is freely invertable (i.e say `X = ~Z`). As well, we can also do: `(icmp eq/ne (and X, Y), Y)` -> `(icmp eq/ne (or X, ~Y), -1)` If `Y` is freely invertible. Proofs: https://alive2.llvm.org/ce/z/yeWH3E Differential Revision: https://reviews.llvm.org/D159059
1 parent 1cba910 commit c63dbd2

7 files changed

+79
-80
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4709,6 +4709,21 @@ static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q,
47094709
if (Pred == ICmpInst::ICMP_UGE)
47104710
return new ICmpInst(ICmpInst::ICMP_EQ, Op0, Op1);
47114711

4712+
if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) {
4713+
// icmp (X & Y) eq/ne Y --> (X | ~Y) eq/ne -1 if Y is freely invertible and
4714+
// Y is non-constant. If Y is constant the `X & C == C` form is preferable
4715+
// so don't do this fold.
4716+
if (!match(Op1, m_ImmConstant()))
4717+
if (auto *NotOp1 =
4718+
IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder))
4719+
return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1),
4720+
Constant::getAllOnesValue(Op1->getType()));
4721+
// icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible.
4722+
if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder))
4723+
return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA),
4724+
Constant::getNullValue(Op1->getType()));
4725+
}
4726+
47124727
return nullptr;
47134728
}
47144729

@@ -5485,21 +5500,6 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
54855500
}
54865501
}
54875502

5488-
// canoncalize:
5489-
// (icmp eq/ne (and X, C), X)
5490-
// -> (icmp eq/ne (and X, ~C), 0)
5491-
{
5492-
Constant *CMask;
5493-
A = nullptr;
5494-
if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_ImmConstant(CMask)))))
5495-
A = Op1;
5496-
else if (match(Op1, m_OneUse(m_And(m_Specific(Op0), m_ImmConstant(CMask)))))
5497-
A = Op0;
5498-
if (A)
5499-
return new ICmpInst(Pred, Builder.CreateAnd(A, Builder.CreateNot(CMask)),
5500-
Constant::getNullValue(A->getType()));
5501-
}
5502-
55035503
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) {
55045504
// A == (A^B) -> B == 0
55055505
Value *OtherVal = A == Op0 ? B : A;

llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
144144
; CHECK-LABEL: @oneuse0(
145145
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
146146
; CHECK-NEXT: call void @use8(i8 [[T0]])
147-
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
147+
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
148148
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
149149
; CHECK-NEXT: ret i1 [[RET]]
150150
;
@@ -161,7 +161,8 @@ define i1 @oneuse1(i8 %x, i8 %y) {
161161
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
162162
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
163163
; CHECK-NEXT: call void @use8(i8 [[T1]])
164-
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
164+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
165+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
165166
; CHECK-NEXT: ret i1 [[RET]]
166167
;
167168
%t0 = shl i8 -1, %y
@@ -195,7 +196,8 @@ define i1 @oneuse3(i8 %x, i8 %y) {
195196
; CHECK-NEXT: call void @use8(i8 [[T0]])
196197
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
197198
; CHECK-NEXT: call void @use8(i8 [[T1]])
198-
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
199+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
200+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
199201
; CHECK-NEXT: ret i1 [[RET]]
200202
;
201203
%t0 = shl i8 -1, %y
@@ -269,9 +271,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
269271
define i1 @n1(i8 %x, i8 %y) {
270272
; CHECK-LABEL: @n1(
271273
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
272-
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
273-
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
274-
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
274+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
275+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
275276
; CHECK-NEXT: ret i1 [[RET]]
276277
;
277278
%t0 = shl i8 1, %y ; not -1
@@ -284,9 +285,9 @@ define i1 @n1(i8 %x, i8 %y) {
284285
define i1 @n2(i8 %x, i8 %y) {
285286
; CHECK-LABEL: @n2(
286287
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
287-
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
288+
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2
288289
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
289-
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
290+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
290291
; CHECK-NEXT: ret i1 [[RET]]
291292
;
292293
%t0 = shl i8 -1, %y

llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
144144
; CHECK-LABEL: @oneuse0(
145145
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
146146
; CHECK-NEXT: call void @use8(i8 [[T0]])
147-
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
147+
; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
148148
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
149149
; CHECK-NEXT: ret i1 [[RET]]
150150
;
@@ -161,7 +161,8 @@ define i1 @oneuse1(i8 %x, i8 %y) {
161161
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
162162
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
163163
; CHECK-NEXT: call void @use8(i8 [[T1]])
164-
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
164+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
165+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
165166
; CHECK-NEXT: ret i1 [[RET]]
166167
;
167168
%t0 = shl i8 -1, %y
@@ -195,7 +196,8 @@ define i1 @oneuse3(i8 %x, i8 %y) {
195196
; CHECK-NEXT: call void @use8(i8 [[T0]])
196197
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
197198
; CHECK-NEXT: call void @use8(i8 [[T1]])
198-
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
199+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
200+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
199201
; CHECK-NEXT: ret i1 [[RET]]
200202
;
201203
%t0 = shl i8 -1, %y
@@ -269,9 +271,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
269271
define i1 @n1(i8 %x, i8 %y) {
270272
; CHECK-LABEL: @n1(
271273
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
272-
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
273-
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
274-
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
274+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
275+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
275276
; CHECK-NEXT: ret i1 [[RET]]
276277
;
277278
%t0 = shl i8 1, %y ; not -1
@@ -284,9 +285,9 @@ define i1 @n1(i8 %x, i8 %y) {
284285
define i1 @n2(i8 %x, i8 %y) {
285286
; CHECK-LABEL: @n2(
286287
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
287-
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
288+
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2
288289
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
289-
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
290+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
290291
; CHECK-NEXT: ret i1 [[RET]]
291292
;
292293
%t0 = shl i8 -1, %y

llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) {
251251
; CHECK-LABEL: @n1(
252252
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
253253
; CHECK-NEXT: call void @use8(i8 [[T0]])
254-
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
254+
; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]
255255
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
256-
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
256+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
257257
; CHECK-NEXT: ret i1 [[RET]]
258258
;
259259
%t0 = shl i8 -1, %y ; not 1
@@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) {
268268
; CHECK-LABEL: @n2(
269269
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
270270
; CHECK-NEXT: call void @use8(i8 [[T0]])
271-
; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1
271+
; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]]
272272
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
273-
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
273+
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
274274
; CHECK-NEXT: ret i1 [[RET]]
275275
;
276276
%t0 = shl i8 1, %y

llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) {
251251
; CHECK-LABEL: @n1(
252252
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
253253
; CHECK-NEXT: call void @use8(i8 [[T0]])
254-
; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
254+
; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]
255255
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
256-
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
256+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
257257
; CHECK-NEXT: ret i1 [[RET]]
258258
;
259259
%t0 = shl i8 -1, %y ; not 1
@@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) {
268268
; CHECK-LABEL: @n2(
269269
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
270270
; CHECK-NEXT: call void @use8(i8 [[T0]])
271-
; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1
271+
; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]]
272272
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
273-
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
273+
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
274274
; CHECK-NEXT: ret i1 [[RET]]
275275
;
276276
%t0 = shl i8 1, %y

0 commit comments

Comments
 (0)