aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Green <david.green@arm.com>2019-10-22 15:39:47 +0000
committerDavid Green <david.green@arm.com>2019-10-22 15:39:47 +0000
commit2c4ca6832fa6b306ee6a7010bfb80a3f2596f824 (patch)
treeb978d8fba715be02c4f33013cc94e12267e2c86c
parent6e8533b05630a1e06d39a61270dcbf6d0662b3b5 (diff)
downloadllvm-upstream-master.tar.gz
[InstCombine] Signed saturation patternsupstream-master
This adds an instcombine matcher for code that attempts to perform signed saturating arithmetic by casting to a higher type. Unsigned cases are already matched, this adds extra matches for the more complex signed cases, which involves matching the min(max(add a b)) nodes with proper extends to ensure legality. Differential Revision: https://reviews.llvm.org/D68651 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375505 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/InstCombine/InstCombineInternal.h1
-rw-r--r--lib/Transforms/InstCombine/InstCombineSelect.cpp67
-rw-r--r--test/Transforms/InstCombine/sadd_sat.ll154
3 files changed, 98 insertions, 124 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineInternal.h b/lib/Transforms/InstCombine/InstCombineInternal.h
index 4917a355cad..1dbc06d92e7 100644
--- a/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -601,6 +601,7 @@ private:
Instruction *narrowMathIfNoOverflow(BinaryOperator &I);
Instruction *narrowRotate(TruncInst &Trunc);
Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
+ Instruction *matchSAddSubSat(SelectInst &MinMax1);
/// Determine if a pair of casts can be replaced by a single cast.
///
diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 55ac8202130..9fc871e49b3 100644
--- a/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2004,6 +2004,71 @@ static Instruction *moveAddAfterMinMax(SelectPatternFlavor SPF, Value *X,
return nullptr;
}
+/// Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
+Instruction *InstCombiner::matchSAddSubSat(SelectInst &MinMax1) {
+ Type *Ty = MinMax1.getType();
+
+ // We are looking for a tree of:
+ // max(INT_MIN, min(INT_MAX, add(sext(A), sext(B))))
+ // Where the min and max could be reversed
+ Instruction *MinMax2;
+ BinaryOperator *AddSub;
+ const APInt *MinValue, *MaxValue;
+ if (match(&MinMax1, m_SMin(m_Instruction(MinMax2), m_APInt(MaxValue)))) {
+ if (!match(MinMax2, m_SMax(m_BinOp(AddSub), m_APInt(MinValue))))
+ return nullptr;
+ } else if (match(&MinMax1,
+ m_SMax(m_Instruction(MinMax2), m_APInt(MinValue)))) {
+ if (!match(MinMax2, m_SMin(m_BinOp(AddSub), m_APInt(MaxValue))))
+ return nullptr;
+ } else
+ return nullptr;
+
+ // Check that the constants clamp a saturate, and that the new type would be
+ // sensible to convert to.
+ if (!(*MaxValue + 1).isPowerOf2() || -*MinValue != *MaxValue + 1)
+ return nullptr;
+ // In what bitwidth can this be treated as saturating arithmetics?
+ unsigned NewBitWidth = (*MaxValue + 1).logBase2() + 1;
+ // FIXME: This isn't quite right for vectors, but using the scalar type is a
+ // good first approximation for what should be done there.
+ if (!shouldChangeType(Ty->getScalarType()->getIntegerBitWidth(), NewBitWidth))
+ return nullptr;
+
+ // Also make sure that the number of uses is as expected. The "3"s are for the
+ // the two items of min/max (the compare and the select).
+ if (MinMax2->hasNUsesOrMore(3) || AddSub->hasNUsesOrMore(3))
+ return nullptr;
+
+ // Create the new type (which can be a vector type)
+ Type *NewTy = Ty->getWithNewBitWidth(NewBitWidth);
+ // Match the two extends from the add/sub
+ Value *A, *B;
+ if(!match(AddSub, m_BinOp(m_SExt(m_Value(A)), m_SExt(m_Value(B)))))
+ return nullptr;
+ // And check the incoming values are of a type smaller than or equal to the
+ // size of the saturation. Otherwise the higher bits can cause different
+ // results.
+ if (A->getType()->getScalarSizeInBits() > NewBitWidth ||
+ B->getType()->getScalarSizeInBits() > NewBitWidth)
+ return nullptr;
+
+ Intrinsic::ID IntrinsicID;
+ if (AddSub->getOpcode() == Instruction::Add)
+ IntrinsicID = Intrinsic::sadd_sat;
+ else if (AddSub->getOpcode() == Instruction::Sub)
+ IntrinsicID = Intrinsic::ssub_sat;
+ else
+ return nullptr;
+
+ // Finally create and return the sat intrinsic, truncated to the new type
+ Function *F = Intrinsic::getDeclaration(MinMax1.getModule(), IntrinsicID, NewTy);
+ Value *AT = Builder.CreateSExt(A, NewTy);
+ Value *BT = Builder.CreateSExt(B, NewTy);
+ Value *Sat = Builder.CreateCall(F, {AT, BT});
+ return CastInst::Create(Instruction::SExt, Sat, Ty);
+}
+
/// Reduce a sequence of min/max with a common operand.
static Instruction *factorizeMinMaxTree(SelectPatternFlavor SPF, Value *LHS,
Value *RHS,
@@ -2430,6 +2495,8 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
if (Instruction *I = factorizeMinMaxTree(SPF, LHS, RHS, Builder))
return I;
+ if (Instruction *I = matchSAddSubSat(SI))
+ return I;
}
}
diff --git a/test/Transforms/InstCombine/sadd_sat.ll b/test/Transforms/InstCombine/sadd_sat.ll
index c3aba403737..04dd4f5c038 100644
--- a/test/Transforms/InstCombine/sadd_sat.ll
+++ b/test/Transforms/InstCombine/sadd_sat.ll
@@ -6,15 +6,8 @@ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
define i32 @sadd_sat32(i32 %a, i32 %b) {
; CHECK-LABEL: @sadd_sat32(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
-; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
-; CHECK-NEXT: ret i32 [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%conv = sext i32 %a to i64
@@ -31,15 +24,8 @@ entry:
define i32 @ssub_sat32(i32 %a, i32 %b) {
; CHECK-LABEL: @ssub_sat32(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[CONV]], [[CONV1]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[SUB]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[SUB]], i64 2147483647
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
-; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
-; CHECK-NEXT: ret i32 [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
+; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%conv = sext i32 %a to i64
@@ -81,15 +67,8 @@ entry:
define signext i16 @sadd_sat16(i16 signext %a, i16 signext %b) {
; CHECK-LABEL: @sadd_sat16(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
-; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 32767
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 32767
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
-; CHECK-NEXT: ret i16 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
+; CHECK-NEXT: ret i16 [[TMP0]]
;
entry:
%conv = sext i16 %a to i32
@@ -106,15 +85,8 @@ entry:
define signext i16 @ssub_sat16(i16 signext %a, i16 signext %b) {
; CHECK-LABEL: @ssub_sat16(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
-; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 32767
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 32767
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
-; CHECK-NEXT: ret i16 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
+; CHECK-NEXT: ret i16 [[TMP0]]
;
entry:
%conv = sext i16 %a to i32
@@ -131,15 +103,8 @@ entry:
define signext i8 @sadd_sat8(i8 signext %a, i8 signext %b) {
; CHECK-LABEL: @sadd_sat8(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 127
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 127
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
-; CHECK-NEXT: ret i8 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
+; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
%conv = sext i8 %a to i32
@@ -156,15 +121,8 @@ entry:
define signext i8 @ssub_sat8(i8 signext %a, i8 signext %b) {
; CHECK-LABEL: @ssub_sat8(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
-; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 127
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 127
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
-; CHECK-NEXT: ret i8 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
+; CHECK-NEXT: ret i8 [[TMP0]]
;
entry:
%conv = sext i8 %a to i32
@@ -181,15 +139,8 @@ entry:
define signext i64 @sadd_sat64(i64 signext %a, i64 signext %b) {
; CHECK-LABEL: @sadd_sat64(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
-; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i65 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[ADD]], 9223372036854775807
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[ADD]], i65 9223372036854775807
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
-; CHECK-NEXT: ret i64 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[B:%.*]], i64 [[A:%.*]])
+; CHECK-NEXT: ret i64 [[TMP0]]
;
entry:
%conv = sext i64 %a to i65
@@ -206,15 +157,8 @@ entry:
define signext i64 @ssub_sat64(i64 signext %a, i64 signext %b) {
; CHECK-LABEL: @ssub_sat64(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
-; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
-; CHECK-NEXT: [[SUB:%.*]] = sub nsw i65 [[CONV]], [[CONV1]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[SUB]], 9223372036854775807
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[SUB]], i65 9223372036854775807
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
-; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
-; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
-; CHECK-NEXT: ret i64 [[CONV9]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.ssub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
+; CHECK-NEXT: ret i64 [[TMP0]]
;
entry:
%conv = sext i64 %a to i65
@@ -281,15 +225,8 @@ entry:
define <4 x i32> @sadd_satv4i32(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @sadd_satv4i32(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
-; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
-; CHECK-NEXT: [[ADD:%.*]] = add nsw <4 x i64> [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
-; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
-; CHECK-NEXT: ret <4 x i32> [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
+; CHECK-NEXT: ret <4 x i32> [[TMP0]]
;
entry:
%conv = sext <4 x i32> %a to <4 x i64>
@@ -306,15 +243,8 @@ entry:
define <4 x i32> @ssub_satv4i32(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @ssub_satv4i32(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
-; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
-; CHECK-NEXT: [[ADD:%.*]] = sub nsw <4 x i64> [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
-; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
-; CHECK-NEXT: ret <4 x i32> [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
+; CHECK-NEXT: ret <4 x i32> [[TMP0]]
;
entry:
%conv = sext <4 x i32> %a to <4 x i64>
@@ -370,16 +300,10 @@ entry:
define i32 @sadd_sat32_extrause_1(i32 %a, i32 %b) {
; CHECK-LABEL: @sadd_sat32_extrause_1(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
-; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
; CHECK-NEXT: call void @use64(i64 [[SPEC_STORE_SELECT8]])
-; CHECK-NEXT: ret i32 [[CONV7]]
+; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%conv = sext i32 %a to i64
@@ -476,15 +400,9 @@ entry:
define i32 @sadd_sat32_ext16(i32 %a, i16 %b) {
; CHECK-LABEL: @sadd_sat32_ext16(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
-; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
-; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
-; CHECK-NEXT: ret i32 [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = sext i16 [[B:%.*]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 [[A:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
;
entry:
%conv = sext i32 %a to i64
@@ -549,15 +467,8 @@ entry:
define i32 @sadd_sat32_maxmin(i32 %a, i32 %b) {
; CHECK-LABEL: @sadd_sat32_maxmin(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
-; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
-; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
-; CHECK-NEXT: ret i32 [[CONV7]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%conv = sext i32 %a to i64
@@ -574,13 +485,8 @@ entry:
define i64 @sadd_sat32_notrunc(i32 %a, i32 %b) {
; CHECK-LABEL: @sadd_sat32_notrunc(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
-; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
-; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
-; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
-; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
+; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
; CHECK-NEXT: ret i64 [[SPEC_STORE_SELECT8]]
;
entry: