[llvm] 6b9317f - [InstCombine] Fold zero check followed by decrement to usub.sat

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 9 05:22:55 PST 2023


Author: Jamie Hill-Daniel
Date: 2023-01-09T14:22:25+01:00
New Revision: 6b9317f52a66318a57a216da2e5e4890ef2aef7b

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

LOG: [InstCombine] Fold zero check followed by decrement to usub.sat

Fold (a == 0) : 0 ? a - 1 into usub.sat(a, 1).

Differential Revision: https://reviews.llvm.org/D140798

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/Transforms/InstCombine/saturating-add-sub.ll
    llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
    llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 6fc7051669a92..ea30c01aeeeec 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -803,19 +803,31 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
                                             const Value *FalseVal,
                                             InstCombiner::BuilderTy &Builder) {
   ICmpInst::Predicate Pred = ICI->getPredicate();
-  if (!ICmpInst::isUnsigned(Pred))
-    return nullptr;
+  Value *A = ICI->getOperand(0);
+  Value *B = ICI->getOperand(1);
 
   // (b > a) ? 0 : a - b -> (b <= a) ? a - b : 0
+  // (a == 0) ? 0 : a - 1 -> (a != 0) ? a - 1 : 0
   if (match(TrueVal, m_Zero())) {
     Pred = ICmpInst::getInversePredicate(Pred);
     std::swap(TrueVal, FalseVal);
   }
+
   if (!match(FalseVal, m_Zero()))
     return nullptr;
 
-  Value *A = ICI->getOperand(0);
-  Value *B = ICI->getOperand(1);
+  // ugt 0 is canonicalized to ne 0 and requires special handling
+  // (a != 0) ? a + -1 : 0 -> usub.sat(a, 1)
+  if (Pred == ICmpInst::ICMP_NE) {
+    if (match(B, m_Zero()) && match(TrueVal, m_Add(m_Specific(A), m_AllOnes())))
+      return Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A,
+                                           ConstantInt::get(A->getType(), 1));
+    return nullptr;
+  }
+
+  if (!ICmpInst::isUnsigned(Pred))
+    return nullptr;
+
   if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_ULT) {
     // (b < a) ? a - b : 0 -> (a > b) ? a - b : 0
     std::swap(A, B);

diff  --git a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
index 8556febd9233c..f1b763771ff58 100644
--- a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
+++ b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
@@ -523,9 +523,7 @@ define i8 @test_scalar_usub_combine(i8 %a) {
 ; Can simplify zero check followed by decrement
 define i8 @test_simplify_decrement(i8 %a) {
 ; CHECK-LABEL: @test_simplify_decrement(
-; CHECK-NEXT:    [[I:%.*]] = icmp eq i8 [[A:%.*]], 0
-; CHECK-NEXT:    [[I1:%.*]] = add i8 [[A]], -1
-; CHECK-NEXT:    [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]]
+; CHECK-NEXT:    [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 1)
 ; CHECK-NEXT:    ret i8 [[I2]]
 ;
   %i = icmp eq i8 %a, 0
@@ -540,8 +538,7 @@ define i8 @test_simplify_decrement_ne(i8 %a) {
 ; CHECK-LABEL: @test_simplify_decrement_ne(
 ; CHECK-NEXT:    [[I:%.*]] = icmp ne i8 [[A:%.*]], 0
 ; CHECK-NEXT:    call void @use.i1(i1 [[I]])
-; CHECK-NEXT:    [[I1:%.*]] = add i8 [[A]], -1
-; CHECK-NEXT:    [[I2:%.*]] = select i1 [[I]], i8 [[I1]], i8 0
+; CHECK-NEXT:    [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A]], i8 1)
 ; CHECK-NEXT:    ret i8 [[I2]]
 ;
   %i = icmp ne i8 %a, 0
@@ -553,9 +550,7 @@ define i8 @test_simplify_decrement_ne(i8 %a) {
 
 define <2 x i8> @test_simplify_decrement_vec(<2 x i8> %a) {
 ; CHECK-LABEL: @test_simplify_decrement_vec(
-; CHECK-NEXT:    [[I:%.*]] = icmp eq <2 x i8> [[A:%.*]], zeroinitializer
-; CHECK-NEXT:    [[I1:%.*]] = add <2 x i8> [[A]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[I2:%.*]] = select <2 x i1> [[I]], <2 x i8> zeroinitializer, <2 x i8> [[I1]]
+; CHECK-NEXT:    [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 1, i8 1>)
 ; CHECK-NEXT:    ret <2 x i8> [[I2]]
 ;
   %i = icmp eq <2 x i8> %a, <i8 0, i8 0>
@@ -566,9 +561,7 @@ define <2 x i8> @test_simplify_decrement_vec(<2 x i8> %a) {
 
 define <2 x i8> @test_simplify_decrement_vec_undef(<2 x i8> %a) {
 ; CHECK-LABEL: @test_simplify_decrement_vec_undef(
-; CHECK-NEXT:    [[I:%.*]] = icmp eq <2 x i8> [[A:%.*]], zeroinitializer
-; CHECK-NEXT:    [[I1:%.*]] = add <2 x i8> [[A]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[I2:%.*]] = select <2 x i1> [[I]], <2 x i8> <i8 0, i8 undef>, <2 x i8> [[I1]]
+; CHECK-NEXT:    [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 1, i8 1>)
 ; CHECK-NEXT:    ret <2 x i8> [[I2]]
 ;
   %i = icmp eq <2 x i8> %a, <i8 0, i8 0>

diff  --git a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
index 2b440c0e390aa..75b3c0d66a54d 100644
--- a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
+++ b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
@@ -265,9 +265,7 @@ define i32 @max_sub_ugt_c1(i32 %a) {
 
 define i32 @max_sub_ugt_c01(i32 %a) {
 ; CHECK-LABEL: @max_sub_ugt_c01(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
-; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -1
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 0, i32 [[SUB]]
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1)
 ; CHECK-NEXT:    ret i32 [[SEL]]
 ;
   %cmp = icmp ugt i32 %a, 0

diff  --git a/llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll b/llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll
index a97f085dc74a1..6b92b1f989ccc 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr44461-br-to-switch-rotate.ll
@@ -19,8 +19,7 @@ define i64 @test() {
 ; CHECK:       bb3.i.i:
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[ITER1_SROA_5_0]], 0
 ; CHECK-NEXT:    [[TMP3]] = zext i1 [[TMP2]] to i8
-; CHECK-NEXT:    [[_5_0_I_I_I_I:%.*]] = add i64 [[ITER1_SROA_5_0]], -1
-; CHECK-NEXT:    [[SPEC_SELECT]] = select i1 [[TMP2]], i64 0, i64 [[_5_0_I_I_I_I]]
+; CHECK-NEXT:    [[SPEC_SELECT]] = tail call i64 @llvm.usub.sat.i64(i64 [[ITER1_SROA_5_0]], i64 1)
 ; CHECK-NEXT:    [[TMP4]] = add i64 [[COUNT_1]], [[ITER1_SROA_5_0]]
 ; CHECK-NEXT:    br label [[BB10]]
 ; CHECK:       bb12:


        


More information about the llvm-commits mailing list