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