1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
3 // RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
4 
5 short _Accum sa;
6 _Accum a, a2, a3, a4;
7 long _Accum la;
8 unsigned short _Accum usa;
9 unsigned _Accum ua;
10 unsigned long _Accum ula;
11 
12 short _Fract sf;
13 _Fract f;
14 long _Fract lf;
15 unsigned short _Fract usf;
16 unsigned _Fract uf;
17 unsigned long _Fract ulf;
18 
19 _Sat short _Accum sa_sat;
20 _Sat _Accum a_sat;
21 _Sat long _Accum la_sat;
22 _Sat unsigned short _Accum usa_sat;
23 _Sat unsigned _Accum ua_sat;
24 _Sat unsigned long _Accum ula_sat;
25 _Sat unsigned _Fract uf_sat;
26 
27 int i;
28 unsigned int ui;
29 _Bool b;
30 
31 // CHECK-LABEL: @ssub_sasasa(
32 // CHECK-NEXT:  entry:
33 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
34 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @sa, align 2
35 // CHECK-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
36 // CHECK-NEXT:    store i16 [[TMP2]], i16* @sa, align 2
37 // CHECK-NEXT:    ret void
38 //
ssub_sasasa()39 void ssub_sasasa() {
40   sa = sa - sa;
41 }
42 
43 // CHECK-LABEL: @ssub_asaa(
44 // CHECK-NEXT:  entry:
45 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
46 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
47 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
48 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
49 // CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
50 // CHECK-NEXT:    store i32 [[TMP2]], i32* @a, align 4
51 // CHECK-NEXT:    ret void
52 //
ssub_asaa()53 void ssub_asaa() {
54   a = sa - a;
55 }
56 
57 // CHECK-LABEL: @ssub_sasasf(
58 // CHECK-NEXT:  entry:
59 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
60 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @sf, align 1
61 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
62 // CHECK-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
63 // CHECK-NEXT:    store i16 [[TMP2]], i16* @sa, align 2
64 // CHECK-NEXT:    ret void
65 //
ssub_sasasf()66 void ssub_sasasf() {
67   sa = sa - sf;
68 }
69 
70 // CHECK-LABEL: @ssub_sasaf(
71 // CHECK-NEXT:  entry:
72 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
73 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @f, align 2
74 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i24
75 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
76 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i24
77 // CHECK-NEXT:    [[TMP2:%.*]] = sub i24 [[UPSCALE]], [[RESIZE1]]
78 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i24 [[TMP2]], 8
79 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
80 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
81 // CHECK-NEXT:    ret void
82 //
ssub_sasaf()83 void ssub_sasaf() {
84   sa = sa - f;
85 }
86 
87 // CHECK-LABEL: @ssub_aasf(
88 // CHECK-NEXT:  entry:
89 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
90 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @sf, align 1
91 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
92 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
93 // CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP0]], [[UPSCALE]]
94 // CHECK-NEXT:    store i32 [[TMP2]], i32* @a, align 4
95 // CHECK-NEXT:    ret void
96 //
ssub_aasf()97 void ssub_aasf() {
98   a = a - sf;
99 }
100 
101 // CHECK-LABEL: @ssub_aalf(
102 // CHECK-NEXT:  entry:
103 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
104 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @lf, align 4
105 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
106 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
107 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i48
108 // CHECK-NEXT:    [[TMP2:%.*]] = sub i48 [[UPSCALE]], [[RESIZE1]]
109 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i48 [[TMP2]], 16
110 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i48 [[DOWNSCALE]] to i32
111 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
112 // CHECK-NEXT:    ret void
113 //
ssub_aalf()114 void ssub_aalf() {
115   a = a - lf;
116 }
117 
118 // SIGNED-LABEL: @ssub_sasausa(
119 // SIGNED-NEXT:  entry:
120 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
121 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa, align 2
122 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
123 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
124 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i17
125 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i17 [[UPSCALE]], [[RESIZE1]]
126 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
127 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
128 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
129 // SIGNED-NEXT:    ret void
130 //
131 // UNSIGNED-LABEL: @ssub_sasausa(
132 // UNSIGNED-NEXT:  entry:
133 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
134 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa, align 2
135 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
136 // UNSIGNED-NEXT:    store i16 [[TMP2]], i16* @sa, align 2
137 // UNSIGNED-NEXT:    ret void
138 //
ssub_sasausa()139 void ssub_sasausa() {
140   sa = sa - usa;
141 }
142 
143 // SIGNED-LABEL: @ssub_asaua(
144 // SIGNED-NEXT:  entry:
145 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
146 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ua, align 4
147 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i33
148 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 9
149 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i33
150 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i33 [[UPSCALE]], [[RESIZE1]]
151 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
152 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
153 // SIGNED-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
154 // SIGNED-NEXT:    ret void
155 //
156 // UNSIGNED-LABEL: @ssub_asaua(
157 // UNSIGNED-NEXT:  entry:
158 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
159 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ua, align 4
160 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
161 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
162 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
163 // UNSIGNED-NEXT:    store i32 [[TMP2]], i32* @a, align 4
164 // UNSIGNED-NEXT:    ret void
165 //
ssub_asaua()166 void ssub_asaua() {
167   a = sa - ua;
168 }
169 
170 // SIGNED-LABEL: @ssub_sasausf(
171 // SIGNED-NEXT:  entry:
172 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
173 // SIGNED-NEXT:    [[TMP1:%.*]] = load i8, i8* @usf, align 1
174 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
175 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
176 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i8 [[TMP1]] to i17
177 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i17 [[UPSCALE]], [[RESIZE1]]
178 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
179 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
180 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
181 // SIGNED-NEXT:    ret void
182 //
183 // UNSIGNED-LABEL: @ssub_sasausf(
184 // UNSIGNED-NEXT:  entry:
185 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
186 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i8, i8* @usf, align 1
187 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
188 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
189 // UNSIGNED-NEXT:    store i16 [[TMP2]], i16* @sa, align 2
190 // UNSIGNED-NEXT:    ret void
191 //
ssub_sasausf()192 void ssub_sasausf() {
193   sa = sa - usf;
194 }
195 
196 // SIGNED-LABEL: @ssub_sasaulf(
197 // SIGNED-NEXT:  entry:
198 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
199 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ulf, align 4
200 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i41
201 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i41 [[RESIZE]], 25
202 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i41
203 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i41 [[UPSCALE]], [[RESIZE1]]
204 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i41 [[TMP2]], 25
205 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i41 [[DOWNSCALE]] to i16
206 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
207 // SIGNED-NEXT:    ret void
208 //
209 // UNSIGNED-LABEL: @ssub_sasaulf(
210 // UNSIGNED-NEXT:  entry:
211 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
212 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ulf, align 4
213 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
214 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 24
215 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
216 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i40 [[UPSCALE]], [[RESIZE1]]
217 // UNSIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i40 [[TMP2]], 24
218 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[DOWNSCALE]] to i16
219 // UNSIGNED-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
220 // UNSIGNED-NEXT:    ret void
221 //
ssub_sasaulf()222 void ssub_sasaulf() {
223   sa = sa - ulf;
224 }
225 
226 // CHECK-LABEL: @ssub_aaaaa(
227 // CHECK-NEXT:  entry:
228 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
229 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a2, align 4
230 // CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP0]], [[TMP1]]
231 // CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* @a3, align 4
232 // CHECK-NEXT:    [[TMP4:%.*]] = sub i32 [[TMP2]], [[TMP3]]
233 // CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* @a4, align 4
234 // CHECK-NEXT:    [[TMP6:%.*]] = sub i32 [[TMP4]], [[TMP5]]
235 // CHECK-NEXT:    store i32 [[TMP6]], i32* @a, align 4
236 // CHECK-NEXT:    ret void
237 //
ssub_aaaaa()238 void ssub_aaaaa() {
239   a = a - a2 - a3 - a4;
240 }
241 
242 
243 // CHECK-LABEL: @usub_usausausa(
244 // CHECK-NEXT:  entry:
245 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
246 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa, align 2
247 // CHECK-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
248 // CHECK-NEXT:    store i16 [[TMP2]], i16* @usa, align 2
249 // CHECK-NEXT:    ret void
250 //
usub_usausausa()251 void usub_usausausa() {
252   usa = usa - usa;
253 }
254 
255 // CHECK-LABEL: @usub_uausaua(
256 // CHECK-NEXT:  entry:
257 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
258 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @ua, align 4
259 // CHECK-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
260 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
261 // CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
262 // CHECK-NEXT:    store i32 [[TMP2]], i32* @ua, align 4
263 // CHECK-NEXT:    ret void
264 //
usub_uausaua()265 void usub_uausaua() {
266   ua = usa - ua;
267 }
268 
269 // CHECK-LABEL: @usub_usausausf(
270 // CHECK-NEXT:  entry:
271 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
272 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @usf, align 1
273 // CHECK-NEXT:    [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
274 // CHECK-NEXT:    [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
275 // CHECK-NEXT:    store i16 [[TMP2]], i16* @usa, align 2
276 // CHECK-NEXT:    ret void
277 //
usub_usausausf()278 void usub_usausausf() {
279   usa = usa - usf;
280 }
281 
282 // CHECK-LABEL: @usub_usausauf(
283 // CHECK-NEXT:  entry:
284 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
285 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf, align 2
286 // CHECK-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
287 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
288 // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
289 // CHECK-NEXT:    [[TMP2:%.*]] = sub i24 [[UPSCALE]], [[RESIZE1]]
290 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
291 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
292 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @usa, align 2
293 // CHECK-NEXT:    ret void
294 //
usub_usausauf()295 void usub_usausauf() {
296   usa = usa - uf;
297 }
298 
299 
300 // CHECK-LABEL: @int_sasai(
301 // CHECK-NEXT:  entry:
302 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
303 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
304 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
305 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
306 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
307 // CHECK-NEXT:    [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
308 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
309 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
310 // CHECK-NEXT:    ret void
311 //
int_sasai()312 void int_sasai() {
313   sa = sa - i;
314 }
315 
316 // CHECK-LABEL: @int_sasaui(
317 // CHECK-NEXT:  entry:
318 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
319 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @ui, align 4
320 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
321 // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
322 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
323 // CHECK-NEXT:    [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
324 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
325 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @sa, align 2
326 // CHECK-NEXT:    ret void
327 //
int_sasaui()328 void int_sasaui() {
329   sa = sa - ui;
330 }
331 
332 // SIGNED-LABEL: @int_usausai(
333 // SIGNED-NEXT:  entry:
334 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
335 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
336 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
337 // SIGNED-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
338 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
339 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
340 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
341 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa, align 2
342 // SIGNED-NEXT:    ret void
343 //
344 // UNSIGNED-LABEL: @int_usausai(
345 // UNSIGNED-NEXT:  entry:
346 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
347 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
348 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
349 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
350 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
351 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
352 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
353 // UNSIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa, align 2
354 // UNSIGNED-NEXT:    ret void
355 //
int_usausai()356 void int_usausai() {
357   usa = usa - i;
358 }
359 
360 // SIGNED-LABEL: @int_usausaui(
361 // SIGNED-NEXT:  entry:
362 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
363 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ui, align 4
364 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
365 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
366 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
367 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
368 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
369 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa, align 2
370 // SIGNED-NEXT:    ret void
371 //
372 // UNSIGNED-LABEL: @int_usausaui(
373 // UNSIGNED-NEXT:  entry:
374 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
375 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @ui, align 4
376 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
377 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i39
378 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
379 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
380 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
381 // UNSIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa, align 2
382 // UNSIGNED-NEXT:    ret void
383 //
int_usausaui()384 void int_usausaui() {
385   usa = usa - ui;
386 }
387 
388 // CHECK-LABEL: @int_lflfui(
389 // CHECK-NEXT:  entry:
390 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @lf, align 4
391 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @ui, align 4
392 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
393 // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i64
394 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE1]], 31
395 // CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[RESIZE]], [[UPSCALE]]
396 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i64 [[TMP2]] to i32
397 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @lf, align 4
398 // CHECK-NEXT:    ret void
399 //
int_lflfui()400 void int_lflfui() {
401   lf = lf - ui;
402 }
403 
404 // CHECK-LABEL: @int_aab(
405 // CHECK-NEXT:  entry:
406 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
407 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @b, align 1
408 // CHECK-NEXT:    [[TOBOOL:%.*]] = trunc i8 [[TMP1]] to i1
409 // CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
410 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
411 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[CONV]] to i47
412 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
413 // CHECK-NEXT:    [[TMP2:%.*]] = sub i47 [[RESIZE]], [[UPSCALE]]
414 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
415 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
416 // CHECK-NEXT:    ret void
417 //
int_aab()418 void int_aab() {
419   a = a - b;
420 }
421 
422 
423 // CHECK-LABEL: @sat_sassasas(
424 // CHECK-NEXT:  entry:
425 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa, align 2
426 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @sa_sat, align 2
427 // CHECK-NEXT:    [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
428 // CHECK-NEXT:    store i16 [[TMP2]], i16* @sa_sat, align 2
429 // CHECK-NEXT:    ret void
430 //
sat_sassasas()431 void sat_sassasas() {
432   sa_sat = sa - sa_sat;
433 }
434 
435 // SIGNED-LABEL: @sat_usasusausas(
436 // SIGNED-NEXT:  entry:
437 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
438 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
439 // SIGNED-NEXT:    [[TMP2:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
440 // SIGNED-NEXT:    store i16 [[TMP2]], i16* @usa_sat, align 2
441 // SIGNED-NEXT:    ret void
442 //
443 // UNSIGNED-LABEL: @sat_usasusausas(
444 // UNSIGNED-NEXT:  entry:
445 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa, align 2
446 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
447 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
448 // UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[TMP2]], 0
449 // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i16 0, i16 [[TMP2]]
450 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = trunc i16 [[SATMIN]] to i15
451 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i15 [[RESIZE]] to i16
452 // UNSIGNED-NEXT:    store i16 [[RESIZE1]], i16* @usa_sat, align 2
453 // UNSIGNED-NEXT:    ret void
454 //
sat_usasusausas()455 void sat_usasusausas() {
456   usa_sat = usa - usa_sat;
457 }
458 
459 // SIGNED-LABEL: @sat_uasuausas(
460 // SIGNED-NEXT:  entry:
461 // SIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @ua, align 4
462 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
463 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
464 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
465 // SIGNED-NEXT:    [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]])
466 // SIGNED-NEXT:    store i32 [[TMP2]], i32* @ua_sat, align 4
467 // SIGNED-NEXT:    ret void
468 //
469 // UNSIGNED-LABEL: @sat_uasuausas(
470 // UNSIGNED-NEXT:  entry:
471 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @ua, align 4
472 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
473 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
474 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
475 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]])
476 // UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 0
477 // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i32 0, i32 [[TMP2]]
478 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = trunc i32 [[SATMIN]] to i31
479 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = zext i31 [[RESIZE1]] to i32
480 // UNSIGNED-NEXT:    store i32 [[RESIZE2]], i32* @ua_sat, align 4
481 // UNSIGNED-NEXT:    ret void
482 //
sat_uasuausas()483 void sat_uasuausas() {
484   ua_sat = ua - usa_sat;
485 }
486 
487 // CHECK-LABEL: @sat_sassasi(
488 // CHECK-NEXT:  entry:
489 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
490 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
491 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
492 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
493 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
494 // CHECK-NEXT:    [[TMP2:%.*]] = call i39 @llvm.ssub.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
495 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
496 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
497 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], -32768
498 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i39 -32768, i39 [[SATMAX]]
499 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
500 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @sa_sat, align 2
501 // CHECK-NEXT:    ret void
502 //
sat_sassasi()503 void sat_sassasi() {
504   sa_sat = sa_sat - i;
505 }
506 
507 // CHECK-LABEL: @sat_sassasui(
508 // CHECK-NEXT:  entry:
509 // CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
510 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @ui, align 4
511 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
512 // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
513 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
514 // CHECK-NEXT:    [[TMP2:%.*]] = call i40 @llvm.ssub.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
515 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 32767
516 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i40 32767, i40 [[TMP2]]
517 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], -32768
518 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i40 -32768, i40 [[SATMAX]]
519 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
520 // CHECK-NEXT:    store i16 [[RESIZE2]], i16* @sa_sat, align 2
521 // CHECK-NEXT:    ret void
522 //
sat_sassasui()523 void sat_sassasui() {
524   sa_sat = sa_sat - ui;
525 }
526 
527 // SIGNED-LABEL: @sat_ufsufsufs(
528 // SIGNED-NEXT:  entry:
529 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
530 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
531 // SIGNED-NEXT:    [[TMP2:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
532 // SIGNED-NEXT:    store i16 [[TMP2]], i16* @uf_sat, align 2
533 // SIGNED-NEXT:    ret void
534 //
535 // UNSIGNED-LABEL: @sat_ufsufsufs(
536 // UNSIGNED-NEXT:  entry:
537 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
538 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
539 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
540 // UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[TMP2]], 0
541 // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i16 0, i16 [[TMP2]]
542 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = trunc i16 [[SATMIN]] to i15
543 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i15 [[RESIZE]] to i16
544 // UNSIGNED-NEXT:    store i16 [[RESIZE1]], i16* @uf_sat, align 2
545 // UNSIGNED-NEXT:    ret void
546 //
sat_ufsufsufs()547 void sat_ufsufsufs() {
548   uf_sat = uf_sat - uf_sat;
549 }
550 
551 // SIGNED-LABEL: @sat_usasusasi(
552 // SIGNED-NEXT:  entry:
553 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
554 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
555 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
556 // SIGNED-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
557 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
558 // SIGNED-NEXT:    [[TMP2:%.*]] = call i40 @llvm.ssub.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
559 // SIGNED-NEXT:    [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 65535
560 // SIGNED-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i40 65535, i40 [[TMP2]]
561 // SIGNED-NEXT:    [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], 0
562 // SIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i40 0, i40 [[SATMAX]]
563 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
564 // SIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa_sat, align 2
565 // SIGNED-NEXT:    ret void
566 //
567 // UNSIGNED-LABEL: @sat_usasusasi(
568 // UNSIGNED-NEXT:  entry:
569 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
570 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
571 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
572 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
573 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
574 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i39 @llvm.ssub.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
575 // UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
576 // UNSIGNED-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
577 // UNSIGNED-NEXT:    [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], 0
578 // UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i39 0, i39 [[SATMAX]]
579 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
580 // UNSIGNED-NEXT:    store i16 [[RESIZE2]], i16* @usa_sat, align 2
581 // UNSIGNED-NEXT:    ret void
582 //
sat_usasusasi()583 void sat_usasusasi() {
584   usa_sat = usa_sat - i;
585 }
586