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 _Fract shf;
6 _Accum a;
7 unsigned _Fract uf;
8 unsigned long _Accum ula;
9 
10 _Sat short _Fract sshf;
11 _Sat _Accum sa;
12 _Sat unsigned _Fract suf;
13 _Sat unsigned long _Accum sula;
14 
15 int i;
16 unsigned int u;
17 signed char c;
18 
19 
20 // CHECK-LABEL: @add_shfa(
21 // CHECK-NEXT:  entry:
22 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
23 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @shf, align 1
24 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
25 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
26 // CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[UPSCALE]], [[TMP0]]
27 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP2]], 8
28 // CHECK-NEXT:    [[RESIZE1:%.*]] = trunc i32 [[DOWNSCALE]] to i8
29 // CHECK-NEXT:    store i8 [[RESIZE1]], i8* @shf, align 1
30 // CHECK-NEXT:    ret void
31 //
add_shfa()32 void add_shfa() {
33   shf += a;
34 }
35 
36 // SIGNED-LABEL: @add_auf(
37 // SIGNED-NEXT:  entry:
38 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
39 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
40 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
41 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
42 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
43 // SIGNED-NEXT:    [[TMP2:%.*]] = add i33 [[UPSCALE]], [[RESIZE1]]
44 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
45 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
46 // SIGNED-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
47 // SIGNED-NEXT:    ret void
48 //
49 // UNSIGNED-LABEL: @add_auf(
50 // UNSIGNED-NEXT:  entry:
51 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
52 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
53 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
54 // UNSIGNED-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], [[RESIZE]]
55 // UNSIGNED-NEXT:    store i32 [[TMP2]], i32* @a, align 4
56 // UNSIGNED-NEXT:    ret void
57 //
add_auf()58 void add_auf() {
59   a += uf;
60 }
61 
62 // CHECK-LABEL: @add_ufula(
63 // CHECK-NEXT:  entry:
64 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, i64* @ula, align 8
65 // CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf, align 2
66 // CHECK-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP1]] to i64
67 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 16
68 // CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[UPSCALE]], [[TMP0]]
69 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = lshr i64 [[TMP2]], 16
70 // CHECK-NEXT:    [[RESIZE1:%.*]] = trunc i64 [[DOWNSCALE]] to i16
71 // CHECK-NEXT:    store i16 [[RESIZE1]], i16* @uf, align 2
72 // CHECK-NEXT:    ret void
73 //
add_ufula()74 void add_ufula() {
75   uf += ula;
76 }
77 
78 // SIGNED-LABEL: @add_ulashf(
79 // SIGNED-NEXT:  entry:
80 // SIGNED-NEXT:    [[TMP0:%.*]] = load i8, i8* @shf, align 1
81 // SIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @ula, align 8
82 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i64 [[TMP1]] to i65
83 // SIGNED-NEXT:    [[RESIZE1:%.*]] = sext i8 [[TMP0]] to i65
84 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i65 [[RESIZE1]], 25
85 // SIGNED-NEXT:    [[TMP2:%.*]] = add i65 [[RESIZE]], [[UPSCALE]]
86 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i65 [[TMP2]], 1
87 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i65 [[DOWNSCALE]] to i64
88 // SIGNED-NEXT:    [[UPSCALE3:%.*]] = shl i64 [[RESIZE2]], 1
89 // SIGNED-NEXT:    store i64 [[UPSCALE3]], i64* @ula, align 8
90 // SIGNED-NEXT:    ret void
91 //
92 // UNSIGNED-LABEL: @add_ulashf(
93 // UNSIGNED-NEXT:  entry:
94 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i8, i8* @shf, align 1
95 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @ula, align 8
96 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i64
97 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 24
98 // UNSIGNED-NEXT:    [[TMP2:%.*]] = add i64 [[TMP1]], [[UPSCALE]]
99 // UNSIGNED-NEXT:    store i64 [[TMP2]], i64* @ula, align 8
100 // UNSIGNED-NEXT:    ret void
101 //
add_ulashf()102 void add_ulashf() {
103   ula += shf;
104 }
105 
106 // SIGNED-LABEL: @add_ufshf(
107 // SIGNED-NEXT:  entry:
108 // SIGNED-NEXT:    [[TMP0:%.*]] = load i8, i8* @shf, align 1
109 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf, align 2
110 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP1]] to i17
111 // SIGNED-NEXT:    [[RESIZE1:%.*]] = sext i8 [[TMP0]] to i17
112 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i17 [[RESIZE1]], 9
113 // SIGNED-NEXT:    [[TMP2:%.*]] = add i17 [[RESIZE]], [[UPSCALE]]
114 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
115 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
116 // SIGNED-NEXT:    [[UPSCALE3:%.*]] = shl i16 [[RESIZE2]], 1
117 // SIGNED-NEXT:    store i16 [[UPSCALE3]], i16* @uf, align 2
118 // SIGNED-NEXT:    ret void
119 //
120 // UNSIGNED-LABEL: @add_ufshf(
121 // UNSIGNED-NEXT:  entry:
122 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i8, i8* @shf, align 1
123 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @uf, align 2
124 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i16
125 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
126 // UNSIGNED-NEXT:    [[TMP2:%.*]] = add i16 [[TMP1]], [[UPSCALE]]
127 // UNSIGNED-NEXT:    store i16 [[TMP2]], i16* @uf, align 2
128 // UNSIGNED-NEXT:    ret void
129 //
add_ufshf()130 void add_ufshf() {
131   uf += shf;
132 }
133 
134 // CHECK-LABEL: @add_ashf(
135 // CHECK-NEXT:  entry:
136 // CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* @shf, align 1
137 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
138 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i32
139 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
140 // CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], [[UPSCALE]]
141 // CHECK-NEXT:    store i32 [[TMP2]], i32* @a, align 4
142 // CHECK-NEXT:    ret void
143 //
add_ashf()144 void add_ashf() {
145   a += shf;
146 }
147 
148 // CHECK-LABEL: @add_ai(
149 // CHECK-NEXT:  entry:
150 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
151 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
152 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
153 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
154 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
155 // CHECK-NEXT:    [[TMP2:%.*]] = add i47 [[RESIZE]], [[UPSCALE]]
156 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
157 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
158 // CHECK-NEXT:    ret void
159 //
add_ai()160 void add_ai() {
161   a += i;
162 }
163 
164 // CHECK-LABEL: @add_au(
165 // CHECK-NEXT:  entry:
166 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @u, align 4
167 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
168 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i48
169 // CHECK-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP0]] to i48
170 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i48 [[RESIZE1]], 15
171 // CHECK-NEXT:    [[TMP2:%.*]] = add i48 [[RESIZE]], [[UPSCALE]]
172 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i48 [[TMP2]] to i32
173 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
174 // CHECK-NEXT:    ret void
175 //
add_au()176 void add_au() {
177   a += u;
178 }
179 
180 // SIGNED-LABEL: @add_ulai(
181 // SIGNED-NEXT:  entry:
182 // SIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
183 // SIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @ula, align 8
184 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i64 [[TMP1]] to i65
185 // SIGNED-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i65
186 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i65 [[RESIZE1]], 32
187 // SIGNED-NEXT:    [[TMP2:%.*]] = add i65 [[RESIZE]], [[UPSCALE]]
188 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i65 [[TMP2]] to i64
189 // SIGNED-NEXT:    store i64 [[RESIZE2]], i64* @ula, align 8
190 // SIGNED-NEXT:    ret void
191 //
192 // UNSIGNED-LABEL: @add_ulai(
193 // UNSIGNED-NEXT:  entry:
194 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
195 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @ula, align 8
196 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
197 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 31
198 // UNSIGNED-NEXT:    [[TMP2:%.*]] = add i64 [[TMP1]], [[UPSCALE]]
199 // UNSIGNED-NEXT:    store i64 [[TMP2]], i64* @ula, align 8
200 // UNSIGNED-NEXT:    ret void
201 //
add_ulai()202 void add_ulai() {
203   ula += i;
204 }
205 
206 // SIGNED-LABEL: @add_iula(
207 // SIGNED-NEXT:  entry:
208 // SIGNED-NEXT:    [[TMP0:%.*]] = load i64, i64* @ula, align 8
209 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
210 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i65
211 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i65 [[RESIZE]], 32
212 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i64 [[TMP0]] to i65
213 // SIGNED-NEXT:    [[TMP2:%.*]] = add i65 [[UPSCALE]], [[RESIZE1]]
214 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i65 [[TMP2]] to i64
215 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = lshr i64 [[RESIZE2]], 32
216 // SIGNED-NEXT:    [[RESIZE3:%.*]] = trunc i64 [[DOWNSCALE]] to i32
217 // SIGNED-NEXT:    store i32 [[RESIZE3]], i32* @i, align 4
218 // SIGNED-NEXT:    ret void
219 //
220 // UNSIGNED-LABEL: @add_iula(
221 // UNSIGNED-NEXT:  entry:
222 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i64, i64* @ula, align 8
223 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @i, align 4
224 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i64
225 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 31
226 // UNSIGNED-NEXT:    [[TMP2:%.*]] = add i64 [[UPSCALE]], [[TMP0]]
227 // UNSIGNED-NEXT:    [[DOWNSCALE:%.*]] = lshr i64 [[TMP2]], 31
228 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = trunc i64 [[DOWNSCALE]] to i32
229 // UNSIGNED-NEXT:    store i32 [[RESIZE1]], i32* @i, align 4
230 // UNSIGNED-NEXT:    ret void
231 //
add_iula()232 void add_iula() {
233   i += ula;
234 }
235 
236 // CHECK-LABEL: @add_ca(
237 // CHECK-NEXT:  entry:
238 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
239 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @c, align 1
240 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
241 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
242 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
243 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
244 // CHECK-NEXT:    [[TMP2:%.*]] = add i47 [[UPSCALE]], [[RESIZE1]]
245 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
246 // CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[RESIZE2]], 0
247 // CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[RESIZE2]], 32767
248 // CHECK-NEXT:    [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP4]], i32 [[RESIZE2]]
249 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP5]], 15
250 // CHECK-NEXT:    [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
251 // CHECK-NEXT:    store i8 [[RESIZE3]], i8* @c, align 1
252 // CHECK-NEXT:    ret void
253 //
add_ca()254 void add_ca() {
255   c += a;
256 }
257 
258 // CHECK-LABEL: @add_sai(
259 // CHECK-NEXT:  entry:
260 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
261 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @sa, align 4
262 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
263 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
264 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
265 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[RESIZE]], i47 [[UPSCALE]])
266 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
267 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
268 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
269 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
270 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
271 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @sa, align 4
272 // CHECK-NEXT:    ret void
273 //
add_sai()274 void add_sai() {
275   sa += i;
276 }
277 
278 // CHECK-LABEL: @add_csa(
279 // CHECK-NEXT:  entry:
280 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @sa, align 4
281 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @c, align 1
282 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
283 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
284 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
285 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
286 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]])
287 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
288 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
289 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
290 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
291 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
292 // CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
293 // CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
294 // CHECK-NEXT:    [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
295 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
296 // CHECK-NEXT:    [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
297 // CHECK-NEXT:    store i8 [[RESIZE3]], i8* @c, align 1
298 // CHECK-NEXT:    ret void
299 //
add_csa()300 void add_csa() {
301   c += sa;
302 }
303 
304 // SIGNED-LABEL: @add_sulau(
305 // SIGNED-NEXT:  entry:
306 // SIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @u, align 4
307 // SIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @sula, align 8
308 // SIGNED-NEXT:    [[RESIZE:%.*]] = zext i32 [[TMP0]] to i64
309 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 32
310 // SIGNED-NEXT:    [[TMP2:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[TMP1]], i64 [[UPSCALE]])
311 // SIGNED-NEXT:    store i64 [[TMP2]], i64* @sula, align 8
312 // SIGNED-NEXT:    ret void
313 //
314 // UNSIGNED-LABEL: @add_sulau(
315 // UNSIGNED-NEXT:  entry:
316 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @u, align 4
317 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i64, i64* @sula, align 8
318 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = trunc i64 [[TMP1]] to i63
319 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i32 [[TMP0]] to i63
320 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i63 [[RESIZE1]], 31
321 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i63 @llvm.uadd.sat.i63(i63 [[RESIZE]], i63 [[UPSCALE]])
322 // UNSIGNED-NEXT:    [[RESIZE2:%.*]] = zext i63 [[TMP2]] to i64
323 // UNSIGNED-NEXT:    store i64 [[RESIZE2]], i64* @sula, align 8
324 // UNSIGNED-NEXT:    ret void
325 //
add_sulau()326 void add_sulau() {
327   sula += u;
328 }
329 
330 // SIGNED-LABEL: @add_sshsuf(
331 // SIGNED-NEXT:  entry:
332 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @suf, align 2
333 // SIGNED-NEXT:    [[TMP1:%.*]] = load i8, i8* @sshf, align 1
334 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP1]] to i17
335 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 9
336 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i17
337 // SIGNED-NEXT:    [[TMP2:%.*]] = call i17 @llvm.sadd.sat.i17(i17 [[UPSCALE]], i17 [[RESIZE1]])
338 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
339 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
340 // SIGNED-NEXT:    [[DOWNSCALE3:%.*]] = ashr i16 [[RESIZE2]], 8
341 // SIGNED-NEXT:    [[RESIZE4:%.*]] = trunc i16 [[DOWNSCALE3]] to i8
342 // SIGNED-NEXT:    store i8 [[RESIZE4]], i8* @sshf, align 1
343 // SIGNED-NEXT:    ret void
344 //
345 // UNSIGNED-LABEL: @add_sshsuf(
346 // UNSIGNED-NEXT:  entry:
347 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @suf, align 2
348 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i8, i8* @sshf, align 1
349 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
350 // UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
351 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[UPSCALE]], i16 [[TMP0]])
352 // UNSIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i16 [[TMP2]], 8
353 // UNSIGNED-NEXT:    [[RESIZE1:%.*]] = trunc i16 [[DOWNSCALE]] to i8
354 // UNSIGNED-NEXT:    store i8 [[RESIZE1]], i8* @sshf, align 1
355 // UNSIGNED-NEXT:    ret void
356 //
add_sshsuf()357 void add_sshsuf() {
358   sshf += suf;
359 }
360 
361 // Subtraction, multiplication and division should work about the same, so
362 // just make sure we can do them.
363 
364 // SIGNED-LABEL: @sub_auf(
365 // SIGNED-NEXT:  entry:
366 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
367 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
368 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
369 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
370 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
371 // SIGNED-NEXT:    [[TMP2:%.*]] = sub i33 [[UPSCALE]], [[RESIZE1]]
372 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
373 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
374 // SIGNED-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
375 // SIGNED-NEXT:    ret void
376 //
377 // UNSIGNED-LABEL: @sub_auf(
378 // UNSIGNED-NEXT:  entry:
379 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
380 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
381 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
382 // UNSIGNED-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP1]], [[RESIZE]]
383 // UNSIGNED-NEXT:    store i32 [[TMP2]], i32* @a, align 4
384 // UNSIGNED-NEXT:    ret void
385 //
sub_auf()386 void sub_auf() {
387   a -= uf;
388 }
389 
390 // CHECK-LABEL: @sub_ai(
391 // CHECK-NEXT:  entry:
392 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
393 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
394 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
395 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
396 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
397 // CHECK-NEXT:    [[TMP2:%.*]] = sub i47 [[RESIZE]], [[UPSCALE]]
398 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
399 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
400 // CHECK-NEXT:    ret void
401 //
sub_ai()402 void sub_ai() {
403   a -= i;
404 }
405 
406 // CHECK-LABEL: @sub_csa(
407 // CHECK-NEXT:  entry:
408 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @sa, align 4
409 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @c, align 1
410 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
411 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
412 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
413 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
414 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.ssub.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]])
415 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
416 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
417 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
418 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
419 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
420 // CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
421 // CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
422 // CHECK-NEXT:    [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
423 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
424 // CHECK-NEXT:    [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
425 // CHECK-NEXT:    store i8 [[RESIZE3]], i8* @c, align 1
426 // CHECK-NEXT:    ret void
427 //
sub_csa()428 void sub_csa() {
429   c -= sa;
430 }
431 
432 
433 // SIGNED-LABEL: @mul_auf(
434 // SIGNED-NEXT:  entry:
435 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
436 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
437 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
438 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
439 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
440 // SIGNED-NEXT:    [[TMP2:%.*]] = call i33 @llvm.smul.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
441 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
442 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
443 // SIGNED-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
444 // SIGNED-NEXT:    ret void
445 //
446 // UNSIGNED-LABEL: @mul_auf(
447 // UNSIGNED-NEXT:  entry:
448 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
449 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
450 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
451 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
452 // UNSIGNED-NEXT:    store i32 [[TMP2]], i32* @a, align 4
453 // UNSIGNED-NEXT:    ret void
454 //
mul_auf()455 void mul_auf() {
456   a *= uf;
457 }
458 
459 // CHECK-LABEL: @mul_ai(
460 // CHECK-NEXT:  entry:
461 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
462 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
463 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
464 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
465 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
466 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
467 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
468 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
469 // CHECK-NEXT:    ret void
470 //
mul_ai()471 void mul_ai() {
472   a *= i;
473 }
474 
475 // CHECK-LABEL: @mul_csa(
476 // CHECK-NEXT:  entry:
477 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @sa, align 4
478 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @c, align 1
479 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
480 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
481 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
482 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
483 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.smul.fix.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
484 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
485 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
486 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
487 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
488 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
489 // CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
490 // CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
491 // CHECK-NEXT:    [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
492 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
493 // CHECK-NEXT:    [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
494 // CHECK-NEXT:    store i8 [[RESIZE3]], i8* @c, align 1
495 // CHECK-NEXT:    ret void
496 //
mul_csa()497 void mul_csa() {
498   c *= sa;
499 }
500 
501 
502 // SIGNED-LABEL: @div_auf(
503 // SIGNED-NEXT:  entry:
504 // SIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
505 // SIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
506 // SIGNED-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
507 // SIGNED-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
508 // SIGNED-NEXT:    [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
509 // SIGNED-NEXT:    [[TMP2:%.*]] = call i33 @llvm.sdiv.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
510 // SIGNED-NEXT:    [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
511 // SIGNED-NEXT:    [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
512 // SIGNED-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
513 // SIGNED-NEXT:    ret void
514 //
515 // UNSIGNED-LABEL: @div_auf(
516 // UNSIGNED-NEXT:  entry:
517 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i16, i16* @uf, align 2
518 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
519 // UNSIGNED-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
520 // UNSIGNED-NEXT:    [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
521 // UNSIGNED-NEXT:    store i32 [[TMP2]], i32* @a, align 4
522 // UNSIGNED-NEXT:    ret void
523 //
div_auf()524 void div_auf() {
525   a /= uf;
526 }
527 
528 // CHECK-LABEL: @div_ai(
529 // CHECK-NEXT:  entry:
530 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
531 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
532 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
533 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
534 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
535 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
536 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
537 // CHECK-NEXT:    store i32 [[RESIZE2]], i32* @a, align 4
538 // CHECK-NEXT:    ret void
539 //
div_ai()540 void div_ai() {
541   a /= i;
542 }
543 
544 // CHECK-LABEL: @div_csa(
545 // CHECK-NEXT:  entry:
546 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @sa, align 4
547 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @c, align 1
548 // CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
549 // CHECK-NEXT:    [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
550 // CHECK-NEXT:    [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
551 // CHECK-NEXT:    [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
552 // CHECK-NEXT:    [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
553 // CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
554 // CHECK-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
555 // CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
556 // CHECK-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
557 // CHECK-NEXT:    [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
558 // CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
559 // CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
560 // CHECK-NEXT:    [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
561 // CHECK-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
562 // CHECK-NEXT:    [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
563 // CHECK-NEXT:    store i8 [[RESIZE3]], i8* @c, align 1
564 // CHECK-NEXT:    ret void
565 //
div_csa()566 void div_csa() {
567   c /= sa;
568 }
569 
570 
571 // CHECK-LABEL: @shft_ai(
572 // CHECK-NEXT:  entry:
573 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
574 // CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
575 // CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[TMP1]], [[TMP0]]
576 // CHECK-NEXT:    store i32 [[TMP2]], i32* @a, align 4
577 // CHECK-NEXT:    ret void
578 //
shft_ai()579 void shft_ai() {
580   a <<= i;
581 }
582 
583 // SIGNED-LABEL: @shft_sufi(
584 // SIGNED-NEXT:  entry:
585 // SIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
586 // SIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @suf, align 2
587 // SIGNED-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP0]] to i16
588 // SIGNED-NEXT:    [[TMP3:%.*]] = call i16 @llvm.ushl.sat.i16(i16 [[TMP1]], i16 [[TMP2]])
589 // SIGNED-NEXT:    store i16 [[TMP3]], i16* @suf, align 2
590 // SIGNED-NEXT:    ret void
591 //
592 // UNSIGNED-LABEL: @shft_sufi(
593 // UNSIGNED-NEXT:  entry:
594 // UNSIGNED-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
595 // UNSIGNED-NEXT:    [[TMP1:%.*]] = load i16, i16* @suf, align 2
596 // UNSIGNED-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP0]] to i16
597 // UNSIGNED-NEXT:    [[TMP3:%.*]] = call i16 @llvm.sshl.sat.i16(i16 [[TMP1]], i16 [[TMP2]])
598 // UNSIGNED-NEXT:    store i16 [[TMP3]], i16* @suf, align 2
599 // UNSIGNED-NEXT:    ret void
600 //
shft_sufi()601 void shft_sufi() {
602   suf <<= i;
603 }
604 
605 // CHECK-LABEL: @shft_ulai(
606 // CHECK-NEXT:  entry:
607 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @i, align 4
608 // CHECK-NEXT:    [[TMP1:%.*]] = load i64, i64* @ula, align 8
609 // CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[TMP0]] to i64
610 // CHECK-NEXT:    [[TMP3:%.*]] = lshr i64 [[TMP1]], [[TMP2]]
611 // CHECK-NEXT:    store i64 [[TMP3]], i64* @ula, align 8
612 // CHECK-NEXT:    ret void
613 //
shft_ulai()614 void shft_ulai() {
615   ula >>= i;
616 }
617