Clang Project

clang_source_code/test/Frontend/fixed_point_add.c
1// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
2// 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
3
4// Addition between different fixed point types
5short _Accum sa_const = 1.0hk + 2.0hk;  // CHECK-DAG: @sa_const  = {{.*}}global i16 384, align 2
6_Accum a_const = 1.0hk + 2.0k;          // CHECK-DAG: @a_const   = {{.*}}global i32 98304, align 4
7long _Accum la_const = 1.0hk + 2.0lk;   // CHECK-DAG: @la_const  = {{.*}}global i64 6442450944, align 8
8short _Accum sa_const2 = 0.5hr + 2.0hk; // CHECK-DAG: @sa_const2  = {{.*}}global i16 320, align 2
9short _Accum sa_const3 = 0.5r + 2.0hk;  // CHECK-DAG: @sa_const3  = {{.*}}global i16 320, align 2
10short _Accum sa_const4 = 0.5lr + 2.0hk; // CHECK-DAG: @sa_const4  = {{.*}}global i16 320, align 2
11
12// Unsigned addition
13unsigned short _Accum usa_const = 1.0uhk + 2.0uhk;
14// CHECK-SIGNED-DAG:   @usa_const = {{.*}}global i16 768, align 2
15// CHECK-UNSIGNED-DAG: @usa_const = {{.*}}global i16 384, align 2
16
17// Unsigned + signed
18short _Accum sa_const5 = 1.0uhk + 2.0hk;
19// CHECK-DAG: @sa_const5 = {{.*}}global i16 384, align 2
20
21// Addition with negative number
22short _Accum sa_const6 = 0.5hr + (-2.0hk);
23// CHECK-DAG: @sa_const6 = {{.*}}global i16 -192, align 2
24
25// Int addition
26unsigned short _Accum usa_const2 = 2 + 0.5uhk;
27// CHECK-SIGNED-DAG:   @usa_const2 = {{.*}}global i16 640, align 2
28// CHECK-UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 320, align 2
29short _Accum sa_const7 = 2 + (-0.5hk);   // CHECK-DAG: @sa_const7 = {{.*}}global i16 192, align 2
30short _Accum sa_const8 = 257 + (-2.0hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 32640, align 2
31long _Fract lf_const = -0.5lr + 1;       // CHECK-DAG: @lf_const  = {{.*}}global i32 1073741824, align 4
32
33// Saturated addition
34_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk + 128.0hk;
35// CHECK-DAG: @sat_sa_const = {{.*}}global i16 32767, align 2
36_Sat unsigned short _Accum sat_usa_const = (_Sat unsigned short _Accum)128.0uhk + 128.0uhk;
37// CHECK-SIGNED-DAG:   @sat_usa_const = {{.*}}global i16 65535, align 2
38// CHECK-UNSIGNED-DAG: @sat_usa_const = {{.*}}global i16 32767, align 2
39_Sat short _Accum sat_sa_const2 = (_Sat short _Accum)128.0hk + 128;
40// CHECK-DAG: @sat_sa_const2 = {{.*}}global i16 32767, align 2
41_Sat unsigned short _Accum sat_usa_const2 = (_Sat unsigned short _Accum)128.0uhk + 128;
42// CHECK-SIGNED-DAG:   @sat_usa_const2 = {{.*}}global i16 65535, align 2
43// CHECK-UNSIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 32767, align 2
44_Sat unsigned short _Accum sat_usa_const3 = (_Sat unsigned short _Accum)0.5uhk + (-2);
45// CHECK-DAG:   @sat_usa_const3 = {{.*}}global i16 0, align 2
46
47void SignedAddition() {
48  // CHECK-LABEL: SignedAddition
49  short _Accum sa;
50  _Accum a, b, c, d;
51  long _Accum la;
52  unsigned short _Accum usa;
53  unsigned _Accum ua;
54  unsigned long _Accum ula;
55
56  short _Fract sf;
57  _Fract f;
58  long _Fract lf;
59  unsigned short _Fract usf;
60  unsigned _Fract uf;
61  unsigned long _Fract ulf;
62
63  // Same type
64  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
65  // CHECK-NEXT: [[SA2:%[0-9]+]] = load i16, i16* %sa, align 2
66  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[SA2]]
67  // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
68  sa = sa + sa;
69
70  // To larger scale and larger width
71  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
72  // CHECK-NEXT: [[A:%[0-9]+]] = load i32, i32* %a, align 4
73  // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
74  // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
75  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[SA]], [[A]]
76  // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
77  a = sa + a;
78
79  // To same scale and smaller width
80  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
81  // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
82  // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i16
83  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[EXT_SF]]
84  // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
85  sa = sa + sf;
86
87  // To smaller scale and same width.
88  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
89  // CHECK-NEXT: [[F:%[0-9]+]] = load i16, i16* %f, align 2
90  // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i24
91  // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i24 [[EXT_SA]], 8
92  // CHECK-NEXT: [[EXT_F:%[a-z0-9]+]] = sext i16 [[F]] to i24
93  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[SA]], [[EXT_F]]
94  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8
95  // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
96  // CHECK-NEXT: store i16 [[TRUNC_RES]], i16* %sa, align 2
97  sa = sa + f;
98
99  // To smaller scale and smaller width
100  // CHECK:      [[A:%[0-9]+]] = load i32, i32* %a, align 4
101  // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
102  // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i32
103  // CHECK-NEXT: [[SF:%[a-z0-9]+]] = shl i32 [[EXT_SF]], 8
104  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[A]], [[SF]]
105  // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
106  a = a + sf;
107
108  // To larger scale and same width
109  // CHECK:      [[A:%[0-9]+]] = load i32, i32* %a, align 4
110  // CHECK-NEXT: [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
111  // CHECK-NEXT: [[EXT_A:%[a-z0-9]+]] = sext i32 [[A]] to i48
112  // CHECK-NEXT: [[A:%[a-z0-9]+]] = shl i48 [[EXT_A]], 16
113  // CHECK-NEXT: [[EXT_LF:%[a-z0-9]+]] = sext i32 [[LF]] to i48
114  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i48 [[A]], [[EXT_LF]]
115  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i48 [[SUM]], 16
116  // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i48 [[RES]] to i32
117  // CHECK-NEXT: store i32 [[TRUNC_RES]], i32* %a, align 4
118  a = a + lf;
119
120  // With corresponding unsigned type
121  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
122  // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
123  // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
124  // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
125  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i17
126  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i17 [[SA]], [[USA_EXT]]
127  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
128  // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
129  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[USA]]
130  // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
131  sa = sa + usa;
132
133  // With unsigned of larger scale
134  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
135  // CHECK-NEXT: [[USA:%[0-9]+]] = load i32, i32* %ua, align 4
136  // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i33
137  // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i33 [[SA_EXT]], 9
138  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i32 [[USA]] to i33
139  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i33 [[SA]], [[USA_EXT]]
140  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i33 [[SUM]], 1
141  // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i33 [[RESULT]] to i32
142  // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
143  // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
144  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i32 [[SA]], [[USA]]
145  // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
146  a = sa + ua;
147
148  // With unsigned of smaller width
149  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
150  // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
151  // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
152  // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
153  // SIGNED-NEXT: [[USF_EXT:%[a-z0-9]+]] = zext i8 [[USF]] to i17
154  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i17 [[SA]], [[USF_EXT]]
155  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
156  // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
157  // UNSIGNED-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
158  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[EXT_USF]]
159  // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
160  sa = sa + usf;
161
162  // With unsigned of larger width and smaller scale
163  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
164  // CHECK-NEXT: [[ULF:%[0-9]+]] = load i32, i32* %ulf, align 4
165  // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i41
166  // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i41 [[SA_EXT]], 25
167  // SIGNED-NEXT: [[ULF_EXT:%[a-z0-9]+]] = zext i32 [[ULF]] to i41
168  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i41 [[SA]], [[ULF_EXT]]
169  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i41 [[SUM]], 25
170  // SIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i41 [[RESULT]] to i16
171  // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i40
172  // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i40 [[EXT_SA]], 24
173  // UNSIGNED-NEXT: [[EXT_ULF:%[a-z0-9]+]] = zext i32 [[ULF]] to i40
174  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[SA]], [[EXT_ULF]]
175  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i40 [[SUM]], 24
176  // UNSIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i40 [[RES]] to i16
177  // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %sa, align 2
178  sa = sa + ulf;
179
180  // Chained additions of the same signed type should result in the same
181  // semantics width.
182  // CHECK:      [[A:%[0-9]+]] = load i32, i32* %a, align 4
183  // CHECK-NEXT: [[B:%[0-9]+]] = load i32, i32* %b, align 4
184  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[A]], [[B]]
185  // CHECK-NEXT: [[C:%[0-9]+]] = load i32, i32* %c, align 4
186  // CHECK-NEXT: [[SUM2:%[0-9]+]] = add i32 [[SUM]], [[C]]
187  // CHECK-NEXT: [[D:%[0-9]+]] = load i32, i32* %d, align 4
188  // CHECK-NEXT: [[SUM3:%[0-9]+]] = add i32 [[SUM2]], [[D]]
189  // CHECK-NEXT: store i32 [[SUM3]], i32* %a, align 4
190  a = a + b + c + d;
191}
192
193void UnsignedAddition() {
194  // CHECK-LABEL: UnsignedAddition
195  unsigned short _Accum usa;
196  unsigned _Accum ua;
197  unsigned long _Accum ula;
198
199  unsigned short _Fract usf;
200  unsigned _Fract uf;
201  unsigned long _Fract ulf;
202
203  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
204  // CHECK-NEXT: [[USA2:%[0-9]+]] = load i16, i16* %usa, align 2
205  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[USA]], [[USA2]]
206  // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
207  usa = usa + usa;
208
209  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
210  // CHECK-NEXT: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
211  // CHECK-NEXT: [[EXT_USA:%[a-z0-9]+]] = zext i16 [[USA]] to i32
212  // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[EXT_USA]], 8
213  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[USA]], [[UA]]
214  // CHECK-NEXT: store i32 [[SUM]], i32* %ua, align 4
215  ua = usa + ua;
216
217  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
218  // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
219  // CHECK-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
220  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[USA]], [[EXT_USF]]
221  // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
222  usa = usa + usf;
223
224  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
225  // CHECK-NEXT: [[UF:%[0-9]+]] = load i16, i16* %uf, align 2
226  // CHECK-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i24
227  // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8
228  // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24
229  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[USA]], [[UF_EXT]]
230  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
231  // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
232  // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2
233  usa = usa + uf;
234}
235
236void IntAddition() {
237  // CHECK-LABEL: IntAddition
238  short _Accum sa;
239  _Accum a;
240  unsigned short _Accum usa;
241  _Sat short _Accum sa_sat;
242  int i;
243  unsigned int ui;
244  long _Fract lf;
245  _Bool b;
246
247  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
248  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
249  // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i39
250  // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
251  // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
252  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i39 [[SA_EXT]], [[I]]
253  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
254  // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
255  sa = sa + i;
256
257  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
258  // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
259  // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i40
260  // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i40
261  // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i40 [[UI_EXT]], 7
262  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i40 [[SA_EXT]], [[UI]]
263  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
264  // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
265  sa = sa + ui;
266
267  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
268  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
269  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
270  // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i40
271  // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
272  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
273  // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
274  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
275  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
276  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
277  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]]
278  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
279  // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
280  usa = usa + i;
281
282  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
283  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
284  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
285  // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
286  // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
287  // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
288  // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
289  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
290  // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
291  // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
292  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]]
293  // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
294  // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
295  usa = usa + ui;
296
297  // CHECK:      [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
298  // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
299  // CHECK-NEXT: [[LF_EXT:%[a-z0-9]+]] = sext i32 [[LF]] to i64
300  // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i64
301  // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i64 [[UI_EXT]], 31
302  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i64 [[LF_EXT]], [[UI]]
303  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i64 [[SUM]] to i32
304  // CHECK-NEXT: store i32 [[RES]], i32* %lf, align 4
305  lf = lf + ui;
306
307  // CHECK:      [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
308  // CHECK-NEXT: [[BOOL:%[0-9]+]] = load i8, i8* %b, align 1
309  // CHECK-NEXT: [[AS_BOOL:%[a-z0-9]+]] = trunc i8 [[BOOL]] to i1
310  // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = zext i1 [[AS_BOOL]] to i32
311  // CHECK-NEXT: [[ACCUM_EXT:%[a-z0-9]+]] = sext i32 [[ACCUM]] to i47
312  // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = sext i32 [[BOOL_EXT]] to i47
313  // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = shl i47 [[BOOL]], 15
314  // CHECK-NEXT: [[SUM:%[0-9]+]] = add i47 [[ACCUM_EXT]], [[BOOL_EXT]]
315  // CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i47 [[SUM]] to i32
316  // CHECK-NEXT: store i32 [[RESULT]], i32* %a, align 4
317  a = a + b;
318}
319
320void SaturatedAddition() {
321  // CHECK-LABEL: SaturatedAddition
322  short _Accum sa;
323  _Accum a;
324  long _Accum la;
325  unsigned short _Accum usa;
326  unsigned _Accum ua;
327  unsigned long _Accum ula;
328
329  _Sat short _Accum sa_sat;
330  _Sat _Accum a_sat;
331  _Sat long _Accum la_sat;
332  _Sat unsigned short _Accum usa_sat;
333  _Sat unsigned _Accum ua_sat;
334  _Sat unsigned long _Accum ula_sat;
335  _Sat unsigned _Fract uf_sat;
336
337  int i;
338  unsigned int ui;
339
340  // CHECK:      [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
341  // CHECK-NEXT: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
342  // CHECK-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.sadd.sat.i16(i16 [[SA]], i16
343  // [[SA_SAT]])
344  // CHECK-NEXT: store i16 [[SUM]], i16* %sa_sat, align 2
345  sa_sat = sa + sa_sat;
346
347  // CHECK:      [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
348  // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
349  // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
350  // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
351  // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
352  // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
353  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]])
354  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
355  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
356  usa_sat = usa + usa_sat;
357
358  // CHECK:      [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
359  // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2
360  // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32
361  // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
362  // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.uadd.sat.i32(i32 [[UA]], i32 [[USA]])
363  // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
364  // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
365  // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
366  // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
367  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.uadd.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]])
368  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
369  // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
370  ua_sat = ua + usa_sat;
371
372  // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
373  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
374  // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i39
375  // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
376  // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
377  // CHECK-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.sadd.sat.i39(i39 [[SA_SAT_EXT]], i39 [[I]])
378  // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
379  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
380  // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RES]], -32768
381  // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 -32768, i39 [[RES]]
382  // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i39 [[RES2]] to i16
383  // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
384  sa_sat = sa_sat + i;
385
386  // CHECK:      [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
387  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
388  // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i40
389  // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
390  // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7
391  // CHECK-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.sadd.sat.i40(i40 [[SA_SAT_EXT]], i40 [[I]])
392  // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 32767
393  // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 32767, i40 [[SUM]]
394  // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RES]], -32768
395  // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 -32768, i40 [[RES]]
396  // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i40 [[RES2]] to i16
397  // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
398  sa_sat = sa_sat + ui;
399
400  // CHECK:      [[UF_SAT:%[0-9]+]] = load i16, i16* %uf_sat, align 2
401  // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
402  // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
403  // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
404  // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
405  // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
406  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]])
407  // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
408  // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
409  uf_sat = uf_sat + uf_sat;
410
411  // CHECK:      [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
412  // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
413  // SIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i40
414  // SIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i40
415  // SIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i40 [[I_RESIZE]], 8
416  // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.uadd.sat.i40(i40 [[USA_SAT_RESIZE]], i40 [[I_UPSCALE]])
417  // SIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 65535
418  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 65535, i40 [[SUM]]
419  // SIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RESULT]], 0
420  // SIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 0, i40 [[RESULT]]
421  // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i40 [[RESULT2]] to i16
422  // UNSIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i39
423  // UNSIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i39
424  // UNSIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i39 [[I_RESIZE]], 7
425  // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.uadd.sat.i39(i39 [[USA_SAT_RESIZE]], i39 [[I_UPSCALE]])
426  // UNSIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
427  // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
428  // UNSIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RESULT]], 0
429  // UNSIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 0, i39 [[RESULT]]
430  // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i39 [[RESULT2]] to i16
431  // CHECK-NEXT: store i16 [[RESULT]], i16* %usa_sat, align 2
432  usa_sat = usa_sat + i;
433}
434