[llvm] r347772 - [InstCombine] Canonicalize ssub.sat to sadd.sat

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 28 08:37:10 PST 2018


Author: nikic
Date: Wed Nov 28 08:37:09 2018
New Revision: 347772

URL: http://llvm.org/viewvc/llvm-project?rev=347772&view=rev
Log:
[InstCombine] Canonicalize ssub.sat to sadd.sat

Canonicalize ssub.sat(X, C) to ssub.sat(X, -C) if C is constant and
not signed minimum. This will help further optimizations to apply.

This change is part of https://reviews.llvm.org/D54534.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=347772&r1=347771&r2=347772&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Wed Nov 28 08:37:09 2018
@@ -2102,6 +2102,17 @@ Instruction *InstCombiner::visitCallInst
         return BinaryOperator::CreateNSWSub(Arg0, Arg1);
       break;
     }
+
+    // ssub.sat(X, C) -> sadd.sat(X, -C) if C != MIN
+    // TODO: Support non-splat C.
+    const APInt *C;
+    if (IID == Intrinsic::ssub_sat && match(Arg1, m_APInt(C)) &&
+        !C->isMinSignedValue()) {
+      Value *NegVal = ConstantInt::get(II->getType(), -*C);
+      return replaceInstUsesWith(
+          *II, Builder.CreateBinaryIntrinsic(
+              Intrinsic::sadd_sat, Arg0, NegVal));
+    }
     break;
   }
 

Modified: llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll?rev=347772&r1=347771&r2=347772&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll Wed Nov 28 08:37:09 2018
@@ -331,8 +331,8 @@ define i8 @test_scalar_usub_canonical(i8
 ; Canonicalize ssub to sadd.
 define i8 @test_scalar_ssub_canonical(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_canonical(
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10)
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
   %r = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10)
   ret i8 %r
@@ -340,8 +340,8 @@ define i8 @test_scalar_ssub_canonical(i8
 
 define <2 x i8> @test_vector_ssub_canonical(<2 x i8> %a) {
 ; CHECK-LABEL: @test_vector_ssub_canonical(
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 10>)
-; CHECK-NEXT:    ret <2 x i8> [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -10, i8 -10>)
+; CHECK-NEXT:    ret <2 x i8> [[TMP1]]
 ;
   %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>)
   ret <2 x i8> %r
@@ -437,9 +437,9 @@ define <2 x i8> @test_vector_usub_overfl
 ; Can combine ssubs if sign matches.
 define i8 @test_scalar_ssub_both_positive(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_both_positive(
-; CHECK-NEXT:    [[Z1:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT:    [[Z2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[Z1]], i8 20)
-; CHECK-NEXT:    ret i8 [[Z2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10)
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[TMP1]], i8 -20)
+; CHECK-NEXT:    ret i8 [[TMP2]]
 ;
   %z1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10)
   %z2 = call i8 @llvm.ssub.sat.i8(i8 %z1, i8 20)
@@ -448,9 +448,9 @@ define i8 @test_scalar_ssub_both_positiv
 
 define <2 x i8> @test_vector_ssub_both_positive(<2 x i8> %a) {
 ; CHECK-LABEL: @test_vector_ssub_both_positive(
-; CHECK-NEXT:    [[Z1:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 10>)
-; CHECK-NEXT:    [[Z2:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[Z1]], <2 x i8> <i8 20, i8 20>)
-; CHECK-NEXT:    ret <2 x i8> [[Z2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -10, i8 -10>)
+; CHECK-NEXT:    [[TMP2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[TMP1]], <2 x i8> <i8 -20, i8 -20>)
+; CHECK-NEXT:    ret <2 x i8> [[TMP2]]
 ;
   %z1 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>)
   %z2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %z1, <2 x i8> <i8 20, i8 20>)
@@ -459,9 +459,9 @@ define <2 x i8> @test_vector_ssub_both_p
 
 define i8 @test_scalar_ssub_both_negative(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_both_negative(
-; CHECK-NEXT:    [[U1:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 -10)
-; CHECK-NEXT:    [[U2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[U1]], i8 -20)
-; CHECK-NEXT:    ret i8 [[U2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10)
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[TMP1]], i8 20)
+; CHECK-NEXT:    ret i8 [[TMP2]]
 ;
   %u1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -10)
   %u2 = call i8 @llvm.ssub.sat.i8(i8 %u1, i8 -20)
@@ -470,9 +470,9 @@ define i8 @test_scalar_ssub_both_negativ
 
 define <2 x i8> @test_vector_ssub_both_negative(<2 x i8> %a) {
 ; CHECK-LABEL: @test_vector_ssub_both_negative(
-; CHECK-NEXT:    [[U1:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -10, i8 -10>)
-; CHECK-NEXT:    [[U2:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[U1]], <2 x i8> <i8 -20, i8 -20>)
-; CHECK-NEXT:    ret <2 x i8> [[U2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 10>)
+; CHECK-NEXT:    [[TMP2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[TMP1]], <2 x i8> <i8 20, i8 20>)
+; CHECK-NEXT:    ret <2 x i8> [[TMP2]]
 ;
   %u1 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 -10, i8 -10>)
   %u2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %u1, <2 x i8> <i8 -20, i8 -20>)
@@ -482,9 +482,9 @@ define <2 x i8> @test_vector_ssub_both_n
 ; Can't combine ssubs if constants have different sign.
 define i8 @test_scalar_ssub_different_sign(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_different_sign(
-; CHECK-NEXT:    [[V1:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT:    [[V2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[V1]], i8 -20)
-; CHECK-NEXT:    ret i8 [[V2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10)
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[TMP1]], i8 20)
+; CHECK-NEXT:    ret i8 [[TMP2]]
 ;
   %v1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10)
   %v2 = call i8 @llvm.ssub.sat.i8(i8 %v1, i8 -20)
@@ -495,8 +495,8 @@ define i8 @test_scalar_ssub_different_si
 define i8 @test_scalar_sadd_ssub(i8 %a) {
 ; CHECK-LABEL: @test_scalar_sadd_ssub(
 ; CHECK-NEXT:    [[V1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT:    [[V2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[V1]], i8 -20)
-; CHECK-NEXT:    ret i8 [[V2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[V1]], i8 20)
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
   %v1 = call i8 @llvm.sadd.sat.i8(i8 10, i8 %a)
   %v2 = call i8 @llvm.ssub.sat.i8(i8 %v1, i8 -20)
@@ -506,8 +506,8 @@ define i8 @test_scalar_sadd_ssub(i8 %a)
 define <2 x i8> @test_vector_sadd_ssub(<2 x i8> %a) {
 ; CHECK-LABEL: @test_vector_sadd_ssub(
 ; CHECK-NEXT:    [[V1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -10, i8 -10>)
-; CHECK-NEXT:    [[V2:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[V1]], <2 x i8> <i8 20, i8 20>)
-; CHECK-NEXT:    ret <2 x i8> [[V2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[V1]], <2 x i8> <i8 -20, i8 -20>)
+; CHECK-NEXT:    ret <2 x i8> [[TMP1]]
 ;
   %v1 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 -10, i8 -10>, <2 x i8> %a)
   %v2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %v1, <2 x i8> <i8 20, i8 20>)
@@ -517,9 +517,9 @@ define <2 x i8> @test_vector_sadd_ssub(<
 ; Can't combine ssubs if they overflow.
 define i8 @test_scalar_ssub_overflow(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_overflow(
-; CHECK-NEXT:    [[W1:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 100)
-; CHECK-NEXT:    [[W2:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[W1]], i8 100)
-; CHECK-NEXT:    ret i8 [[W2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -100)
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[TMP1]], i8 -100)
+; CHECK-NEXT:    ret i8 [[TMP2]]
 ;
   %w1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 100)
   %w2 = call i8 @llvm.ssub.sat.i8(i8 %w1, i8 100)
@@ -641,8 +641,8 @@ define <2 x i8> @test_vector_ssub_nneg_n
 define i8 @test_scalar_ssub_neg_nneg(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_neg_nneg(
 ; CHECK-NEXT:    [[A_NEG:%.*]] = or i8 [[A:%.*]], -128
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A_NEG]], i8 10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A_NEG]], i8 -10)
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
   %a_neg = or i8 %a, -128
   %r = call i8 @llvm.ssub.sat.i8(i8 %a_neg, i8 10)




More information about the llvm-commits mailing list