-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[InstSimplify] Extend icmp-of-add simplification to sle/sgt/sge #168900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When comparing additions with the same base where one has `nsw`, the following simplification can be performed: ```llvm icmp slt/sgt/sle/sge (x + C1), (x +nsw C2) => icmp slt/sgt/sle/sge C1, C2 ``` Previously this was only done for `slt`. This patch extends it to the `sgt`, `sle`, and `sge` predicates when either of the conditions hold: - `C1 <= C2 && C1 >= 0`, or - `C2 <= C1 && C1 <= 0` This patch also handles the `C1 == C2` case, which was previously excluded. Proof: https://alive2.llvm.org/ce/z/LtmY4f
|
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: Pedro Lobo (pedroclobo) ChangesWhen comparing additions with the same base where one has icmp slt/sgt/sle/sge (x + C1), (x +nsw C2)
=>
icmp slt/sgt/sle/sge C1, C2Previously this was only done for
This patch also handles the Proof: https://alive2.llvm.org/ce/z/LtmY4f Full diff: https://github.com/llvm/llvm-project/pull/168900.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 8968f6b934d77..452cba23e3309 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3261,20 +3261,22 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpPredicate Pred, BinaryOperator *LBO,
// If only one of the icmp's operands has NSW flags, try to prove that:
//
-// icmp slt (x + C1), (x +nsw C2)
+// icmp slt/sgt/sle/sge (x + C1), (x +nsw C2)
//
// is equivalent to:
//
-// icmp slt C1, C2
+// icmp slt/sgt/sle/sge C1, C2
//
// which is true if x + C2 has the NSW flags set and:
-// *) C1 < C2 && C1 >= 0, or
-// *) C2 < C1 && C1 <= 0.
+// *) C1 <= C2 && C1 >= 0, or
+// *) C2 <= C1 && C1 <= 0.
//
static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS,
const InstrInfoQuery &IIQ) {
- // TODO: only support icmp slt for now.
- if (Pred != CmpInst::ICMP_SLT || !IIQ.UseInstrInfo)
+ // TODO: support other predicates.
+ if ((Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_SGT &&
+ Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SGE) ||
+ !IIQ.UseInstrInfo)
return false;
// Canonicalize nsw add as RHS.
@@ -3289,8 +3291,8 @@ static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS,
!match(RHS, m_Add(m_Specific(X), m_APInt(C2))))
return false;
- return (C1->slt(*C2) && C1->isNonNegative()) ||
- (C2->slt(*C1) && C1->isNonPositive());
+ return (C1->sle(*C2) && C1->isNonNegative()) ||
+ (C2->sle(*C1) && C1->isNonPositive());
}
/// TODO: A large part of this logic is duplicated in InstCombine's
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index 97ac8f2ea47ea..ba10ea532a34a 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -2687,10 +2687,7 @@ define i1 @icmp_nsw_false_2(i32 %V) {
define i1 @icmp_nsw_false_3(i32 %V) {
; CHECK-LABEL: @icmp_nsw_false_3(
-; CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[V:%.*]], 5
-; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[V]], 5
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD6]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%add5 = add nsw i32 %V, 5
%add6 = add i32 %V, 5
@@ -2724,6 +2721,45 @@ define i1 @icmp_nsw_false_5(i8 %V) {
ret i1 %cmp
}
+define i1 @icmp_nsw_false_6(i8 %V) {
+; CHECK-LABEL: @icmp_nsw_false_6(
+; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], 6
+; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], -1
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], [[ADDNSW]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %add = add i8 %V, 6
+ %addnsw = add nsw i8 %V, -1
+ %cmp = icmp sgt i8 %add, %addnsw
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_false_7(i8 %V) {
+; CHECK-LABEL: @icmp_nsw_false_7(
+; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -1
+; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 3
+; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[ADD]], [[ADDNSW]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %add = add i8 %V, -1
+ %addnsw = add nsw i8 %V, 3
+ %cmp = icmp sle i8 %add, %addnsw
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_false_8(i8 %V) {
+; CHECK-LABEL: @icmp_nsw_false_8(
+; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -15
+; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 42
+; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[ADD]], [[ADDNSW]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %add = add i8 %V, -15
+ %addnsw = add nsw i8 %V, 42
+ %cmp = icmp sge i8 %add, %addnsw
+ ret i1 %cmp
+}
+
define i1 @icmp_nsw_i8(i8 %V) {
; CHECK-LABEL: @icmp_nsw_i8(
; CHECK-NEXT: ret i1 true
@@ -2766,10 +2802,7 @@ define <4 x i1> @icmp_nsw_vec(<4 x i32> %V) {
define i1 @icmp_nsw_3(i32 %V) {
; CHECK-LABEL: @icmp_nsw_3(
-; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5
-; CHECK-NEXT: [[ADD5_2:%.*]] = add nsw i32 [[V]], 5
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD5_2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%add5 = add i32 %V, 5
%add5_2 = add nsw i32 %V, 5
@@ -2844,10 +2877,7 @@ define i1 @icmp_nsw_9(i32 %V1, i32 %V2) {
define i1 @icmp_nsw_10(i32 %V) {
; CHECK-LABEL: @icmp_nsw_10(
-; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5
-; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 6
-; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD6]], [[ADD5]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%add5 = add i32 %V, 5
%add6 = add nsw i32 %V, 6
@@ -2868,6 +2898,36 @@ define i1 @icmp_nsw_11(i32 %V) {
ret i1 %cmp
}
+define i1 @icmp_nsw_12(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_12(
+; CHECK-NEXT: ret i1 true
+;
+ %add5 = add i32 %V, 2
+ %add6 = add nsw i32 %V, 3
+ %cmp = icmp slt i32 %add5, %add6
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_13(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_13(
+; CHECK-NEXT: ret i1 true
+;
+ %add5 = add i32 %V, 7
+ %add6 = add nsw i32 %V, 10
+ %cmp = icmp sle i32 %add5, %add6
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_14(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_14(
+; CHECK-NEXT: ret i1 false
+;
+ %add5 = add i32 %V, 7
+ %add6 = add nsw i32 %V, 10
+ %cmp = icmp sge i32 %add5, %add6
+ ret i1 %cmp
+}
+
define i1 @icmp_nsw_nonpos(i32 %V) {
; CHECK-LABEL: @icmp_nsw_nonpos(
; CHECK-NEXT: ret i1 false
@@ -2890,6 +2950,36 @@ define i1 @icmp_nsw_nonpos2(i32 %V) {
ret i1 %cmp
}
+define i1 @icmp_nsw_nonpos3(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_nonpos3(
+; CHECK-NEXT: ret i1 false
+;
+ %add5 = add i32 %V, -2
+ %add6 = add nsw i32 %V, -5
+ %cmp = icmp sle i32 %add5, %add6
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_nonpos4(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_nonpos4(
+; CHECK-NEXT: ret i1 true
+;
+ %add5 = add i32 %V, -10
+ %add6 = add nsw i32 %V, -30
+ %cmp = icmp sgt i32 %add5, %add6
+ ret i1 %cmp
+}
+
+define i1 @icmp_nsw_nonpos5(i32 %V) {
+; CHECK-LABEL: @icmp_nsw_nonpos5(
+; CHECK-NEXT: ret i1 true
+;
+ %add5 = add i32 %V, -15
+ %add6 = add nsw i32 %V, -100
+ %cmp = icmp sge i32 %add5, %add6
+ ret i1 %cmp
+}
+
declare i11 @llvm.ctpop.i11(i11)
declare i73 @llvm.ctpop.i73(i73)
declare <2 x i13> @llvm.ctpop.v2i13(<2 x i13>)
|
🐧 Linux x64 Test Results
|
dtcxzyw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks.
When comparing additions with the same base where one has
nsw, thefollowing simplification can be performed:
Previously this was only done for
slt. This patch extends it to thesgt,sle, andsgepredicates when either of the conditions hold:C1 <= C2 && C1 >= 0, orC2 <= C1 && C1 <= 0This patch also handles the
C1 == C2case, which was previously excluded.Proof: https://alive2.llvm.org/ce/z/LtmY4f