llvm.org GIT mirror llvm / master
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375505 91177308-0d34-0410-b5e6-96231b3b80d8 David Green 9 months ago
3 changed file(s) with 98 addition(s) and 124 deletion(s). Raw diff Collapse all Expand all
600600 Instruction *narrowMathIfNoOverflow(BinaryOperator &I);
601601 Instruction *narrowRotate(TruncInst &Trunc);
602602 Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
603 Instruction *matchSAddSubSat(SelectInst &MinMax1);
603604
604605 /// Determine if a pair of casts can be replaced by a single cast.
605606 ///
20032003 return nullptr;
20042004 }
20052005
2006 /// Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
2007 Instruction *InstCombiner::matchSAddSubSat(SelectInst &MinMax1) {
2008 Type *Ty = MinMax1.getType();
2009
2010 // We are looking for a tree of:
2011 // max(INT_MIN, min(INT_MAX, add(sext(A), sext(B))))
2012 // Where the min and max could be reversed
2013 Instruction *MinMax2;
2014 BinaryOperator *AddSub;
2015 const APInt *MinValue, *MaxValue;
2016 if (match(&MinMax1, m_SMin(m_Instruction(MinMax2), m_APInt(MaxValue)))) {
2017 if (!match(MinMax2, m_SMax(m_BinOp(AddSub), m_APInt(MinValue))))
2018 return nullptr;
2019 } else if (match(&MinMax1,
2020 m_SMax(m_Instruction(MinMax2), m_APInt(MinValue)))) {
2021 if (!match(MinMax2, m_SMin(m_BinOp(AddSub), m_APInt(MaxValue))))
2022 return nullptr;
2023 } else
2024 return nullptr;
2025
2026 // Check that the constants clamp a saturate, and that the new type would be
2027 // sensible to convert to.
2028 if (!(*MaxValue + 1).isPowerOf2() || -*MinValue != *MaxValue + 1)
2029 return nullptr;
2030 // In what bitwidth can this be treated as saturating arithmetics?
2031 unsigned NewBitWidth = (*MaxValue + 1).logBase2() + 1;
2032 // FIXME: This isn't quite right for vectors, but using the scalar type is a
2033 // good first approximation for what should be done there.
2034 if (!shouldChangeType(Ty->getScalarType()->getIntegerBitWidth(), NewBitWidth))
2035 return nullptr;
2036
2037 // Also make sure that the number of uses is as expected. The "3"s are for the
2038 // the two items of min/max (the compare and the select).
2039 if (MinMax2->hasNUsesOrMore(3) || AddSub->hasNUsesOrMore(3))
2040 return nullptr;
2041
2042 // Create the new type (which can be a vector type)
2043 Type *NewTy = Ty->getWithNewBitWidth(NewBitWidth);
2044 // Match the two extends from the add/sub
2045 Value *A, *B;
2046 if(!match(AddSub, m_BinOp(m_SExt(m_Value(A)), m_SExt(m_Value(B)))))
2047 return nullptr;
2048 // And check the incoming values are of a type smaller than or equal to the
2049 // size of the saturation. Otherwise the higher bits can cause different
2050 // results.
2051 if (A->getType()->getScalarSizeInBits() > NewBitWidth ||
2052 B->getType()->getScalarSizeInBits() > NewBitWidth)
2053 return nullptr;
2054
2055 Intrinsic::ID IntrinsicID;
2056 if (AddSub->getOpcode() == Instruction::Add)
2057 IntrinsicID = Intrinsic::sadd_sat;
2058 else if (AddSub->getOpcode() == Instruction::Sub)
2059 IntrinsicID = Intrinsic::ssub_sat;
2060 else
2061 return nullptr;
2062
2063 // Finally create and return the sat intrinsic, truncated to the new type
2064 Function *F = Intrinsic::getDeclaration(MinMax1.getModule(), IntrinsicID, NewTy);
2065 Value *AT = Builder.CreateSExt(A, NewTy);
2066 Value *BT = Builder.CreateSExt(B, NewTy);
2067 Value *Sat = Builder.CreateCall(F, {AT, BT});
2068 return CastInst::Create(Instruction::SExt, Sat, Ty);
2069 }
2070
20062071 /// Reduce a sequence of min/max with a common operand.
20072072 static Instruction *factorizeMinMaxTree(SelectPatternFlavor SPF, Value *LHS,
20082073 Value *RHS,
24292494
24302495 if (Instruction *I = factorizeMinMaxTree(SPF, LHS, RHS, Builder))
24312496 return I;
2497 if (Instruction *I = matchSAddSubSat(SI))
2498 return I;
24322499 }
24332500 }
24342501
55 define i32 @sadd_sat32(i32 %a, i32 %b) {
66 ; CHECK-LABEL: @sadd_sat32(
77 ; CHECK-NEXT: entry:
8 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
9 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
10 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
11 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
12 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
13 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
14 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
15 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
16 ; CHECK-NEXT: ret i32 [[CONV7]]
8 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
9 ; CHECK-NEXT: ret i32 [[TMP0]]
1710 ;
1811 entry:
1912 %conv = sext i32 %a to i64
3023 define i32 @ssub_sat32(i32 %a, i32 %b) {
3124 ; CHECK-LABEL: @ssub_sat32(
3225 ; CHECK-NEXT: entry:
33 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
34 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
35 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[CONV]], [[CONV1]]
36 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[SUB]], 2147483647
37 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[SUB]], i64 2147483647
38 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
39 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
40 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
41 ; CHECK-NEXT: ret i32 [[CONV7]]
26 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
27 ; CHECK-NEXT: ret i32 [[TMP0]]
4228 ;
4329 entry:
4430 %conv = sext i32 %a to i64
8066 define signext i16 @sadd_sat16(i16 signext %a, i16 signext %b) {
8167 ; CHECK-LABEL: @sadd_sat16(
8268 ; CHECK-NEXT: entry:
83 ; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
84 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
85 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
86 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 32767
87 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 32767
88 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
89 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
90 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
91 ; CHECK-NEXT: ret i16 [[CONV9]]
69 ; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
70 ; CHECK-NEXT: ret i16 [[TMP0]]
9271 ;
9372 entry:
9473 %conv = sext i16 %a to i32
10584 define signext i16 @ssub_sat16(i16 signext %a, i16 signext %b) {
10685 ; CHECK-LABEL: @ssub_sat16(
10786 ; CHECK-NEXT: entry:
108 ; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
109 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
110 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
111 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 32767
112 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 32767
113 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
114 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
115 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
116 ; CHECK-NEXT: ret i16 [[CONV9]]
87 ; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
88 ; CHECK-NEXT: ret i16 [[TMP0]]
11789 ;
11890 entry:
11991 %conv = sext i16 %a to i32
130102 define signext i8 @sadd_sat8(i8 signext %a, i8 signext %b) {
131103 ; CHECK-LABEL: @sadd_sat8(
132104 ; CHECK-NEXT: entry:
133 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
134 ; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
135 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
136 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 127
137 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 127
138 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
139 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
140 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
141 ; CHECK-NEXT: ret i8 [[CONV9]]
105 ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
106 ; CHECK-NEXT: ret i8 [[TMP0]]
142107 ;
143108 entry:
144109 %conv = sext i8 %a to i32
155120 define signext i8 @ssub_sat8(i8 signext %a, i8 signext %b) {
156121 ; CHECK-LABEL: @ssub_sat8(
157122 ; CHECK-NEXT: entry:
158 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
159 ; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
160 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
161 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 127
162 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 127
163 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
164 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
165 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
166 ; CHECK-NEXT: ret i8 [[CONV9]]
123 ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
124 ; CHECK-NEXT: ret i8 [[TMP0]]
167125 ;
168126 entry:
169127 %conv = sext i8 %a to i32
180138 define signext i64 @sadd_sat64(i64 signext %a, i64 signext %b) {
181139 ; CHECK-LABEL: @sadd_sat64(
182140 ; CHECK-NEXT: entry:
183 ; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
184 ; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
185 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i65 [[CONV1]], [[CONV]]
186 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[ADD]], 9223372036854775807
187 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[ADD]], i65 9223372036854775807
188 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
189 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
190 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
191 ; CHECK-NEXT: ret i64 [[CONV9]]
141 ; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[B:%.*]], i64 [[A:%.*]])
142 ; CHECK-NEXT: ret i64 [[TMP0]]
192143 ;
193144 entry:
194145 %conv = sext i64 %a to i65
205156 define signext i64 @ssub_sat64(i64 signext %a, i64 signext %b) {
206157 ; CHECK-LABEL: @ssub_sat64(
207158 ; CHECK-NEXT: entry:
208 ; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
209 ; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
210 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i65 [[CONV]], [[CONV1]]
211 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[SUB]], 9223372036854775807
212 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[SUB]], i65 9223372036854775807
213 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
214 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
215 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
216 ; CHECK-NEXT: ret i64 [[CONV9]]
159 ; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.ssub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
160 ; CHECK-NEXT: ret i64 [[TMP0]]
217161 ;
218162 entry:
219163 %conv = sext i64 %a to i65
280224 define <4 x i32> @sadd_satv4i32(<4 x i32> %a, <4 x i32> %b) {
281225 ; CHECK-LABEL: @sadd_satv4i32(
282226 ; CHECK-NEXT: entry:
283 ; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
284 ; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
285 ; CHECK-NEXT: [[ADD:%.*]] = add nsw <4 x i64> [[CONV1]], [[CONV]]
286 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]],
287 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64>
288 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]],
289 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64>
290 ; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
291 ; CHECK-NEXT: ret <4 x i32> [[CONV7]]
227 ; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
228 ; CHECK-NEXT: ret <4 x i32> [[TMP0]]
292229 ;
293230 entry:
294231 %conv = sext <4 x i32> %a to <4 x i64>
305242 define <4 x i32> @ssub_satv4i32(<4 x i32> %a, <4 x i32> %b) {
306243 ; CHECK-LABEL: @ssub_satv4i32(
307244 ; CHECK-NEXT: entry:
308 ; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
309 ; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
310 ; CHECK-NEXT: [[ADD:%.*]] = sub nsw <4 x i64> [[CONV1]], [[CONV]]
311 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]],
312 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64>
313 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]],
314 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64>
315 ; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
316 ; CHECK-NEXT: ret <4 x i32> [[CONV7]]
245 ; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
246 ; CHECK-NEXT: ret <4 x i32> [[TMP0]]
317247 ;
318248 entry:
319249 %conv = sext <4 x i32> %a to <4 x i64>
369299 define i32 @sadd_sat32_extrause_1(i32 %a, i32 %b) {
370300 ; CHECK-LABEL: @sadd_sat32_extrause_1(
371301 ; CHECK-NEXT: entry:
372 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
373 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
374 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
375 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
376 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
377 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
378 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
379 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
302 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
303 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
380304 ; CHECK-NEXT: call void @use64(i64 [[SPEC_STORE_SELECT8]])
381 ; CHECK-NEXT: ret i32 [[CONV7]]
305 ; CHECK-NEXT: ret i32 [[TMP0]]
382306 ;
383307 entry:
384308 %conv = sext i32 %a to i64
475399 define i32 @sadd_sat32_ext16(i32 %a, i16 %b) {
476400 ; CHECK-LABEL: @sadd_sat32_ext16(
477401 ; CHECK-NEXT: entry:
478 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
479 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i64
480 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
481 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
482 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
483 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
484 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
485 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
486 ; CHECK-NEXT: ret i32 [[CONV7]]
402 ; CHECK-NEXT: [[TMP0:%.*]] = sext i16 [[B:%.*]] to i32
403 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 [[A:%.*]])
404 ; CHECK-NEXT: ret i32 [[TMP1]]
487405 ;
488406 entry:
489407 %conv = sext i32 %a to i64
548466 define i32 @sadd_sat32_maxmin(i32 %a, i32 %b) {
549467 ; CHECK-LABEL: @sadd_sat32_maxmin(
550468 ; CHECK-NEXT: entry:
551 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
552 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
553 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
554 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
555 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
556 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
557 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
558 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
559 ; CHECK-NEXT: ret i32 [[CONV7]]
469 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
470 ; CHECK-NEXT: ret i32 [[TMP0]]
560471 ;
561472 entry:
562473 %conv = sext i32 %a to i64
573484 define i64 @sadd_sat32_notrunc(i32 %a, i32 %b) {
574485 ; CHECK-LABEL: @sadd_sat32_notrunc(
575486 ; CHECK-NEXT: entry:
576 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
577 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
578 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
579 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
580 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
581 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
582 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
487 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
488 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
583489 ; CHECK-NEXT: ret i64 [[SPEC_STORE_SELECT8]]
584490 ;
585491 entry: