Skip to content

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Sep 10, 2023

This patch simplifies the overflow check of unsigned addition.

a + b <u a implies a + b <u b
a + b >=u a implies a + b >=u b

Alive2: https://alive2.llvm.org/ce/z/H8oK8n
Fixes #65863.

@dtcxzyw dtcxzyw requested review from a team as code owners September 10, 2023 20:06
@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Sep 10, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 10, 2023

@llvm/pr-subscribers-llvm-analysis

Changes

This patch simplifies the overflow check of unsigned addition.

a + b <u a implies a + b <u b
a + b >=u a implies a + b >=u b

Alive2: https://alive2.llvm.org/ce/z/H8oK8n
Fixes #65863.

--
Full diff: https://github.com/llvm/llvm-project/pull/65910.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+20)
  • (modified) llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll (+104)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..e77310ca1fdf01c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8291,6 +8291,26 @@ static std::optional isImpliedCondICmps(const ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
     return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 

@RKSimon
Copy link
Collaborator

RKSimon commented Sep 13, 2023

Please can you pre-commit the tests to show the IR diff?

@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2023

@llvm/pr-subscribers-llvm-transforms

Changes

This patch simplifies the overflow check of unsigned addition.

a + b &lt;u a implies a + b &lt;u b
a + b &gt;=u a implies a + b &gt;=u b

Alive2: https://alive2.llvm.org/ce/z/H8oK8n
Fixes #65863.


Full diff: https://github.com/llvm/llvm-project/pull/65910.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+23)
  • (modified) llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll (+8-24)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..5aaff4ee81be969 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8291,6 +8291,29 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
     return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 <u L1 implies R0 <u R1
+  if (ICmpInst::isUnsigned(LPred) && ICmpInst::isUnsigned(RPred)) {
+    if (L0 == R1) {
+      std::swap(R0, R1);
+      RPred = ICmpInst::getSwappedPredicate(RPred);
+    }
+    if (L1 == R0) {
+      std::swap(L0, L1);
+      LPred = ICmpInst::getSwappedPredicate(LPred);
+    }
+    if (L1 == R1) {
+      std::swap(L0, L1);
+      LPred = ICmpInst::getSwappedPredicate(LPred);
+      std::swap(R0, R1);
+      RPred = ICmpInst::getSwappedPredicate(RPred);
+    }
+    if (L0 == R0 &&
+        (LPred == ICmpInst::ICMP_UGE || LPred == ICmpInst::ICMP_ULT) &&
+        (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) &&
+        match(L0, m_c_Add(m_Specific(L1), m_Specific(R1))))
+      return LPred == RPred;
+  }
+
   if (LPred == RPred)
     return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth);
 
diff --git a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
index 4a6610250df559a..df442dd8f185c81 100644
--- a/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
+++ b/llvm/test/Transforms/InstSimplify/and-or-implied-cond.ll
@@ -131,9 +131,7 @@ define i1 @uaddo_and(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_and(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp uge i64 [[S]], [[A]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp uge i64 [[S]], [[B]]
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp uge i64 %s, %a
@@ -146,9 +144,7 @@ define i1 @uaddo_and_commuted1(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_and_commuted1(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ule i64 [[A]], [[S]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp uge i64 [[S]], [[B]]
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ule i64 %a, %s
@@ -161,9 +157,7 @@ define i1 @uaddo_and_commuted2(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_and_commuted2(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp uge i64 [[S]], [[A]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ule i64 [[B]], [[S]]
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp uge i64 %s, %a
@@ -176,9 +170,7 @@ define i1 @uaddo_and_commuted3(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_and_commuted3(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ule i64 [[A]], [[S]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ule i64 [[B]], [[S]]
-; CHECK-NEXT:    [[COND:%.*]] = and i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ule i64 %a, %s
@@ -191,9 +183,7 @@ define i1 @uaddo_or(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_or(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ult i64 [[S]], [[A]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ult i64 [[S]], [[B]]
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ult i64 %s, %a
@@ -206,9 +196,7 @@ define i1 @uaddo_or_commuted1(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_or_commuted1(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ugt i64 [[A]], [[S]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ult i64 [[S]], [[B]]
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ugt i64 %a, %s
@@ -221,9 +209,7 @@ define i1 @uaddo_or_commuted2(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_or_commuted2(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ult i64 [[S]], [[A]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ugt i64 [[B]], [[S]]
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ult i64 %s, %a
@@ -236,9 +222,7 @@ define i1 @uaddo_or_commuted3(i64 %a, i64 %b){
 ; CHECK-LABEL: @uaddo_or_commuted3(
 ; CHECK-NEXT:    [[S:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    [[COND_A:%.*]] = icmp ugt i64 [[A]], [[S]]
-; CHECK-NEXT:    [[COND_B:%.*]] = icmp ugt i64 [[B]], [[S]]
-; CHECK-NEXT:    [[COND:%.*]] = or i1 [[COND_A]], [[COND_B]]
-; CHECK-NEXT:    ret i1 [[COND]]
+; CHECK-NEXT:    ret i1 [[COND_A]]
 ;
   %s = add i64 %a, %b
   %cond_a = icmp ugt i64 %a, %s

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Sep 19, 2023

Ping.

@dtcxzyw dtcxzyw requested a review from goldsteinn September 24, 2023 09:09
@goldsteinn
Copy link
Contributor

LGTM.

@dtcxzyw dtcxzyw merged commit 9f2fc88 into llvm:main Sep 28, 2023
@dtcxzyw dtcxzyw deleted the uaddo-check-imply branch September 28, 2023 17:59
legrosbuffle pushed a commit to legrosbuffle/llvm-project that referenced this pull request Sep 29, 2023
This patch simplifies the overflow check of unsigned addition.

`a + b <u a` implies `a + b <u b`
`a + b >=u a` implies `a + b >=u b`

Alive2: https://alive2.llvm.org/ce/z/H8oK8n
Fixes llvm#65863.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplify add-with-overflow pattern (uaddo)
4 participants