[llvm] r362006 - [InstCombine] Optimize always overflowing signed saturating add/sub

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed May 29 11:37:13 PDT 2019


Author: nikic
Date: Wed May 29 11:37:13 2019
New Revision: 362006

URL: http://llvm.org/viewvc/llvm-project?rev=362006&view=rev
Log:
[InstCombine] Optimize always overflowing signed saturating add/sub

Based on the overflow direction information added in D62463, we can
now fold always overflowing signed saturating add/sub to signed min/max.

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

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=362006&r1=362005&r2=362006&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Wed May 29 11:37:13 2019
@@ -13,6 +13,7 @@
 #include "InstCombineInternal.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
@@ -2053,6 +2054,7 @@ Instruction *InstCombiner::visitCallInst
   case Intrinsic::usub_sat:
   case Intrinsic::ssub_sat: {
     SaturatingInst *SI = cast<SaturatingInst>(II);
+    Type *Ty = SI->getType();
     Value *Arg0 = SI->getLHS();
     Value *Arg1 = SI->getRHS();
 
@@ -2067,14 +2069,16 @@ Instruction *InstCombiner::visitCallInst
           return BinaryOperator::CreateNSW(SI->getBinaryOp(), Arg0, Arg1);
         else
           return BinaryOperator::CreateNUW(SI->getBinaryOp(), Arg0, Arg1);
-      case OverflowResult::AlwaysOverflowsLow:
-        if (SI->isSigned()) break; // TODO: Support signed.
-        return replaceInstUsesWith(*SI,
-                                   ConstantInt::getNullValue(II->getType()));
-      case OverflowResult::AlwaysOverflowsHigh:
-        if (SI->isSigned()) break; // TODO: Support signed.
-        return replaceInstUsesWith(*SI,
-                                   ConstantInt::getAllOnesValue(II->getType()));
+      case OverflowResult::AlwaysOverflowsLow: {
+        unsigned BitWidth = Ty->getScalarSizeInBits();
+        APInt Min = APSInt::getMinValue(BitWidth, !SI->isSigned());
+        return replaceInstUsesWith(*SI, ConstantInt::get(Ty, Min));
+      }
+      case OverflowResult::AlwaysOverflowsHigh: {
+        unsigned BitWidth = Ty->getScalarSizeInBits();
+        APInt Max = APSInt::getMaxValue(BitWidth, !SI->isSigned());
+        return replaceInstUsesWith(*SI, ConstantInt::get(Ty, Max));
+      }
     }
 
     // ssub.sat(X, C) -> sadd.sat(X, -C) if C != MIN

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=362006&r1=362005&r2=362006&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/saturating-add-sub.ll Wed May 29 11:37:13 2019
@@ -341,10 +341,7 @@ define <2 x i8> @test_vector_sadd_neg_ne
 
 define i8 @test_scalar_sadd_always_overflows_low(i8 %a) {
 ; CHECK-LABEL: @test_scalar_sadd_always_overflows_low(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[A:%.*]], -120
-; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP]], i8 [[A]], i8 -120
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[MIN]], i8 -10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 -128
 ;
   %cmp = icmp slt i8 %a, -120
   %min = select i1 %cmp, i8 %a, i8 -120
@@ -354,10 +351,7 @@ define i8 @test_scalar_sadd_always_overf
 
 define i8 @test_scalar_sadd_always_overflows_high(i8 %a) {
 ; CHECK-LABEL: @test_scalar_sadd_always_overflows_high(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], 120
-; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP]], i8 [[A]], i8 120
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[MAX]], i8 10)
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 127
 ;
   %cmp = icmp sgt i8 %a, 120
   %max = select i1 %cmp, i8 %a, i8 120
@@ -829,10 +823,7 @@ define <2 x i8> @test_vector_ssub_neg_nn
 
 define i8 @test_scalar_ssub_always_overflows_low(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_always_overflows_low(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], 120
-; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[CMP]], i8 [[A]], i8 120
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 -10, i8 [[MAX]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 -128
 ;
   %cmp = icmp sgt i8 %a, 120
   %max = select i1 %cmp, i8 %a, i8 120
@@ -842,10 +833,7 @@ define i8 @test_scalar_ssub_always_overf
 
 define i8 @test_scalar_ssub_always_overflows_high(i8 %a) {
 ; CHECK-LABEL: @test_scalar_ssub_always_overflows_high(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[A:%.*]], -120
-; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[CMP]], i8 [[A]], i8 -120
-; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 10, i8 [[MIN]])
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 127
 ;
   %cmp = icmp slt i8 %a, -120
   %min = select i1 %cmp, i8 %a, i8 -120




More information about the llvm-commits mailing list