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 |
5 | short _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 |
7 | long _Accum la_const = 1.0hk + 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 6442450944, align 8 |
8 | short _Accum sa_const2 = 0.5hr + 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 320, align 2 |
9 | short _Accum sa_const3 = 0.5r + 2.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 320, align 2 |
10 | short _Accum sa_const4 = 0.5lr + 2.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 320, align 2 |
11 | |
12 | // Unsigned addition |
13 | unsigned 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 |
18 | short _Accum sa_const5 = 1.0uhk + 2.0hk; |
19 | // CHECK-DAG: @sa_const5 = {{.*}}global i16 384, align 2 |
20 | |
21 | // Addition with negative number |
22 | short _Accum sa_const6 = 0.5hr + (-2.0hk); |
23 | // CHECK-DAG: @sa_const6 = {{.*}}global i16 -192, align 2 |
24 | |
25 | // Int addition |
26 | unsigned 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 |
29 | short _Accum sa_const7 = 2 + (-0.5hk); // CHECK-DAG: @sa_const7 = {{.*}}global i16 192, align 2 |
30 | short _Accum sa_const8 = 257 + (-2.0hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 32640, align 2 |
31 | long _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 | |
47 | void 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 | |
193 | void 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 | |
236 | void 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 | |
320 | void 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 | |