Skip to content

Commit 186155b

Browse files
committed
[InstCombine] Signed saturation patterns
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 llvm-svn: 375505
1 parent 40c4768 commit 186155b

File tree

3 files changed

+98
-124
lines changed

3 files changed

+98
-124
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
601601
Instruction *narrowMathIfNoOverflow(BinaryOperator &I);
602602
Instruction *narrowRotate(TruncInst &Trunc);
603603
Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
604+
Instruction *matchSAddSubSat(SelectInst &MinMax1);
604605

605606
/// Determine if a pair of casts can be replaced by a single cast.
606607
///

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,71 @@ static Instruction *moveAddAfterMinMax(SelectPatternFlavor SPF, Value *X,
20042004
return nullptr;
20052005
}
20062006

2007+
/// Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
2008+
Instruction *InstCombiner::matchSAddSubSat(SelectInst &MinMax1) {
2009+
Type *Ty = MinMax1.getType();
2010+
2011+
// We are looking for a tree of:
2012+
// max(INT_MIN, min(INT_MAX, add(sext(A), sext(B))))
2013+
// Where the min and max could be reversed
2014+
Instruction *MinMax2;
2015+
BinaryOperator *AddSub;
2016+
const APInt *MinValue, *MaxValue;
2017+
if (match(&MinMax1, m_SMin(m_Instruction(MinMax2), m_APInt(MaxValue)))) {
2018+
if (!match(MinMax2, m_SMax(m_BinOp(AddSub), m_APInt(MinValue))))
2019+
return nullptr;
2020+
} else if (match(&MinMax1,
2021+
m_SMax(m_Instruction(MinMax2), m_APInt(MinValue)))) {
2022+
if (!match(MinMax2, m_SMin(m_BinOp(AddSub), m_APInt(MaxValue))))
2023+
return nullptr;
2024+
} else
2025+
return nullptr;
2026+
2027+
// Check that the constants clamp a saturate, and that the new type would be
2028+
// sensible to convert to.
2029+
if (!(*MaxValue + 1).isPowerOf2() || -*MinValue != *MaxValue + 1)
2030+
return nullptr;
2031+
// In what bitwidth can this be treated as saturating arithmetics?
2032+
unsigned NewBitWidth = (*MaxValue + 1).logBase2() + 1;
2033+
// FIXME: This isn't quite right for vectors, but using the scalar type is a
2034+
// good first approximation for what should be done there.
2035+
if (!shouldChangeType(Ty->getScalarType()->getIntegerBitWidth(), NewBitWidth))
2036+
return nullptr;
2037+
2038+
// Also make sure that the number of uses is as expected. The "3"s are for the
2039+
// the two items of min/max (the compare and the select).
2040+
if (MinMax2->hasNUsesOrMore(3) || AddSub->hasNUsesOrMore(3))
2041+
return nullptr;
2042+
2043+
// Create the new type (which can be a vector type)
2044+
Type *NewTy = Ty->getWithNewBitWidth(NewBitWidth);
2045+
// Match the two extends from the add/sub
2046+
Value *A, *B;
2047+
if(!match(AddSub, m_BinOp(m_SExt(m_Value(A)), m_SExt(m_Value(B)))))
2048+
return nullptr;
2049+
// And check the incoming values are of a type smaller than or equal to the
2050+
// size of the saturation. Otherwise the higher bits can cause different
2051+
// results.
2052+
if (A->getType()->getScalarSizeInBits() > NewBitWidth ||
2053+
B->getType()->getScalarSizeInBits() > NewBitWidth)
2054+
return nullptr;
2055+
2056+
Intrinsic::ID IntrinsicID;
2057+
if (AddSub->getOpcode() == Instruction::Add)
2058+
IntrinsicID = Intrinsic::sadd_sat;
2059+
else if (AddSub->getOpcode() == Instruction::Sub)
2060+
IntrinsicID = Intrinsic::ssub_sat;
2061+
else
2062+
return nullptr;
2063+
2064+
// Finally create and return the sat intrinsic, truncated to the new type
2065+
Function *F = Intrinsic::getDeclaration(MinMax1.getModule(), IntrinsicID, NewTy);
2066+
Value *AT = Builder.CreateSExt(A, NewTy);
2067+
Value *BT = Builder.CreateSExt(B, NewTy);
2068+
Value *Sat = Builder.CreateCall(F, {AT, BT});
2069+
return CastInst::Create(Instruction::SExt, Sat, Ty);
2070+
}
2071+
20072072
/// Reduce a sequence of min/max with a common operand.
20082073
static Instruction *factorizeMinMaxTree(SelectPatternFlavor SPF, Value *LHS,
20092074
Value *RHS,
@@ -2430,6 +2495,8 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
24302495

24312496
if (Instruction *I = factorizeMinMaxTree(SPF, LHS, RHS, Builder))
24322497
return I;
2498+
if (Instruction *I = matchSAddSubSat(SI))
2499+
return I;
24332500
}
24342501
}
24352502

llvm/test/Transforms/InstCombine/sadd_sat.ll

Lines changed: 30 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,8 @@ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
66
define i32 @sadd_sat32(i32 %a, i32 %b) {
77
; CHECK-LABEL: @sadd_sat32(
88
; CHECK-NEXT: entry:
9-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
10-
; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
11-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
12-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
13-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
14-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
15-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
16-
; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
17-
; CHECK-NEXT: ret i32 [[CONV7]]
9+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
10+
; CHECK-NEXT: ret i32 [[TMP0]]
1811
;
1912
entry:
2013
%conv = sext i32 %a to i64
@@ -31,15 +24,8 @@ entry:
3124
define i32 @ssub_sat32(i32 %a, i32 %b) {
3225
; CHECK-LABEL: @ssub_sat32(
3326
; CHECK-NEXT: entry:
34-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
35-
; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
36-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[CONV]], [[CONV1]]
37-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[SUB]], 2147483647
38-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[SUB]], i64 2147483647
39-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
40-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
41-
; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
42-
; CHECK-NEXT: ret i32 [[CONV7]]
27+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
28+
; CHECK-NEXT: ret i32 [[TMP0]]
4329
;
4430
entry:
4531
%conv = sext i32 %a to i64
@@ -81,15 +67,8 @@ entry:
8167
define signext i16 @sadd_sat16(i16 signext %a, i16 signext %b) {
8268
; CHECK-LABEL: @sadd_sat16(
8369
; CHECK-NEXT: entry:
84-
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
85-
; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
86-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
87-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 32767
88-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 32767
89-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
90-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
91-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
92-
; CHECK-NEXT: ret i16 [[CONV9]]
70+
; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
71+
; CHECK-NEXT: ret i16 [[TMP0]]
9372
;
9473
entry:
9574
%conv = sext i16 %a to i32
@@ -106,15 +85,8 @@ entry:
10685
define signext i16 @ssub_sat16(i16 signext %a, i16 signext %b) {
10786
; CHECK-LABEL: @ssub_sat16(
10887
; CHECK-NEXT: entry:
109-
; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
110-
; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
111-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
112-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 32767
113-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 32767
114-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
115-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
116-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
117-
; CHECK-NEXT: ret i16 [[CONV9]]
88+
; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
89+
; CHECK-NEXT: ret i16 [[TMP0]]
11890
;
11991
entry:
12092
%conv = sext i16 %a to i32
@@ -131,15 +103,8 @@ entry:
131103
define signext i8 @sadd_sat8(i8 signext %a, i8 signext %b) {
132104
; CHECK-LABEL: @sadd_sat8(
133105
; CHECK-NEXT: entry:
134-
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
135-
; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
136-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
137-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 127
138-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 127
139-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
140-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
141-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
142-
; CHECK-NEXT: ret i8 [[CONV9]]
106+
; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
107+
; CHECK-NEXT: ret i8 [[TMP0]]
143108
;
144109
entry:
145110
%conv = sext i8 %a to i32
@@ -156,15 +121,8 @@ entry:
156121
define signext i8 @ssub_sat8(i8 signext %a, i8 signext %b) {
157122
; CHECK-LABEL: @ssub_sat8(
158123
; CHECK-NEXT: entry:
159-
; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
160-
; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
161-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
162-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 127
163-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 127
164-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
165-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
166-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
167-
; CHECK-NEXT: ret i8 [[CONV9]]
124+
; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
125+
; CHECK-NEXT: ret i8 [[TMP0]]
168126
;
169127
entry:
170128
%conv = sext i8 %a to i32
@@ -181,15 +139,8 @@ entry:
181139
define signext i64 @sadd_sat64(i64 signext %a, i64 signext %b) {
182140
; CHECK-LABEL: @sadd_sat64(
183141
; CHECK-NEXT: entry:
184-
; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
185-
; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
186-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i65 [[CONV1]], [[CONV]]
187-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[ADD]], 9223372036854775807
188-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[ADD]], i65 9223372036854775807
189-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
190-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
191-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
192-
; CHECK-NEXT: ret i64 [[CONV9]]
142+
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[B:%.*]], i64 [[A:%.*]])
143+
; CHECK-NEXT: ret i64 [[TMP0]]
193144
;
194145
entry:
195146
%conv = sext i64 %a to i65
@@ -206,15 +157,8 @@ entry:
206157
define signext i64 @ssub_sat64(i64 signext %a, i64 signext %b) {
207158
; CHECK-LABEL: @ssub_sat64(
208159
; CHECK-NEXT: entry:
209-
; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
210-
; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
211-
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i65 [[CONV]], [[CONV1]]
212-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[SUB]], 9223372036854775807
213-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[SUB]], i65 9223372036854775807
214-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
215-
; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
216-
; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
217-
; CHECK-NEXT: ret i64 [[CONV9]]
160+
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.ssub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
161+
; CHECK-NEXT: ret i64 [[TMP0]]
218162
;
219163
entry:
220164
%conv = sext i64 %a to i65
@@ -281,15 +225,8 @@ entry:
281225
define <4 x i32> @sadd_satv4i32(<4 x i32> %a, <4 x i32> %b) {
282226
; CHECK-LABEL: @sadd_satv4i32(
283227
; CHECK-NEXT: entry:
284-
; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
285-
; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
286-
; CHECK-NEXT: [[ADD:%.*]] = add nsw <4 x i64> [[CONV1]], [[CONV]]
287-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
288-
; 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>
289-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
290-
; 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>
291-
; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
292-
; CHECK-NEXT: ret <4 x i32> [[CONV7]]
228+
; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
229+
; CHECK-NEXT: ret <4 x i32> [[TMP0]]
293230
;
294231
entry:
295232
%conv = sext <4 x i32> %a to <4 x i64>
@@ -306,15 +243,8 @@ entry:
306243
define <4 x i32> @ssub_satv4i32(<4 x i32> %a, <4 x i32> %b) {
307244
; CHECK-LABEL: @ssub_satv4i32(
308245
; CHECK-NEXT: entry:
309-
; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
310-
; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
311-
; CHECK-NEXT: [[ADD:%.*]] = sub nsw <4 x i64> [[CONV1]], [[CONV]]
312-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
313-
; 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>
314-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
315-
; 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>
316-
; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
317-
; CHECK-NEXT: ret <4 x i32> [[CONV7]]
246+
; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
247+
; CHECK-NEXT: ret <4 x i32> [[TMP0]]
318248
;
319249
entry:
320250
%conv = sext <4 x i32> %a to <4 x i64>
@@ -370,16 +300,10 @@ entry:
370300
define i32 @sadd_sat32_extrause_1(i32 %a, i32 %b) {
371301
; CHECK-LABEL: @sadd_sat32_extrause_1(
372302
; CHECK-NEXT: entry:
373-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
374-
; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
375-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
376-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
377-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
378-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
379-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
380-
; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
303+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
304+
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
381305
; CHECK-NEXT: call void @use64(i64 [[SPEC_STORE_SELECT8]])
382-
; CHECK-NEXT: ret i32 [[CONV7]]
306+
; CHECK-NEXT: ret i32 [[TMP0]]
383307
;
384308
entry:
385309
%conv = sext i32 %a to i64
@@ -476,15 +400,9 @@ entry:
476400
define i32 @sadd_sat32_ext16(i32 %a, i16 %b) {
477401
; CHECK-LABEL: @sadd_sat32_ext16(
478402
; CHECK-NEXT: entry:
479-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
480-
; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i64
481-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
482-
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
483-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
484-
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
485-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
486-
; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
487-
; CHECK-NEXT: ret i32 [[CONV7]]
403+
; CHECK-NEXT: [[TMP0:%.*]] = sext i16 [[B:%.*]] to i32
404+
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 [[A:%.*]])
405+
; CHECK-NEXT: ret i32 [[TMP1]]
488406
;
489407
entry:
490408
%conv = sext i32 %a to i64
@@ -549,15 +467,8 @@ entry:
549467
define i32 @sadd_sat32_maxmin(i32 %a, i32 %b) {
550468
; CHECK-LABEL: @sadd_sat32_maxmin(
551469
; CHECK-NEXT: entry:
552-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
553-
; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
554-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
555-
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
556-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
557-
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
558-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
559-
; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
560-
; CHECK-NEXT: ret i32 [[CONV7]]
470+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
471+
; CHECK-NEXT: ret i32 [[TMP0]]
561472
;
562473
entry:
563474
%conv = sext i32 %a to i64
@@ -574,13 +485,8 @@ entry:
574485
define i64 @sadd_sat32_notrunc(i32 %a, i32 %b) {
575486
; CHECK-LABEL: @sadd_sat32_notrunc(
576487
; CHECK-NEXT: entry:
577-
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
578-
; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
579-
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
580-
; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
581-
; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
582-
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
583-
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
488+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
489+
; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
584490
; CHECK-NEXT: ret i64 [[SPEC_STORE_SELECT8]]
585491
;
586492
entry:

0 commit comments

Comments
 (0)