[llvm] f6a8775 - [InstSimplify] Fold icmp of uadd.sat/usub.sat (PR63381)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 19 02:49:48 PDT 2023


Author: Nikita Popov
Date: 2023-06-19T11:49:38+02:00
New Revision: f6a8775c5d9fa6cd49f404da70982f2e7b91c88c

URL: https://github.com/llvm/llvm-project/commit/f6a8775c5d9fa6cd49f404da70982f2e7b91c88c
DIFF: https://github.com/llvm/llvm-project/commit/f6a8775c5d9fa6cd49f404da70982f2e7b91c88c.diff

LOG: [InstSimplify] Fold icmp of uadd.sat/usub.sat (PR63381)

Fold uadd.sat(X, Y) uge X and usub.sat(X, Y) ule X to true.

Proof: https://alive2.llvm.org/ce/z/596m9X

Fixes https://github.com/llvm/llvm-project/issues/63381.

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/saturating-add-sub.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 616873f87f313..48ffa83d45cee 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3682,6 +3682,36 @@ static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate,
   return nullptr;
 }
 
+static Value *simplifyICmpWithIntrinsicOnLHS(CmpInst::Predicate Pred,
+                                             Value *LHS, Value *RHS) {
+  auto *II = dyn_cast<IntrinsicInst>(LHS);
+  if (!II)
+    return nullptr;
+
+  switch (II->getIntrinsicID()) {
+  case Intrinsic::uadd_sat:
+    // uadd.sat(X, Y) uge X, uadd.sat(X, Y) uge Y
+    if (II->getArgOperand(0) == RHS || II->getArgOperand(1) == RHS) {
+      if (Pred == ICmpInst::ICMP_UGE)
+        return ConstantInt::getTrue(getCompareTy(II));
+      if (Pred == ICmpInst::ICMP_ULT)
+        return ConstantInt::getFalse(getCompareTy(II));
+    }
+    return nullptr;
+  case Intrinsic::usub_sat:
+    // usub.sat(X, Y) ule X
+    if (II->getArgOperand(0) == RHS) {
+      if (Pred == ICmpInst::ICMP_ULE)
+        return ConstantInt::getTrue(getCompareTy(II));
+      if (Pred == ICmpInst::ICMP_UGT)
+        return ConstantInt::getFalse(getCompareTy(II));
+    }
+    return nullptr;
+  default:
+    return nullptr;
+  }
+}
+
 /// Given operands for an ICmpInst, see if we can fold the result.
 /// If not, this returns null.
 static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
@@ -3946,6 +3976,12 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
   if (Value *V = simplifyICmpWithMinMax(Pred, LHS, RHS, Q, MaxRecurse))
     return V;
 
+  if (Value *V = simplifyICmpWithIntrinsicOnLHS(Pred, LHS, RHS))
+    return V;
+  if (Value *V = simplifyICmpWithIntrinsicOnLHS(
+          ICmpInst::getSwappedPredicate(Pred), RHS, LHS))
+    return V;
+
   if (Value *V = simplifyICmpWithDominatingAssume(Pred, LHS, RHS, Q))
     return V;
 

diff  --git a/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll b/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
index 616a2060e5339..6fb12612f2f72 100644
--- a/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
+++ b/llvm/test/Transforms/InstSimplify/saturating-add-sub.ll
@@ -797,9 +797,7 @@ define i1 @ssub_icmp_op1_smin(i8 %a) {
 
 define i1 @uadd_uge(i8 %x, i8 %y) {
 ; CHECK-LABEL: @uadd_uge(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[SAT]], [[X]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
   %cmp = icmp uge i8 %sat, %x
@@ -808,9 +806,7 @@ define i1 @uadd_uge(i8 %x, i8 %y) {
 
 define i1 @uadd_uge_rhs(i8 %x, i8 %y) {
 ; CHECK-LABEL: @uadd_uge_rhs(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[SAT]], [[Y]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
   %cmp = icmp uge i8 %sat, %y
@@ -819,9 +815,7 @@ define i1 @uadd_uge_rhs(i8 %x, i8 %y) {
 
 define i1 @uadd_uge_commuted(i8 %x, i8 %y) {
 ; CHECK-LABEL: @uadd_uge_commuted(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[X]], [[SAT]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
   %cmp = icmp ule i8 %x, %sat
@@ -830,9 +824,7 @@ define i1 @uadd_uge_commuted(i8 %x, i8 %y) {
 
 define i1 @uadd_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @uadd_ult(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[SAT]], [[X]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %sat = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
   %cmp = icmp ult i8 %sat, %x
@@ -841,9 +833,7 @@ define i1 @uadd_ult(i8 %x, i8 %y) {
 
 define <2 x i1> @uadd_uge_vec(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @uadd_uge_vec(
-; CHECK-NEXT:    [[SAT:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge <2 x i8> [[SAT]], [[X]]
-; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %sat = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %x, <2 x i8> %y)
   %cmp = icmp uge <2 x i8> %sat, %x
@@ -885,9 +875,7 @@ define i1 @uadd_uge_unrelated_op_fail(i8 %x, i8 %y, i8 %z) {
 
 define i1 @usub_ule(i8 %x, i8 %y) {
 ; CHECK-LABEL: @usub_ule(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[SAT]], [[X]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
   %cmp = icmp ule i8 %sat, %x
@@ -907,9 +895,7 @@ define i1 @usub_ule_rhs_fail(i8 %x, i8 %y) {
 
 define i1 @usub_ule_commuted(i8 %x, i8 %y) {
 ; CHECK-LABEL: @usub_ule_commuted(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[X]], [[SAT]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
   %cmp = icmp uge i8 %x, %sat
@@ -918,9 +904,7 @@ define i1 @usub_ule_commuted(i8 %x, i8 %y) {
 
 define i1 @usub_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @usub_ugt(
-; CHECK-NEXT:    [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SAT]], [[X]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %sat = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
   %cmp = icmp ugt i8 %sat, %x


        


More information about the llvm-commits mailing list