[llvm] [Instsimplify] lshr&icmp adds support for the or instruction (PR #69445)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 18 03:51:18 PDT 2023
https://github.com/DianQK created https://github.com/llvm/llvm-project/pull/69445
Closes #69333.
>From 8664b9332743338dda52d0f30cb68acaa6117264 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Wed, 18 Oct 2023 08:05:41 +0800
Subject: [PATCH 1/3] [InstSimplify] Pre-commit tests for lshr&or
---
llvm/test/Transforms/InstSimplify/compare.ll | 142 +++++++++++++++++++
1 file changed, 142 insertions(+)
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index ac2ebf52ed6296e..9e80fa7ba4e93f2 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -565,6 +565,148 @@ define i1 @lshr7(i32 %X, i32 %Y) {
ret i1 %C
}
+define i1 @or_lshr1(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_lshr1(
+; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = lshr i32 %X, %Y
+ %B = or i32 %X, %Z
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_lshr2(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_lshr2(
+; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = lshr i32 %X, %Y
+ %B = or i32 %Y, %Z
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_lshr3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr3(
+; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = lshr i32 %X, %Y
+ %B0 = or i32 %X, %Z
+ %B = or i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_lshr4(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr4(
+; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = lshr i32 %X, %Y
+ %B0 = or i32 %Y, %Z
+ %B = or i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_lshr5(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr5(
+; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = and i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = lshr i32 %X, %Y
+ %B0 = or i32 %X, %Z
+ %B = and i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_udiv1(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_udiv1(
+; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = udiv i32 %X, %Y
+ %B = or i32 %X, %Z
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_udiv2(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_udiv2(
+; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = udiv i32 %X, %Y
+ %B = or i32 %Y, %Z
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_udiv3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv3(
+; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = udiv i32 %X, %Y
+ %B0 = or i32 %X, %Z
+ %B = or i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_udiv4(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv4(
+; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = udiv i32 %X, %Y
+ %B0 = or i32 %Y, %Z
+ %B = or i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
+define i1 @or_udiv5(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv5(
+; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT: [[B:%.*]] = and i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT: ret i1 [[C]]
+;
+ %A = udiv i32 %X, %Y
+ %B0 = or i32 %X, %Z
+ %B = and i32 %B0, %Z1
+ %C = icmp ult i32 %B, %A
+ ret i1 %C
+}
+
define i1 @lshr_nonzero_eq(i32 %x) {
; CHECK-LABEL: @lshr_nonzero_eq(
; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0
>From e043dda644d08a798f81a547d829cf9d13cb629d Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Wed, 18 Oct 2023 08:18:07 +0800
Subject: [PATCH 2/3] [InstSimplify] x >>u y <=u x | z --> true
---
llvm/lib/Analysis/InstructionSimplify.cpp | 27 +++++++++++++++-----
llvm/test/Transforms/InstSimplify/compare.ll | 10 ++------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index b3feb2470e58efd..7701e157172a1e9 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3174,16 +3174,29 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
}
// x >>u y <=u x --> true.
+ // x >>u y <=u x | z --> true.
// x >>u y >u x --> false.
+ // x >>u y >u x | z --> false.
// x udiv y <=u x --> true.
+ // x udiv y <=u x | z --> true.
// x udiv y >u x --> false.
- if (match(LBO, m_LShr(m_Specific(RHS), m_Value())) ||
- match(LBO, m_UDiv(m_Specific(RHS), m_Value()))) {
- // icmp pred (X op Y), X
- if (Pred == ICmpInst::ICMP_UGT)
- return getFalse(ITy);
- if (Pred == ICmpInst::ICMP_ULE)
- return getTrue(ITy);
+ // x udiv y >u x | z --> false.
+ const Value *RHS0;
+ if (match(LBO, m_LShr(m_Value(RHS0), m_Value())) ||
+ match(LBO, m_UDiv(m_Value(RHS0), m_Value()))) {
+ const Value *RHS1;
+ const Value *RHS2;
+ // TODO: We can handle multiple and instructions.
+ if (RHS0 == RHS || (match(RHS, m_Or(m_Value(RHS1), m_Value(RHS2))) &&
+ (RHS1 == RHS0 || RHS2 == RHS0))) {
+ // icmp pred (X op Y), X
+ if (Pred == ICmpInst::ICMP_UGT) {
+ return getFalse(ITy);
+ }
+ if (Pred == ICmpInst::ICMP_ULE) {
+ return getTrue(ITy);
+ }
+ }
}
// If x is nonzero:
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index 9e80fa7ba4e93f2..43dbe2a94e1fd3b 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -567,10 +567,7 @@ define i1 @lshr7(i32 %X, i32 %Y) {
define i1 @or_lshr1(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @or_lshr1(
-; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[B:%.*]] = or i32 [[X]], [[Z:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%A = lshr i32 %X, %Y
%B = or i32 %X, %Z
@@ -638,10 +635,7 @@ define i1 @or_lshr5(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
define i1 @or_udiv1(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @or_udiv1(
-; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[B:%.*]] = or i32 [[X]], [[Z:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%A = udiv i32 %X, %Y
%B = or i32 %X, %Z
>From 0f7fb8655d30dce926ee514635768b57eabe5bda Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Wed, 18 Oct 2023 08:36:26 +0800
Subject: [PATCH 3/3] [InstSimplify] x >>u y <=u x | z1 | z2 | ... --> true
---
llvm/lib/Analysis/InstructionSimplify.cpp | 23 +++++++++++++++-----
llvm/test/Transforms/InstSimplify/compare.ll | 12 ++--------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 7701e157172a1e9..1665d6d63ab6e34 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3103,6 +3103,23 @@ static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS,
return nullptr;
}
+static bool existOrChain(const Value *From, const Value *To) {
+ const Value *LVal;
+ const Value *RVal;
+ SmallVector<const Value *, 10> WorkList;
+ WorkList.push_back(From);
+ while (!WorkList.empty() && WorkList.size() < 16) {
+ From = WorkList.pop_back_val();
+ if (match(From, m_Or(m_Value(LVal), m_Value(RVal)))) {
+ if (LVal == To || RVal == To)
+ return true;
+ WorkList.push_back(LVal);
+ WorkList.push_back(RVal);
+ }
+ }
+ return false;
+}
+
static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
BinaryOperator *LBO, Value *RHS,
const SimplifyQuery &Q,
@@ -3184,11 +3201,7 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
const Value *RHS0;
if (match(LBO, m_LShr(m_Value(RHS0), m_Value())) ||
match(LBO, m_UDiv(m_Value(RHS0), m_Value()))) {
- const Value *RHS1;
- const Value *RHS2;
- // TODO: We can handle multiple and instructions.
- if (RHS0 == RHS || (match(RHS, m_Or(m_Value(RHS1), m_Value(RHS2))) &&
- (RHS1 == RHS0 || RHS2 == RHS0))) {
+ if (RHS0 == RHS || existOrChain(RHS, RHS0)) {
// icmp pred (X op Y), X
if (Pred == ICmpInst::ICMP_UGT) {
return getFalse(ITy);
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index 43dbe2a94e1fd3b..75c9a69b26245d4 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -590,11 +590,7 @@ define i1 @or_lshr2(i32 %X, i32 %Y, i32 %Z) {
define i1 @or_lshr3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
; CHECK-LABEL: @or_lshr3(
-; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
-; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%A = lshr i32 %X, %Y
%B0 = or i32 %X, %Z
@@ -658,11 +654,7 @@ define i1 @or_udiv2(i32 %X, i32 %Y, i32 %Z) {
define i1 @or_udiv3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
; CHECK-LABEL: @or_udiv3(
-; CHECK-NEXT: [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
-; CHECK-NEXT: [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], [[A]]
-; CHECK-NEXT: ret i1 [[C]]
+; CHECK-NEXT: ret i1 false
;
%A = udiv i32 %X, %Y
%B0 = or i32 %X, %Z
More information about the llvm-commits
mailing list