[llvm] [InstCombine] Make the `(icmp eq/ne (and X, Y), X)` canonicalization work for non-const operands (PR #84688)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 17 12:09:30 PDT 2024
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/84688
>From d2e389feb904474e665c3c5d7c0cc40bf60ececf Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Fri, 22 Mar 2024 12:04:58 -0500
Subject: [PATCH 1/3] [InstCombine] Add multiuse tests for canonicalizing (icmp
eq/ne (and x, y), {x,y}); NFC
---
.../test/Transforms/InstCombine/icmp-of-and-x.ll | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
index e95c72b75f97df..75070e5a34f949 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
@@ -3,6 +3,7 @@
declare i1 @barrier()
declare void @llvm.assume(i1)
+declare void @use.i8(i8)
define i1 @icmp_ult_x_y(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_ult_x_y(
@@ -262,6 +263,21 @@ define i1 @icmp_eq_x_invertable_y(i8 %x, i8 %y) {
ret i1 %r
}
+define i1 @icmp_eq_x_invertable_y_fail_multiuse(i8 %x, i8 %y) {
+; CHECK-LABEL: @icmp_eq_x_invertable_y_fail_multiuse(
+; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]]
+; CHECK-NEXT: call void @use.i8(i8 [[AND]])
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %yy = xor i8 %y, -1
+ %and = and i8 %x, %yy
+ call void @use.i8(i8 %and)
+ %r = icmp eq i8 %x, %and
+ ret i1 %r
+}
+
define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) {
; CHECK-LABEL: @icmp_eq_x_invertable_y2_todo(
; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 7, i8 24
>From 1771fdef82f8174739b2165527e9d9b9707f4b3b Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 13 Sep 2023 13:45:58 -0500
Subject: [PATCH 2/3] [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
---
.../InstCombine/InstCombineCompares.cpp | 30 +++++-----
...low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll | 17 +++---
...low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll | 17 +++---
...low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll | 8 +--
...low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll | 8 +--
.../InstCombine/icmp-and-lowbit-mask.ll | 59 +++++++++----------
.../Transforms/InstCombine/icmp-of-and-x.ll | 20 +++----
7 files changed, 79 insertions(+), 80 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index de909077017432..98dffbfe66d3c3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4724,6 +4724,21 @@ static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q,
if (Pred == ICmpInst::ICMP_UGE)
return new ICmpInst(ICmpInst::ICMP_EQ, Op0, Op1);
+ if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) {
+ // icmp (X & Y) eq/ne Y --> (X | ~Y) eq/ne -1 if Y is freely invertible and
+ // Y is non-constant. If Y is constant the `X & C == C` form is preferable
+ // so don't do this fold.
+ if (!match(Op1, m_ImmConstant()))
+ if (auto *NotOp1 =
+ IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder))
+ return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1),
+ Constant::getAllOnesValue(Op1->getType()));
+ // icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible.
+ if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder))
+ return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA),
+ Constant::getNullValue(Op1->getType()));
+ }
+
return nullptr;
}
@@ -5498,21 +5513,6 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
}
}
- // canoncalize:
- // (icmp eq/ne (and X, C), X)
- // -> (icmp eq/ne (and X, ~C), 0)
- {
- Constant *CMask;
- A = nullptr;
- if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_ImmConstant(CMask)))))
- A = Op1;
- else if (match(Op1, m_OneUse(m_And(m_Specific(Op0), m_ImmConstant(CMask)))))
- A = Op0;
- if (A)
- return new ICmpInst(Pred, Builder.CreateAnd(A, Builder.CreateNot(CMask)),
- Constant::getNullValue(A->getType()));
- }
-
if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) {
// A == (A^B) -> B == 0
Value *OtherVal = A == Op0 ? B : A;
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
index 88487b38e2c708..0a7de501ca0225 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,7 +161,8 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -195,7 +196,8 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -269,9 +271,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
-; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 1, %y ; not -1
@@ -284,9 +285,9 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
+; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
index b717925fd644fc..54ff87676e71d9 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,7 +161,8 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -195,7 +196,8 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -269,9 +271,8 @@ define i1 @n0(i8 %x, i8 %y, i8 %notx) {
define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
-; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 1, %y ; not -1
@@ -284,9 +285,9 @@ define i1 @n1(i8 %x, i8 %y) {
define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
-; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
+; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -2
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
index a65be1e9ceeca3..c7c57b601eab38 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
@@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
+; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y ; not 1
@@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1
+; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 1, %y
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
index f156d9bf007cbb..d5826524f1637c 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v3-and-icmp-ne-to-icmp-ugt.ll
@@ -251,9 +251,9 @@ define i1 @n1(i8 %x, i8 %y) {
; CHECK-LABEL: @n1(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
+; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y ; not 1
@@ -268,9 +268,9 @@ define i1 @n2(i8 %x, i8 %y) {
; CHECK-LABEL: @n2(
; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1
+; CHECK-NEXT: [[T1:%.*]] = sub nuw i8 -2, [[T0]]
; CHECK-NEXT: [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], [[X]]
+; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[T2]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 1, %y
diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll
index 5de3e89d7027ab..8bb7fd0e522cb0 100644
--- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll
@@ -5,9 +5,9 @@ declare void @use.i8(i8)
declare void @use.i16(i16)
define i1 @src_is_mask_zext(i16 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_zext(
-; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123
; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16
+; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -22,11 +22,11 @@ define i1 @src_is_mask_zext(i16 %x_in, i8 %y) {
define i1 @src_is_mask_zext_fail_not_mask(i16 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_zext_fail_not_mask(
-; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123
; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -2, [[Y:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16
-; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[TMP1]], [[MASK]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[TMP2]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%x = xor i16 %x_in, 123
@@ -80,10 +80,10 @@ define i1 @src_is_mask_sext_fail_multiuse(i16 %x_in, i8 %y) {
define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) {
; CHECK-LABEL: @src_is_mask_and(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[MY:%.*]] = lshr i8 7, [[Y:%.*]]
; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]]
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -99,12 +99,12 @@ define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) {
define i1 @src_is_mask_and_fail_mixed(i8 %x_in, i8 %y, i8 %z) {
; CHECK-LABEL: @src_is_mask_and_fail_mixed(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[MY:%.*]] = ashr i8 -8, [[Y:%.*]]
; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]]
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[MASK]], [[TMP1]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%x = xor i8 %x_in, 123
@@ -119,9 +119,9 @@ define i1 @src_is_mask_and_fail_mixed(i8 %x_in, i8 %y, i8 %z) {
define i1 @src_is_mask_or(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_or(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[MY:%.*]] = lshr i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], 7
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -136,9 +136,9 @@ define i1 @src_is_mask_or(i8 %x_in, i8 %y) {
define i1 @src_is_mask_xor(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_xor(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -152,11 +152,11 @@ define i1 @src_is_mask_xor(i8 %x_in, i8 %y) {
define i1 @src_is_mask_xor_fail_notmask(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_xor_fail_notmask(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[Y:%.*]]
; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], [[Y]]
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]]
-; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]]
+; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X_IN:%.*]], -124
+; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[NOTMASK]], [[TMP2]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%x = xor i8 %x_in, 123
@@ -170,10 +170,10 @@ define i1 @src_is_mask_xor_fail_notmask(i8 %x_in, i8 %y) {
define i1 @src_is_mask_select(i8 %x_in, i8 %y, i1 %cond) {
; CHECK-LABEL: @src_is_mask_select(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -245,11 +245,11 @@ define i1 @src_is_mask_shl_lshr_fail_not_allones(i8 %x_in, i8 %y, i1 %cond) {
define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) {
; CHECK-LABEL: @src_is_mask_lshr(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15
; CHECK-NEXT: [[MASK:%.*]] = lshr i8 [[SMASK]], [[Z:%.*]]
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -265,11 +265,11 @@ define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) {
define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) {
; CHECK-LABEL: @src_is_mask_ashr(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15
; CHECK-NEXT: [[MASK:%.*]] = ashr i8 [[SMASK]], [[Z:%.*]]
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -285,9 +285,9 @@ define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) {
define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_p2_m1(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[P2ORZ:%.*]] = shl i8 2, [[Y:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = add i8 [[P2ORZ]], -1
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -301,10 +301,10 @@ define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) {
define i1 @src_is_mask_umax(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_umax(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umax.i8(i8 [[YMASK]], i8 3)
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -320,11 +320,11 @@ define i1 @src_is_mask_umax(i8 %x_in, i8 %y) {
define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) {
; CHECK-LABEL: @src_is_mask_umin(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[ZMASK:%.*]] = lshr i8 15, [[Z:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 [[ZMASK]])
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -341,12 +341,12 @@ define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) {
define i1 @src_is_mask_umin_fail_mismatch(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_umin_fail_mismatch(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 -32)
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[MASK]], [[TMP1]]
+; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP2]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%x = xor i8 %x_in, 123
@@ -361,10 +361,10 @@ define i1 @src_is_mask_umin_fail_mismatch(i8 %x_in, i8 %y) {
define i1 @src_is_mask_smax(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_smax(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smax.i8(i8 [[YMASK]], i8 -1)
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -380,10 +380,10 @@ define i1 @src_is_mask_smax(i8 %x_in, i8 %y) {
define i1 @src_is_mask_smin(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_smin(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1
; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smin.i8(i8 [[YMASK]], i8 0)
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -399,9 +399,9 @@ define i1 @src_is_mask_smin(i8 %x_in, i8 %y) {
define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_mask_bitreverse_not_mask(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]])
+; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]]
; CHECK-NEXT: ret i1 [[R]]
;
@@ -417,7 +417,7 @@ define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) {
define i1 @src_is_notmask_sext(i16 %x_in, i8 %y) {
; CHECK-LABEL: @src_is_notmask_sext(
; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -8, [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124
+; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -128
; CHECK-NEXT: [[TMP2:%.*]] = sext i8 [[M_IN]] to i16
; CHECK-NEXT: [[R:%.*]] = icmp uge i16 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i1 [[R]]
@@ -529,12 +529,11 @@ define i1 @src_is_notmask_lshr_shl(i8 %x_in, i8 %y) {
define i1 @src_is_notmask_lshr_shl_fail_mismatch_shifts(i8 %x_in, i8 %y, i8 %z) {
; CHECK-LABEL: @src_is_notmask_lshr_shl_fail_mismatch_shifts(
-; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
; CHECK-NEXT: [[MASK_SHR:%.*]] = lshr i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[NMASK:%.*]] = shl i8 [[MASK_SHR]], [[Z:%.*]]
-; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[NMASK]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], 123
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[NMASK]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%x = xor i8 %x_in, 123
diff --git a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
index 75070e5a34f949..0f26be12c39cc6 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll
@@ -239,9 +239,9 @@ define i1 @icmp_sle_negx_y_fail_maybe_zero(i8 %x, i8 %y) {
define i1 @icmp_eq_x_invertable_y_todo(i8 %x, i1 %y) {
; CHECK-LABEL: @icmp_eq_x_invertable_y_todo(
-; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 7, i8 24
+; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25
; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%yy = select i1 %y, i8 7, i8 24
@@ -252,9 +252,8 @@ define i1 @icmp_eq_x_invertable_y_todo(i8 %x, i1 %y) {
define i1 @icmp_eq_x_invertable_y(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_eq_x_invertable_y(
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%yy = xor i8 %y, -1
@@ -280,9 +279,9 @@ define i1 @icmp_eq_x_invertable_y_fail_multiuse(i8 %x, i8 %y) {
define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) {
; CHECK-LABEL: @icmp_eq_x_invertable_y2_todo(
-; CHECK-NEXT: [[YY:%.*]] = select i1 [[Y:%.*]], i8 7, i8 24
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[YY]], [[AND]]
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25
+; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%yy = select i1 %y, i8 7, i8 24
@@ -293,9 +292,8 @@ define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) {
define i1 @icmp_eq_x_invertable_y2(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_eq_x_invertable_y2(
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[YY]], [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[YY]]
+; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%yy = xor i8 %y, -1
>From b38251ba59d2f15a19920b8f3c0ff625c06fae46 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Fri, 22 Mar 2024 11:57:15 -0500
Subject: [PATCH 3/3] [InstCombine] Fix regressions from canonicalizing `(icmp
eq/ne (X, Y), Y` -> `(icmp eq/ne (~X, Y), 0)`
This issue is the canonicalization can consume `not` instruction which
are a limitted resource and are use to enable multiple transforms.
In this case `foldICmpWithLowBitMaskedVal` is a "better" user of `not`
instructions, so just check if that has a result first.
---
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 5 +++++
...anonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll | 8 +++-----
...anonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll | 8 +++-----
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 98dffbfe66d3c3..5ef6861755f689 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4734,6 +4734,11 @@ static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q,
return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1),
Constant::getAllOnesValue(Op1->getType()));
// icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible.
+ // Since we may be consuming a `not` here, first check if we match
+ // `foldICmpWithLowBitMaskedVal` as it is a "better" user of `not`
+ // instructions.
+ if (Value *R = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Q, IC))
+ return IC.replaceInstUsesWith(I, R);
if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder))
return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA),
Constant::getNullValue(Op1->getType()));
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
index 0a7de501ca0225..24ca49386b7e88 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,8 +161,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -196,8 +195,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
index 54ff87676e71d9..271d78d589b609 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,8 +161,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -196,8 +195,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
More information about the llvm-commits
mailing list