Skip to content

Commit 5532ab1

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 Closes #84688
1 parent 9871486 commit 5532ab1

8 files changed

+88
-89
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

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

4733+
if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) {
4734+
// icmp (X & Y) eq/ne Y --> (X | ~Y) eq/ne -1 if Y is freely invertible and
4735+
// Y is non-constant. If Y is constant the `X & C == C` form is preferable
4736+
// so don't do this fold.
4737+
if (!match(Op1, m_ImmConstant()))
4738+
if (auto *NotOp1 =
4739+
IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder))
4740+
return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1),
4741+
Constant::getAllOnesValue(Op1->getType()));
4742+
// icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible.
4743+
if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder))
4744+
return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA),
4745+
Constant::getNullValue(Op1->getType()));
4746+
}
4747+
47334748
return nullptr;
47344749
}
47354750

@@ -5505,21 +5520,6 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
55055520
}
55065521
}
55075522

5508-
// canoncalize:
5509-
// (icmp eq/ne (and X, C), X)
5510-
// -> (icmp eq/ne (and X, ~C), 0)
5511-
{
5512-
Constant *CMask;
5513-
A = nullptr;
5514-
if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_ImmConstant(CMask)))))
5515-
A = Op1;
5516-
else if (match(Op1, m_OneUse(m_And(m_Specific(Op0), m_ImmConstant(CMask)))))
5517-
A = Op0;
5518-
if (A)
5519-
return new ICmpInst(Pred, Builder.CreateAnd(A, Builder.CreateNot(CMask)),
5520-
Constant::getNullValue(A->getType()));
5521-
}
5522-
55235523
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) {
55245524
// A == (A^B) -> B == 0
55255525
Value *OtherVal = A == Op0 ? B : A;

llvm/test/Analysis/ValueTracking/known-power-of-two-urem.ll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,9 @@ define i8 @known_power_of_two_lshr_add_one_allow_zero(i8 %x, i8 %y) {
428428
define i1 @known_power_of_two_lshr_add_one_nuw_deny_zero(i8 %x, i8 %y) {
429429
; CHECK-LABEL: @known_power_of_two_lshr_add_one_nuw_deny_zero(
430430
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]]
431-
; CHECK-NEXT: [[P:%.*]] = add nuw i8 [[TMP1]], 1
432-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[P]], [[Y:%.*]]
433-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
431+
; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]]
432+
; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[Y:%.*]]
433+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1
434434
; CHECK-NEXT: ret i1 [[R]]
435435
;
436436
%4 = lshr i8 -1, %x
@@ -445,9 +445,9 @@ define i1 @known_power_of_two_lshr_add_one_nuw_deny_zero(i8 %x, i8 %y) {
445445
define i1 @negative_known_power_of_two_lshr_add_one_deny_zero(i8 %x, i8 %y) {
446446
; CHECK-LABEL: @negative_known_power_of_two_lshr_add_one_deny_zero(
447447
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]]
448-
; CHECK-NEXT: [[P:%.*]] = add i8 [[TMP1]], 1
449-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[P]], [[Y:%.*]]
450-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[P]]
448+
; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]]
449+
; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[Y:%.*]]
450+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1
451451
; CHECK-NEXT: ret i1 [[R]]
452452
;
453453
%4 = lshr i8 -1, %x
@@ -462,9 +462,9 @@ define i1 @negative_known_power_of_two_lshr_add_one_deny_zero(i8 %x, i8 %y) {
462462
define i1 @negative_known_power_of_two_lshr_add_one_nsw_deny_zero(i8 %x, i8 %y) {
463463
; CHECK-LABEL: @negative_known_power_of_two_lshr_add_one_nsw_deny_zero(
464464
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]]
465-
; CHECK-NEXT: [[P:%.*]] = add nsw i8 [[TMP1]], 1
466-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[P]], [[Y:%.*]]
467-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[P]]
465+
; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]]
466+
; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[Y:%.*]]
467+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1
468468
; CHECK-NEXT: ret i1 [[R]]
469469
;
470470
%4 = lshr i8 -1, %x

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)