[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / sadd_sat.ll
blobb9a4771f6eeb49d065d13fc27970273c087f1427
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
6 define i32 @sadd_sat32(i32 %a, i32 %b) {
7 ; CHECK-LABEL: @sadd_sat32(
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
10 ; CHECK-NEXT:    ret i32 [[TMP0]]
12 entry:
13   %conv = sext i32 %a to i64
14   %conv1 = sext i32 %b to i64
15   %add = add i64 %conv1, %conv
16   %0 = icmp slt i64 %add, 2147483647
17   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
18   %1 = icmp sgt i64 %spec.store.select, -2147483648
19   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
20   %conv7 = trunc i64 %spec.store.select8 to i32
21   ret i32 %conv7
24 define i32 @sadd_sat32_mm(i32 %a, i32 %b) {
25 ; CHECK-LABEL: @sadd_sat32_mm(
26 ; CHECK-NEXT:  entry:
27 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
28 ; CHECK-NEXT:    ret i32 [[TMP0]]
30 entry:
31   %conv = sext i32 %a to i64
32   %conv1 = sext i32 %b to i64
33   %add = add i64 %conv1, %conv
34   %spec.store.select = call i64 @llvm.smin.i64(i64 %add, i64 2147483647)
35   %spec.store.select8 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
36   %conv7 = trunc i64 %spec.store.select8 to i32
37   ret i32 %conv7
40 define i32 @ssub_sat32(i32 %a, i32 %b) {
41 ; CHECK-LABEL: @ssub_sat32(
42 ; CHECK-NEXT:  entry:
43 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
44 ; CHECK-NEXT:    ret i32 [[TMP0]]
46 entry:
47   %conv = sext i32 %a to i64
48   %conv1 = sext i32 %b to i64
49   %sub = sub i64 %conv, %conv1
50   %0 = icmp slt i64 %sub, 2147483647
51   %spec.store.select = select i1 %0, i64 %sub, i64 2147483647
52   %1 = icmp sgt i64 %spec.store.select, -2147483648
53   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
54   %conv7 = trunc i64 %spec.store.select8 to i32
55   ret i32 %conv7
58 define i32 @ssub_sat32_mm(i32 %a, i32 %b) {
59 ; CHECK-LABEL: @ssub_sat32_mm(
60 ; CHECK-NEXT:  entry:
61 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
62 ; CHECK-NEXT:    ret i32 [[TMP0]]
64 entry:
65   %conv = sext i32 %a to i64
66   %conv1 = sext i32 %b to i64
67   %sub = sub i64 %conv, %conv1
68   %spec.store.select = call i64 @llvm.smin.i64(i64 %sub, i64 2147483647)
69   %spec.store.select8 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
70   %conv7 = trunc i64 %spec.store.select8 to i32
71   ret i32 %conv7
74 define i32 @smul_sat32(i32 %a, i32 %b) {
75 ; CHECK-LABEL: @smul_sat32(
76 ; CHECK-NEXT:  entry:
77 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
78 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
79 ; CHECK-NEXT:    [[ADD:%.*]] = mul nsw i64 [[CONV1]], [[CONV]]
80 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
81 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
82 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
83 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
84 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
85 ; CHECK-NEXT:    ret i32 [[CONV7]]
87 entry:
88   %conv = sext i32 %a to i64
89   %conv1 = sext i32 %b to i64
90   %add = mul i64 %conv1, %conv
91   %0 = icmp slt i64 %add, 2147483647
92   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
93   %1 = icmp sgt i64 %spec.store.select, -2147483648
94   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
95   %conv7 = trunc i64 %spec.store.select8 to i32
96   ret i32 %conv7
99 define i32 @smul_sat32_mm(i32 %a, i32 %b) {
100 ; CHECK-LABEL: @smul_sat32_mm(
101 ; CHECK-NEXT:  entry:
102 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
103 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
104 ; CHECK-NEXT:    [[ADD:%.*]] = mul nsw i64 [[CONV1]], [[CONV]]
105 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = call i64 @llvm.smin.i64(i64 [[ADD]], i64 2147483647)
106 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = call i64 @llvm.smax.i64(i64 [[SPEC_STORE_SELECT]], i64 -2147483648)
107 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
108 ; CHECK-NEXT:    ret i32 [[CONV7]]
110 entry:
111   %conv = sext i32 %a to i64
112   %conv1 = sext i32 %b to i64
113   %add = mul i64 %conv1, %conv
114   %spec.store.select = call i64 @llvm.smin.i64(i64 %add, i64 2147483647)
115   %spec.store.select8 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
116   %conv7 = trunc i64 %spec.store.select8 to i32
117   ret i32 %conv7
120 define signext i16 @sadd_sat16(i16 signext %a, i16 signext %b) {
121 ; CHECK-LABEL: @sadd_sat16(
122 ; CHECK-NEXT:  entry:
123 ; CHECK-NEXT:    [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
124 ; CHECK-NEXT:    ret i16 [[TMP0]]
126 entry:
127   %conv = sext i16 %a to i32
128   %conv1 = sext i16 %b to i32
129   %add = add i32 %conv1, %conv
130   %0 = icmp slt i32 %add, 32767
131   %spec.store.select = select i1 %0, i32 %add, i32 32767
132   %1 = icmp sgt i32 %spec.store.select, -32768
133   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -32768
134   %conv9 = trunc i32 %spec.store.select10 to i16
135   ret i16 %conv9
138 define signext i16 @sadd_sat16_mm(i16 signext %a, i16 signext %b) {
139 ; CHECK-LABEL: @sadd_sat16_mm(
140 ; CHECK-NEXT:  entry:
141 ; CHECK-NEXT:    [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
142 ; CHECK-NEXT:    ret i16 [[TMP0]]
144 entry:
145   %conv = sext i16 %a to i32
146   %conv1 = sext i16 %b to i32
147   %add = add i32 %conv1, %conv
148   %spec.store.select = call i32 @llvm.smin.i32(i32 %add, i32 32767)
149   %spec.store.select10 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
150   %conv9 = trunc i32 %spec.store.select10 to i16
151   ret i16 %conv9
154 define signext i16 @ssub_sat16(i16 signext %a, i16 signext %b) {
155 ; CHECK-LABEL: @ssub_sat16(
156 ; CHECK-NEXT:  entry:
157 ; CHECK-NEXT:    [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
158 ; CHECK-NEXT:    ret i16 [[TMP0]]
160 entry:
161   %conv = sext i16 %a to i32
162   %conv1 = sext i16 %b to i32
163   %sub = sub i32 %conv, %conv1
164   %0 = icmp slt i32 %sub, 32767
165   %spec.store.select = select i1 %0, i32 %sub, i32 32767
166   %1 = icmp sgt i32 %spec.store.select, -32768
167   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -32768
168   %conv9 = trunc i32 %spec.store.select10 to i16
169   ret i16 %conv9
172 define signext i16 @ssub_sat16_mm(i16 signext %a, i16 signext %b) {
173 ; CHECK-LABEL: @ssub_sat16_mm(
174 ; CHECK-NEXT:  entry:
175 ; CHECK-NEXT:    [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
176 ; CHECK-NEXT:    ret i16 [[TMP0]]
178 entry:
179   %conv = sext i16 %a to i32
180   %conv1 = sext i16 %b to i32
181   %sub = sub i32 %conv, %conv1
182   %spec.store.select = call i32 @llvm.smin.i32(i32 %sub, i32 32767)
183   %spec.store.select10 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
184   %conv9 = trunc i32 %spec.store.select10 to i16
185   ret i16 %conv9
188 define signext i8 @sadd_sat8(i8 signext %a, i8 signext %b) {
189 ; CHECK-LABEL: @sadd_sat8(
190 ; CHECK-NEXT:  entry:
191 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
192 ; CHECK-NEXT:    ret i8 [[TMP0]]
194 entry:
195   %conv = sext i8 %a to i32
196   %conv1 = sext i8 %b to i32
197   %add = add i32 %conv1, %conv
198   %0 = icmp slt i32 %add, 127
199   %spec.store.select = select i1 %0, i32 %add, i32 127
200   %1 = icmp sgt i32 %spec.store.select, -128
201   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -128
202   %conv9 = trunc i32 %spec.store.select10 to i8
203   ret i8 %conv9
206 define signext i8 @sadd_sat8_mm(i8 signext %a, i8 signext %b) {
207 ; CHECK-LABEL: @sadd_sat8_mm(
208 ; CHECK-NEXT:  entry:
209 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
210 ; CHECK-NEXT:    ret i8 [[TMP0]]
212 entry:
213   %conv = sext i8 %a to i32
214   %conv1 = sext i8 %b to i32
215   %add = add i32 %conv1, %conv
216   %spec.store.select = call i32 @llvm.smin.i32(i32 %add, i32 127)
217   %spec.store.select10 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -128)
218   %conv9 = trunc i32 %spec.store.select10 to i8
219   ret i8 %conv9
222 define signext i8 @ssub_sat8(i8 signext %a, i8 signext %b) {
223 ; CHECK-LABEL: @ssub_sat8(
224 ; CHECK-NEXT:  entry:
225 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
226 ; CHECK-NEXT:    ret i8 [[TMP0]]
228 entry:
229   %conv = sext i8 %a to i32
230   %conv1 = sext i8 %b to i32
231   %sub = sub i32 %conv, %conv1
232   %0 = icmp slt i32 %sub, 127
233   %spec.store.select = select i1 %0, i32 %sub, i32 127
234   %1 = icmp sgt i32 %spec.store.select, -128
235   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -128
236   %conv9 = trunc i32 %spec.store.select10 to i8
237   ret i8 %conv9
240 define signext i8 @ssub_sat8_mm(i8 signext %a, i8 signext %b) {
241 ; CHECK-LABEL: @ssub_sat8_mm(
242 ; CHECK-NEXT:  entry:
243 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
244 ; CHECK-NEXT:    ret i8 [[TMP0]]
246 entry:
247   %conv = sext i8 %a to i32
248   %conv1 = sext i8 %b to i32
249   %sub = sub i32 %conv, %conv1
250   %spec.store.select = call i32 @llvm.smin.i32(i32 %sub, i32 127)
251   %spec.store.select10 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -128)
252   %conv9 = trunc i32 %spec.store.select10 to i8
253   ret i8 %conv9
256 define signext i64 @sadd_sat64(i64 signext %a, i64 signext %b) {
257 ; CHECK-LABEL: @sadd_sat64(
258 ; CHECK-NEXT:  entry:
259 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[B:%.*]], i64 [[A:%.*]])
260 ; CHECK-NEXT:    ret i64 [[TMP0]]
262 entry:
263   %conv = sext i64 %a to i65
264   %conv1 = sext i64 %b to i65
265   %add = add i65 %conv1, %conv
266   %0 = icmp slt i65 %add, 9223372036854775807
267   %spec.store.select = select i1 %0, i65 %add, i65 9223372036854775807
268   %1 = icmp sgt i65 %spec.store.select, -9223372036854775808
269   %spec.store.select10 = select i1 %1, i65 %spec.store.select, i65 -9223372036854775808
270   %conv9 = trunc i65 %spec.store.select10 to i64
271   ret i64 %conv9
274 define signext i64 @ssub_sat64(i64 signext %a, i64 signext %b) {
275 ; CHECK-LABEL: @ssub_sat64(
276 ; CHECK-NEXT:  entry:
277 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.ssub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
278 ; CHECK-NEXT:    ret i64 [[TMP0]]
280 entry:
281   %conv = sext i64 %a to i65
282   %conv1 = sext i64 %b to i65
283   %sub = sub i65 %conv, %conv1
284   %0 = icmp slt i65 %sub, 9223372036854775807
285   %spec.store.select = select i1 %0, i65 %sub, i65 9223372036854775807
286   %1 = icmp sgt i65 %spec.store.select, -9223372036854775808
287   %spec.store.select10 = select i1 %1, i65 %spec.store.select, i65 -9223372036854775808
288   %conv9 = trunc i65 %spec.store.select10 to i64
289   ret i64 %conv9
292 define signext i4 @sadd_sat4(i4 signext %a, i4 signext %b) {
293 ; CHECK-LABEL: @sadd_sat4(
294 ; CHECK-NEXT:  entry:
295 ; CHECK-NEXT:    [[CONV:%.*]] = sext i4 [[A:%.*]] to i32
296 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i4 [[B:%.*]] to i32
297 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
298 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[ADD]], 7
299 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 7
300 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -8
301 ; CHECK-NEXT:    [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -8
302 ; CHECK-NEXT:    [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i4
303 ; CHECK-NEXT:    ret i4 [[CONV9]]
305 entry:
306   %conv = sext i4 %a to i32
307   %conv1 = sext i4 %b to i32
308   %add = add i32 %conv1, %conv
309   %0 = icmp slt i32 %add, 7
310   %spec.store.select = select i1 %0, i32 %add, i32 7
311   %1 = icmp sgt i32 %spec.store.select, -8
312   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -8
313   %conv9 = trunc i32 %spec.store.select10 to i4
314   ret i4 %conv9
317 define signext i4 @ssub_sat4(i4 signext %a, i4 signext %b) {
318 ; CHECK-LABEL: @ssub_sat4(
319 ; CHECK-NEXT:  entry:
320 ; CHECK-NEXT:    [[CONV:%.*]] = sext i4 [[A:%.*]] to i32
321 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i4 [[B:%.*]] to i32
322 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
323 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[SUB]], 7
324 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 7
325 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -8
326 ; CHECK-NEXT:    [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -8
327 ; CHECK-NEXT:    [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i4
328 ; CHECK-NEXT:    ret i4 [[CONV9]]
330 entry:
331   %conv = sext i4 %a to i32
332   %conv1 = sext i4 %b to i32
333   %sub = sub i32 %conv, %conv1
334   %0 = icmp slt i32 %sub, 7
335   %spec.store.select = select i1 %0, i32 %sub, i32 7
336   %1 = icmp sgt i32 %spec.store.select, -8
337   %spec.store.select10 = select i1 %1, i32 %spec.store.select, i32 -8
338   %conv9 = trunc i32 %spec.store.select10 to i4
339   ret i4 %conv9
342 define <4 x i32> @sadd_satv4i32(<4 x i32> %a, <4 x i32> %b) {
343 ; CHECK-LABEL: @sadd_satv4i32(
344 ; CHECK-NEXT:  entry:
345 ; CHECK-NEXT:    [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
346 ; CHECK-NEXT:    ret <4 x i32> [[TMP0]]
348 entry:
349   %conv = sext <4 x i32> %a to <4 x i64>
350   %conv1 = sext <4 x i32> %b to <4 x i64>
351   %add = add <4 x i64> %conv1, %conv
352   %0 = icmp slt <4 x i64> %add, <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
353   %spec.store.select = select <4 x i1> %0, <4 x i64> %add, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
354   %1 = icmp sgt <4 x i64> %spec.store.select, <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
355   %spec.store.select8 = select <4 x i1> %1, <4 x i64> %spec.store.select, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
356   %conv7 = trunc <4 x i64> %spec.store.select8 to <4 x i32>
357   ret <4 x i32> %conv7
360 define <4 x i32> @sadd_satv4i32_mm(<4 x i32> %a, <4 x i32> %b) {
361 ; CHECK-LABEL: @sadd_satv4i32_mm(
362 ; CHECK-NEXT:  entry:
363 ; CHECK-NEXT:    [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
364 ; CHECK-NEXT:    ret <4 x i32> [[TMP0]]
366 entry:
367   %conv = sext <4 x i32> %a to <4 x i64>
368   %conv1 = sext <4 x i32> %b to <4 x i64>
369   %add = add <4 x i64> %conv1, %conv
370   %spec.store.select = call <4 x i64> @llvm.smin.v4i64(<4 x i64> %add, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
371   %spec.store.select8 = call <4 x i64> @llvm.smax.v4i64(<4 x i64> %spec.store.select, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
372   %conv7 = trunc <4 x i64> %spec.store.select8 to <4 x i32>
373   ret <4 x i32> %conv7
376 define <4 x i32> @ssub_satv4i32(<4 x i32> %a, <4 x i32> %b) {
377 ; CHECK-LABEL: @ssub_satv4i32(
378 ; CHECK-NEXT:  entry:
379 ; CHECK-NEXT:    [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
380 ; CHECK-NEXT:    ret <4 x i32> [[TMP0]]
382 entry:
383   %conv = sext <4 x i32> %a to <4 x i64>
384   %conv1 = sext <4 x i32> %b to <4 x i64>
385   %add = sub <4 x i64> %conv1, %conv
386   %0 = icmp slt <4 x i64> %add, <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
387   %spec.store.select = select <4 x i1> %0, <4 x i64> %add, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
388   %1 = icmp sgt <4 x i64> %spec.store.select, <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
389   %spec.store.select8 = select <4 x i1> %1, <4 x i64> %spec.store.select, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
390   %conv7 = trunc <4 x i64> %spec.store.select8 to <4 x i32>
391   ret <4 x i32> %conv7
394 define <4 x i32> @ssub_satv4i32_mm(<4 x i32> %a, <4 x i32> %b) {
395 ; CHECK-LABEL: @ssub_satv4i32_mm(
396 ; CHECK-NEXT:  entry:
397 ; CHECK-NEXT:    [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
398 ; CHECK-NEXT:    ret <4 x i32> [[TMP0]]
400 entry:
401   %conv = sext <4 x i32> %a to <4 x i64>
402   %conv1 = sext <4 x i32> %b to <4 x i64>
403   %add = sub <4 x i64> %conv1, %conv
404   %spec.store.select = call <4 x i64> @llvm.smin.v4i64(<4 x i64> %add, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
405   %spec.store.select8 = call <4 x i64> @llvm.smax.v4i64(<4 x i64> %spec.store.select, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
406   %conv7 = trunc <4 x i64> %spec.store.select8 to <4 x i32>
407   ret <4 x i32> %conv7
410 define <4 x i32> @sadd_satv4i4(<4 x i32> %a, <4 x i32> %b) {
411 ; CHECK-LABEL: @sadd_satv4i4(
412 ; CHECK-NEXT:  entry:
413 ; CHECK-NEXT:    [[ADD:%.*]] = add <4 x i32> [[A:%.*]], [[B:%.*]]
414 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt <4 x i32> [[ADD]], <i32 15, i32 15, i32 15, i32 15>
415 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[ADD]], <4 x i32> <i32 15, i32 15, i32 15, i32 15>
416 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i32> [[SPEC_STORE_SELECT]], <i32 -16, i32 -16, i32 -16, i32 -16>
417 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[SPEC_STORE_SELECT]], <4 x i32> <i32 -16, i32 -16, i32 -16, i32 -16>
418 ; CHECK-NEXT:    ret <4 x i32> [[SPEC_STORE_SELECT8]]
420 entry:
421   %add = add <4 x i32> %a, %b
422   %0 = icmp slt <4 x i32> %add, <i32 15, i32 15, i32 15, i32 15>
423   %spec.store.select = select <4 x i1> %0, <4 x i32> %add, <4 x i32> <i32 15, i32 15, i32 15, i32 15>
424   %1 = icmp sgt <4 x i32> %spec.store.select, <i32 -16, i32 -16, i32 -16, i32 -16>
425   %spec.store.select8 = select <4 x i1> %1, <4 x i32> %spec.store.select, <4 x i32> <i32 -16, i32 -16, i32 -16, i32 -16>
426   ret <4 x i32> %spec.store.select8
429 define <4 x i32> @ssub_satv4i4(<4 x i32> %a, <4 x i32> %b) {
430 ; CHECK-LABEL: @ssub_satv4i4(
431 ; CHECK-NEXT:  entry:
432 ; CHECK-NEXT:    [[ADD:%.*]] = sub <4 x i32> [[A:%.*]], [[B:%.*]]
433 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt <4 x i32> [[ADD]], <i32 15, i32 15, i32 15, i32 15>
434 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[ADD]], <4 x i32> <i32 15, i32 15, i32 15, i32 15>
435 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i32> [[SPEC_STORE_SELECT]], <i32 -16, i32 -16, i32 -16, i32 -16>
436 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[SPEC_STORE_SELECT]], <4 x i32> <i32 -16, i32 -16, i32 -16, i32 -16>
437 ; CHECK-NEXT:    ret <4 x i32> [[SPEC_STORE_SELECT8]]
439 entry:
440   %add = sub <4 x i32> %a, %b
441   %0 = icmp slt <4 x i32> %add, <i32 15, i32 15, i32 15, i32 15>
442   %spec.store.select = select <4 x i1> %0, <4 x i32> %add, <4 x i32> <i32 15, i32 15, i32 15, i32 15>
443   %1 = icmp sgt <4 x i32> %spec.store.select, <i32 -16, i32 -16, i32 -16, i32 -16>
444   %spec.store.select8 = select <4 x i1> %1, <4 x i32> %spec.store.select, <4 x i32> <i32 -16, i32 -16, i32 -16, i32 -16>
445   ret <4 x i32> %spec.store.select8
449 define i32 @sadd_sat32_extrause_1(i32 %a, i32 %b) {
450 ; CHECK-LABEL: @sadd_sat32_extrause_1(
451 ; CHECK-NEXT:  entry:
452 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
453 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
454 ; CHECK-NEXT:    call void @use64(i64 [[SPEC_STORE_SELECT8]])
455 ; CHECK-NEXT:    ret i32 [[TMP0]]
457 entry:
458   %conv = sext i32 %a to i64
459   %conv1 = sext i32 %b to i64
460   %add = add i64 %conv1, %conv
461   %0 = icmp slt i64 %add, 2147483647
462   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
463   %1 = icmp sgt i64 %spec.store.select, -2147483648
464   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
465   %conv7 = trunc i64 %spec.store.select8 to i32
466   call void @use64(i64 %spec.store.select8)
467   ret i32 %conv7
470 define i32 @sadd_sat32_extrause_2(i32 %a, i32 %b) {
471 ; CHECK-LABEL: @sadd_sat32_extrause_2(
472 ; CHECK-NEXT:  entry:
473 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
474 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
475 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
476 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
477 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
478 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
479 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
480 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
481 ; CHECK-NEXT:    call void @use64(i64 [[SPEC_STORE_SELECT]])
482 ; CHECK-NEXT:    ret i32 [[CONV7]]
484 entry:
485   %conv = sext i32 %a to i64
486   %conv1 = sext i32 %b to i64
487   %add = add i64 %conv1, %conv
488   %0 = icmp slt i64 %add, 2147483647
489   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
490   %1 = icmp sgt i64 %spec.store.select, -2147483648
491   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
492   %conv7 = trunc i64 %spec.store.select8 to i32
493   call void @use64(i64 %spec.store.select)
494   ret i32 %conv7
497 define i32 @sadd_sat32_extrause_2_mm(i32 %a, i32 %b) {
498 ; CHECK-LABEL: @sadd_sat32_extrause_2_mm(
499 ; CHECK-NEXT:  entry:
500 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
501 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
502 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
503 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = call i64 @llvm.smin.i64(i64 [[ADD]], i64 2147483647)
504 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = call i64 @llvm.smax.i64(i64 [[SPEC_STORE_SELECT]], i64 -2147483648)
505 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
506 ; CHECK-NEXT:    call void @use64(i64 [[SPEC_STORE_SELECT]])
507 ; CHECK-NEXT:    ret i32 [[CONV7]]
509 entry:
510   %conv = sext i32 %a to i64
511   %conv1 = sext i32 %b to i64
512   %add = add i64 %conv1, %conv
513   %spec.store.select = call i64 @llvm.smin.i64(i64 %add, i64 2147483647)
514   %spec.store.select8 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
515   %conv7 = trunc i64 %spec.store.select8 to i32
516   call void @use64(i64 %spec.store.select)
517   ret i32 %conv7
520 define i32 @sadd_sat32_extrause_3(i32 %a, i32 %b) {
521 ; CHECK-LABEL: @sadd_sat32_extrause_3(
522 ; CHECK-NEXT:  entry:
523 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
524 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
525 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
526 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
527 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
528 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
529 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
530 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
531 ; CHECK-NEXT:    call void @use64(i64 [[ADD]])
532 ; CHECK-NEXT:    ret i32 [[CONV7]]
534 entry:
535   %conv = sext i32 %a to i64
536   %conv1 = sext i32 %b to i64
537   %add = add i64 %conv1, %conv
538   %0 = icmp slt i64 %add, 2147483647
539   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
540   %1 = icmp sgt i64 %spec.store.select, -2147483648
541   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
542   %conv7 = trunc i64 %spec.store.select8 to i32
543   call void @use64(i64 %add)
544   ret i32 %conv7
547 define i32 @sadd_sat32_extrause_3_mm(i32 %a, i32 %b) {
548 ; CHECK-LABEL: @sadd_sat32_extrause_3_mm(
549 ; CHECK-NEXT:  entry:
550 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
551 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
552 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
553 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = call i64 @llvm.smin.i64(i64 [[ADD]], i64 2147483647)
554 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = call i64 @llvm.smax.i64(i64 [[SPEC_STORE_SELECT]], i64 -2147483648)
555 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
556 ; CHECK-NEXT:    call void @use64(i64 [[ADD]])
557 ; CHECK-NEXT:    ret i32 [[CONV7]]
559 entry:
560   %conv = sext i32 %a to i64
561   %conv1 = sext i32 %b to i64
562   %add = add i64 %conv1, %conv
563   %spec.store.select = call i64 @llvm.smin.i64(i64 %add, i64 2147483647)
564   %spec.store.select8 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
565   %conv7 = trunc i64 %spec.store.select8 to i32
566   call void @use64(i64 %add)
567   ret i32 %conv7
570 define i32 @sadd_sat32_trunc(i32 %a, i32 %b) {
571 ; CHECK-LABEL: @sadd_sat32_trunc(
572 ; CHECK-NEXT:  entry:
573 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
574 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
575 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
576 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[ADD]], 32767
577 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 32767
578 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -32768
579 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -32768
580 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
581 ; CHECK-NEXT:    ret i32 [[CONV7]]
583 entry:
584   %conv = sext i32 %a to i64
585   %conv1 = sext i32 %b to i64
586   %add = add i64 %conv1, %conv
587   %0 = icmp slt i64 %add, 32767
588   %spec.store.select = select i1 %0, i64 %add, i64 32767
589   %1 = icmp sgt i64 %spec.store.select, -32768
590   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -32768
591   %conv7 = trunc i64 %spec.store.select8 to i32
592   ret i32 %conv7
595 define i32 @sadd_sat32_ext16(i32 %a, i16 %b) {
596 ; CHECK-LABEL: @sadd_sat32_ext16(
597 ; CHECK-NEXT:  entry:
598 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i16 [[B:%.*]] to i32
599 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 [[A:%.*]])
600 ; CHECK-NEXT:    ret i32 [[TMP1]]
602 entry:
603   %conv = sext i32 %a to i64
604   %conv1 = sext i16 %b to i64
605   %add = add i64 %conv1, %conv
606   %0 = icmp slt i64 %add, 2147483647
607   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
608   %1 = icmp sgt i64 %spec.store.select, -2147483648
609   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
610   %conv7 = trunc i64 %spec.store.select8 to i32
611   ret i32 %conv7
614 define i8 @sadd_sat8_ext8(i8 %a, i16 %b) {
615 ; CHECK-LABEL: @sadd_sat8_ext8(
616 ; CHECK-NEXT:  entry:
617 ; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
618 ; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
619 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
620 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[ADD]], 127
621 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 127
622 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
623 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
624 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i32 [[SPEC_STORE_SELECT8]] to i8
625 ; CHECK-NEXT:    ret i8 [[CONV7]]
627 entry:
628   %conv = sext i8 %a to i32
629   %conv1 = sext i16 %b to i32
630   %add = add i32 %conv1, %conv
631   %0 = icmp slt i32 %add, 127
632   %spec.store.select = select i1 %0, i32 %add, i32 127
633   %1 = icmp sgt i32 %spec.store.select, -128
634   %spec.store.select8 = select i1 %1, i32 %spec.store.select, i32 -128
635   %conv7 = trunc i32 %spec.store.select8 to i8
636   ret i8 %conv7
639 define i32 @sadd_sat32_zext(i32 %a, i32 %b) {
640 ; CHECK-LABEL: @sadd_sat32_zext(
641 ; CHECK-NEXT:  entry:
642 ; CHECK-NEXT:    [[CONV:%.*]] = zext i32 [[A:%.*]] to i64
643 ; CHECK-NEXT:    [[CONV1:%.*]] = zext i32 [[B:%.*]] to i64
644 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i64 [[CONV1]], [[CONV]]
645 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[ADD]], 2147483647
646 ; CHECK-NEXT:    [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
647 ; CHECK-NEXT:    [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT]] to i32
648 ; CHECK-NEXT:    ret i32 [[CONV7]]
650 entry:
651   %conv = zext i32 %a to i64
652   %conv1 = zext i32 %b to i64
653   %add = add i64 %conv1, %conv
654   %0 = icmp slt i64 %add, 2147483647
655   %spec.store.select = select i1 %0, i64 %add, i64 2147483647
656   %1 = icmp sgt i64 %spec.store.select, -2147483648
657   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 -2147483648
658   %conv7 = trunc i64 %spec.store.select8 to i32
659   ret i32 %conv7
662 define i32 @sadd_sat32_maxmin(i32 %a, i32 %b) {
663 ; CHECK-LABEL: @sadd_sat32_maxmin(
664 ; CHECK-NEXT:  entry:
665 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
666 ; CHECK-NEXT:    ret i32 [[TMP0]]
668 entry:
669   %conv = sext i32 %a to i64
670   %conv1 = sext i32 %b to i64
671   %add = add i64 %conv1, %conv
672   %0 = icmp sgt i64 %add, -2147483648
673   %spec.store.select = select i1 %0, i64 %add, i64 -2147483648
674   %1 = icmp slt i64 %spec.store.select, 2147483647
675   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 2147483647
676   %conv7 = trunc i64 %spec.store.select8 to i32
677   ret i32 %conv7
680 define i64 @sadd_sat32_notrunc(i32 %a, i32 %b) {
681 ; CHECK-LABEL: @sadd_sat32_notrunc(
682 ; CHECK-NEXT:  entry:
683 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
684 ; CHECK-NEXT:    [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
685 ; CHECK-NEXT:    ret i64 [[SPEC_STORE_SELECT8]]
687 entry:
688   %conv = sext i32 %a to i64
689   %conv1 = sext i32 %b to i64
690   %add = add i64 %conv1, %conv
691   %0 = icmp sgt i64 %add, -2147483648
692   %spec.store.select = select i1 %0, i64 %add, i64 -2147483648
693   %1 = icmp slt i64 %spec.store.select, 2147483647
694   %spec.store.select8 = select i1 %1, i64 %spec.store.select, i64 2147483647
695   ret i64 %spec.store.select8
698 declare void @use64(i64)
699 declare i64 @llvm.smin.i64(i64, i64)
700 declare i64 @llvm.smax.i64(i64, i64)
701 declare i32 @llvm.smin.i32(i32, i32)
702 declare i32 @llvm.smax.i32(i32, i32)
703 declare <4 x i64> @llvm.smin.v4i64(<4 x i64>, <4 x i64>)
704 declare <4 x i64> @llvm.smax.v4i64(<4 x i64>, <4 x i64>)