[llvm] [InstCombine] Fold `icmp eq/ne (X *nw Z), (Y *nw Z) -> icmp eq/ne Z, 0` when `X != Y` (PR #110413)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 29 01:16:09 PDT 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/110413
Alive2: https://alive2.llvm.org/ce/z/9oDP6K
I found this pattern in https://github.com/casadi/casadi/blob/04e75858d7e626dda62d83b862fc89fc26f52745/casadi/core/repmat.cpp#L70-L78.
>From 2b742305a9d2437dc81958950dfb48ce81684855 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 29 Sep 2024 15:58:05 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/icmp-mul.ll | 119 +++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll
index 3ba21abb069ba7..bdb092c4233c1b 100644
--- a/llvm/test/Transforms/InstCombine/icmp-mul.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll
@@ -1223,3 +1223,122 @@ define <2 x i1> @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule(<2 x i8> %x, <2 x i8>
%cmp = icmp ule <2 x i8> %muly, %mulx
ret <2 x i1> %cmp
}
+
+define i1 @icmp_eq_mul_nsw_nonequal(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nsw i8 %b, %c
+ %cmp = icmp eq i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+define i1 @icmp_eq_mul_nuw_nonequal(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_eq_mul_nuw_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nuw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nuw i8 [[B]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nuw i8 %a, %c
+ %mul2 = mul nuw i8 %b, %c
+ %cmp = icmp eq i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+define i1 @icmp_eq_mul_nsw_nonequal_commuted(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal_commuted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[C]], [[B]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nsw i8 %c, %b
+ %cmp = icmp eq i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+define i1 @icmp_ne_mul_nsw_nonequal(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_ne_mul_nsw_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nsw i8 %b, %c
+ %cmp = icmp ne i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+; Negative tests
+
+define i1 @icmp_eq_mul_nsw_mayequal(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: @icmp_eq_mul_nsw_mayequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B:%.*]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nsw i8 %b, %c
+ %cmp = icmp eq i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+define i1 @icmp_eq_mul_nsw_nuw_nonequal(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_eq_mul_nsw_nuw_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nuw i8 [[B]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nuw i8 %b, %c
+ %cmp = icmp eq i8 %mul1, %mul2
+ ret i1 %cmp
+}
+
+define i1 @icmp_ult_mul_nsw_nonequal(i8 %a, i8 %c) {
+; CHECK-LABEL: @icmp_ult_mul_nsw_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
+; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %b = add i8 %a, 1
+ %mul1 = mul nsw i8 %a, %c
+ %mul2 = mul nsw i8 %b, %c
+ %cmp = icmp ult i8 %mul1, %mul2
+ ret i1 %cmp
+}
>From 72683a84270e5627ea4b696c79b69b2216055034 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 29 Sep 2024 16:10:43 +0800
Subject: [PATCH 2/2] [InstCombine] Fold `icmp eq/ne (X *nw Z), (Y *nw Z) ->
icmp eq/ne Z, 0` when `X != Y`
---
.../InstCombine/InstCombineCompares.cpp | 5 +++++
llvm/test/Transforms/InstCombine/icmp-mul.ll | 20 ++++---------------
2 files changed, 9 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index b1215bb4d83b0f..e3f4925024e65c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5282,6 +5282,11 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
match(Op1, m_c_Mul(m_Specific(Z), m_Value(Y)))))) {
bool NonZero;
if (ICmpInst::isEquality(Pred)) {
+ // If X != Y, fold (X *nw Z) eq/ne (Y *nw Z) -> Z eq/ne 0
+ if (((Op0HasNSW && Op1HasNSW) || (Op0HasNUW && Op1HasNUW)) &&
+ isKnownNonEqual(X, Y, DL, &AC, &I, &DT))
+ return new ICmpInst(Pred, Z, Constant::getNullValue(Z->getType()));
+
KnownBits ZKnown = computeKnownBits(Z, 0, &I);
// if Z % 2 != 0
// X * Z eq/ne Y * Z -> X eq/ne Y
diff --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll
index bdb092c4233c1b..7ce43908c62cd0 100644
--- a/llvm/test/Transforms/InstCombine/icmp-mul.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll
@@ -1227,10 +1227,7 @@ define <2 x i1> @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule(<2 x i8> %x, <2 x i8>
define i1 @icmp_eq_mul_nsw_nonequal(i8 %a, i8 %c) {
; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
-; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
@@ -1244,10 +1241,7 @@ entry:
define i1 @icmp_eq_mul_nuw_nonequal(i8 %a, i8 %c) {
; CHECK-LABEL: @icmp_eq_mul_nuw_nonequal(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
-; CHECK-NEXT: [[MUL1:%.*]] = mul nuw i8 [[A]], [[C:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul nuw i8 [[B]], [[C]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
@@ -1261,10 +1255,7 @@ entry:
define i1 @icmp_eq_mul_nsw_nonequal_commuted(i8 %a, i8 %c) {
; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal_commuted(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
-; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[C]], [[B]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
@@ -1278,10 +1269,7 @@ entry:
define i1 @icmp_ne_mul_nsw_nonequal(i8 %a, i8 %c) {
; CHECK-LABEL: @icmp_ne_mul_nsw_nonequal(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], 1
-; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
-; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[MUL1]], [[MUL2]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[C:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
More information about the llvm-commits
mailing list