1 // Test CodeGen for Security Check Overflow Builtins.
2 // rdar://13421498
3
4 // RUN: %clang_cc1 -no-opaque-pointers -triple "i686-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck -DLONG_TYPE=i32 -DLONG_MAX=2147483647 %s
5 // RUN: %clang_cc1 -no-opaque-pointers -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck -DLONG_TYPE=i64 -DLONG_MAX=9223372036854775807 %s
6 // RUN: %clang_cc1 -no-opaque-pointers -triple "x86_64-mingw32" -emit-llvm -x c %s -o - | FileCheck -DLONG_TYPE=i32 -DLONG_MAX=2147483647 %s
7
8 extern unsigned UnsignedErrorCode;
9 extern unsigned long UnsignedLongErrorCode;
10 extern unsigned long long UnsignedLongLongErrorCode;
11 extern int IntErrorCode;
12 extern long LongErrorCode;
13 extern long long LongLongErrorCode;
14 void overflowed(void);
15
test_add_overflow_uint_uint_uint(unsigned x,unsigned y)16 unsigned test_add_overflow_uint_uint_uint(unsigned x, unsigned y) {
17 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_uint_uint
18 // CHECK-NOT: ext
19 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
20 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
21 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
22 // CHECK: store i32 [[Q]], i32*
23 // CHECK: br i1 [[C]]
24 unsigned r;
25 if (__builtin_add_overflow(x, y, &r))
26 overflowed();
27 return r;
28 }
29
test_add_overflow_int_int_int(int x,int y)30 int test_add_overflow_int_int_int(int x, int y) {
31 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_int_int_int
32 // CHECK-NOT: ext
33 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
34 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
35 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
36 // CHECK: store i32 [[Q]], i32*
37 // CHECK: br i1 [[C]]
38 int r;
39 if (__builtin_add_overflow(x, y, &r))
40 overflowed();
41 return r;
42 }
43
44 int test_add_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y) {
45 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_xint31_xint31_xint31({{.+}})
46 // CHECK-NOT: ext
47 // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.sadd.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
48 // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
49 // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
50 // CHECK: store i31 [[Q]], i31*
51 // CHECK: br i1 [[C]]
52 _BitInt(31) r;
53 if (__builtin_add_overflow(x, y, &r))
54 overflowed();
55 return r;
56 }
57
test_sub_overflow_uint_uint_uint(unsigned x,unsigned y)58 unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
59 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_uint_uint_uint
60 // CHECK-NOT: ext
61 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
62 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
63 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
64 // CHECK: store i32 [[Q]], i32*
65 // CHECK: br i1 [[C]]
66 unsigned r;
67 if (__builtin_sub_overflow(x, y, &r))
68 overflowed();
69 return r;
70 }
71
test_sub_overflow_int_int_int(int x,int y)72 int test_sub_overflow_int_int_int(int x, int y) {
73 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_int_int_int
74 // CHECK-NOT: ext
75 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
76 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
77 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
78 // CHECK: store i32 [[Q]], i32*
79 // CHECK: br i1 [[C]]
80 int r;
81 if (__builtin_sub_overflow(x, y, &r))
82 overflowed();
83 return r;
84 }
85
86 int test_sub_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y) {
87 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_xint31_xint31_xint31({{.+}})
88 // CHECK-NOT: ext
89 // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.ssub.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
90 // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
91 // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
92 // CHECK: store i31 [[Q]], i31*
93 // CHECK: br i1 [[C]]
94 _BitInt(31) r;
95 if (__builtin_sub_overflow(x, y, &r))
96 overflowed();
97 return r;
98 }
99
test_mul_overflow_uint_uint_uint(unsigned x,unsigned y)100 unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
101 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_uint
102 // CHECK-NOT: ext
103 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
104 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
105 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
106 // CHECK: store i32 [[Q]], i32*
107 // CHECK: br i1 [[C]]
108 unsigned r;
109 if (__builtin_mul_overflow(x, y, &r))
110 overflowed();
111 return r;
112 }
113
test_mul_overflow_uint_uint_int(unsigned x,unsigned y)114 int test_mul_overflow_uint_uint_int(unsigned x, unsigned y) {
115 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_int
116 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
117 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
118 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
119 // CHECK: [[C1:%.+]] = icmp ugt i32 [[Q]], 2147483647
120 // CHECK: [[C2:%.+]] = or i1 [[C]], [[C1]]
121 // CHECK: store i32 [[Q]], i32*
122 // CHECK: br i1 [[C2]]
123 int r;
124 if (__builtin_mul_overflow(x, y, &r))
125 overflowed();
126 return r;
127 }
128
test_mul_overflow_uint_uint_int_volatile(unsigned x,unsigned y)129 int test_mul_overflow_uint_uint_int_volatile(unsigned x, unsigned y) {
130 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_int_volatile
131 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
132 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
133 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
134 // CHECK: [[C1:%.+]] = icmp ugt i32 [[Q]], 2147483647
135 // CHECK: [[C2:%.+]] = or i1 [[C]], [[C1]]
136 // CHECK: store volatile i32 [[Q]], i32*
137 // CHECK: br i1 [[C2]]
138 volatile int r;
139 if (__builtin_mul_overflow(x, y, &r))
140 overflowed();
141 return r;
142 }
143
test_mul_overflow_ulong_ulong_long(unsigned long x,unsigned long y)144 long test_mul_overflow_ulong_ulong_long(unsigned long x, unsigned long y) {
145 // CHECK-LABEL: @test_mul_overflow_ulong_ulong_long
146 // CHECK: [[S:%.+]] = call { [[LONG_TYPE]], i1 } @llvm.umul.with.overflow.[[LONG_TYPE]]([[LONG_TYPE]] %{{.+}}, [[LONG_TYPE]] %{{.+}})
147 // CHECK-DAG: [[Q:%.+]] = extractvalue { [[LONG_TYPE]], i1 } [[S]], 0
148 // CHECK-DAG: [[C:%.+]] = extractvalue { [[LONG_TYPE]], i1 } [[S]], 1
149 // CHECK: [[C1:%.+]] = icmp ugt [[LONG_TYPE]] [[Q]], [[LONG_MAX]]
150 // CHECK: [[C2:%.+]] = or i1 [[C]], [[C1]]
151 // LONG64: store [[LONG_TYPE]] [[Q]], [[LONG_TYPE]]*
152 // LONG64: br i1 [[C2]]
153 long r;
154 if (__builtin_mul_overflow(x, y, &r))
155 overflowed();
156 return r;
157 }
158
test_mul_overflow_int_int_int(int x,int y)159 int test_mul_overflow_int_int_int(int x, int y) {
160 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_int_int_int
161 // CHECK-NOT: ext
162 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
163 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
164 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
165 // CHECK: store i32 [[Q]], i32*
166 // CHECK: br i1 [[C]]
167 int r;
168 if (__builtin_mul_overflow(x, y, &r))
169 overflowed();
170 return r;
171 }
172
173 int test_mul_overflow_xint31_xint31_xint31(_BitInt(31) x, _BitInt(31) y) {
174 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint31_xint31_xint31({{.+}})
175 // CHECK-NOT: ext
176 // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
177 // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
178 // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
179 // CHECK: store i31 [[Q]], i31*
180 // CHECK: br i1 [[C]]
181 _BitInt(31) r;
182 if (__builtin_mul_overflow(x, y, &r))
183 overflowed();
184 return r;
185 }
186
187 int test_mul_overflow_xint127_xint127_xint127(_BitInt(127) x, _BitInt(127) y) {
188 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint127_xint127_xint127({{.+}})
189 // CHECK-NOT: ext
190 // CHECK: [[S:%.+]] = call { i127, i1 } @llvm.smul.with.overflow.i127(i127 %{{.+}}, i127 %{{.+}})
191 // CHECK-DAG: [[C:%.+]] = extractvalue { i127, i1 } [[S]], 1
192 // CHECK-DAG: [[Q:%.+]] = extractvalue { i127, i1 } [[S]], 0
193 // CHECK: store i127 [[Q]], i127*
194 // CHECK: br i1 [[C]]
195 _BitInt(127) r;
196 if (__builtin_mul_overflow(x, y, &r))
197 overflowed();
198 return r;
199 }
200
201 int test_mul_overflow_xint128_xint128_xint128(_BitInt(128) x, _BitInt(128) y) {
202 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint128_xint128_xint128({{.+}})
203 // CHECK-NOT: ext
204 // CHECK: [[S:%.+]] = call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %{{.+}}, i128 %{{.+}})
205 // CHECK-DAG: [[C:%.+]] = extractvalue { i128, i1 } [[S]], 1
206 // CHECK-DAG: [[Q:%.+]] = extractvalue { i128, i1 } [[S]], 0
207 // CHECK: store i128 [[Q]], i128*
208 // CHECK: br i1 [[C]]
209 _BitInt(128) r;
210 if (__builtin_mul_overflow(x, y, &r))
211 overflowed();
212 return r;
213 }
214
test_add_overflow_uint_int_int(unsigned x,int y)215 int test_add_overflow_uint_int_int(unsigned x, int y) {
216 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_int_int
217 // CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
218 // CHECK: [[YE:%.+]] = sext i32 %{{.+}} to i33
219 // CHECK: [[S:%.+]] = call { i33, i1 } @llvm.sadd.with.overflow.i33(i33 [[XE]], i33 [[YE]])
220 // CHECK-DAG: [[Q:%.+]] = extractvalue { i33, i1 } [[S]], 0
221 // CHECK-DAG: [[C1:%.+]] = extractvalue { i33, i1 } [[S]], 1
222 // CHECK: [[QT:%.+]] = trunc i33 [[Q]] to i32
223 // CHECK: [[QTE:%.+]] = sext i32 [[QT]] to i33
224 // CHECK: [[C2:%.+]] = icmp ne i33 [[Q]], [[QTE]]
225 // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
226 // CHECK: store i32 [[QT]], i32*
227 // CHECK: br i1 [[C3]]
228 int r;
229 if (__builtin_add_overflow(x, y, &r))
230 overflowed();
231 return r;
232 }
233
test_add_overflow_uint_uint_bool(unsigned x,unsigned y)234 _Bool test_add_overflow_uint_uint_bool(unsigned x, unsigned y) {
235 // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_uint_uint_bool
236 // CHECK-NOT: ext
237 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
238 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
239 // CHECK-DAG: [[C1:%.+]] = extractvalue { i32, i1 } [[S]], 1
240 // CHECK: [[QT:%.+]] = trunc i32 [[Q]] to i1
241 // CHECK: [[QTE:%.+]] = zext i1 [[QT]] to i32
242 // CHECK: [[C2:%.+]] = icmp ne i32 [[Q]], [[QTE]]
243 // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
244 // CHECK: [[QT2:%.+]] = zext i1 [[QT]] to i8
245 // CHECK: store i8 [[QT2]], i8*
246 // CHECK: br i1 [[C3]]
247 _Bool r;
248 if (__builtin_add_overflow(x, y, &r))
249 overflowed();
250 return r;
251 }
252
test_add_overflow_bool_bool_uint(_Bool x,_Bool y)253 unsigned test_add_overflow_bool_bool_uint(_Bool x, _Bool y) {
254 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_bool_bool_uint
255 // CHECK: [[XE:%.+]] = zext i1 %{{.+}} to i32
256 // CHECK: [[YE:%.+]] = zext i1 %{{.+}} to i32
257 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[XE]], i32 [[YE]])
258 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
259 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
260 // CHECK: store i32 [[Q]], i32*
261 // CHECK: br i1 [[C]]
262 unsigned r;
263 if (__builtin_add_overflow(x, y, &r))
264 overflowed();
265 return r;
266 }
267
test_add_overflow_bool_bool_bool(_Bool x,_Bool y)268 _Bool test_add_overflow_bool_bool_bool(_Bool x, _Bool y) {
269 // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_bool_bool_bool
270 // CHECK: [[S:%.+]] = call { i1, i1 } @llvm.uadd.with.overflow.i1(i1 %{{.+}}, i1 %{{.+}})
271 // CHECK-DAG: [[Q:%.+]] = extractvalue { i1, i1 } [[S]], 0
272 // CHECK-DAG: [[C:%.+]] = extractvalue { i1, i1 } [[S]], 1
273 // CHECK: [[QT2:%.+]] = zext i1 [[Q]] to i8
274 // CHECK: store i8 [[QT2]], i8*
275 // CHECK: br i1 [[C]]
276 _Bool r;
277 if (__builtin_add_overflow(x, y, &r))
278 overflowed();
279 return r;
280 }
281
test_add_overflow_volatile(int x,int y)282 int test_add_overflow_volatile(int x, int y) {
283 // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_volatile
284 // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
285 // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
286 // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
287 // CHECK: store volatile i32 [[Q]], i32*
288 // CHECK: br i1 [[C]]
289 volatile int result;
290 if (__builtin_add_overflow(x, y, &result))
291 overflowed();
292 return result;
293 }
294
test_uadd_overflow(unsigned x,unsigned y)295 unsigned test_uadd_overflow(unsigned x, unsigned y) {
296 // CHECK: @test_uadd_overflow
297 // CHECK: %{{.+}} = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
298 unsigned result;
299 if (__builtin_uadd_overflow(x, y, &result))
300 return UnsignedErrorCode;
301 return result;
302 }
303
test_uaddl_overflow(unsigned long x,unsigned long y)304 unsigned long test_uaddl_overflow(unsigned long x, unsigned long y) {
305 // CHECK: @test_uaddl_overflow([[UL:i32|i64]] noundef %x
306 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
307 unsigned long result;
308 if (__builtin_uaddl_overflow(x, y, &result))
309 return UnsignedLongErrorCode;
310 return result;
311 }
312
test_uaddll_overflow(unsigned long long x,unsigned long long y)313 unsigned long long test_uaddll_overflow(unsigned long long x, unsigned long long y) {
314 // CHECK: @test_uaddll_overflow
315 // CHECK: %{{.+}} = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
316 unsigned long long result;
317 if (__builtin_uaddll_overflow(x, y, &result))
318 return UnsignedLongLongErrorCode;
319 return result;
320 }
321
test_usub_overflow(unsigned x,unsigned y)322 unsigned test_usub_overflow(unsigned x, unsigned y) {
323 // CHECK: @test_usub_overflow
324 // CHECK: %{{.+}} = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
325 unsigned result;
326 if (__builtin_usub_overflow(x, y, &result))
327 return UnsignedErrorCode;
328 return result;
329 }
330
test_usubl_overflow(unsigned long x,unsigned long y)331 unsigned long test_usubl_overflow(unsigned long x, unsigned long y) {
332 // CHECK: @test_usubl_overflow([[UL:i32|i64]] noundef %x
333 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
334 unsigned long result;
335 if (__builtin_usubl_overflow(x, y, &result))
336 return UnsignedLongErrorCode;
337 return result;
338 }
339
test_usubll_overflow(unsigned long long x,unsigned long long y)340 unsigned long long test_usubll_overflow(unsigned long long x, unsigned long long y) {
341 // CHECK: @test_usubll_overflow
342 // CHECK: %{{.+}} = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
343 unsigned long long result;
344 if (__builtin_usubll_overflow(x, y, &result))
345 return UnsignedLongLongErrorCode;
346 return result;
347 }
348
test_umul_overflow(unsigned x,unsigned y)349 unsigned test_umul_overflow(unsigned x, unsigned y) {
350 // CHECK: @test_umul_overflow
351 // CHECK: %{{.+}} = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
352 unsigned result;
353 if (__builtin_umul_overflow(x, y, &result))
354 return UnsignedErrorCode;
355 return result;
356 }
357
test_umull_overflow(unsigned long x,unsigned long y)358 unsigned long test_umull_overflow(unsigned long x, unsigned long y) {
359 // CHECK: @test_umull_overflow([[UL:i32|i64]] noundef %x
360 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.umul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
361 unsigned long result;
362 if (__builtin_umull_overflow(x, y, &result))
363 return UnsignedLongErrorCode;
364 return result;
365 }
366
test_umulll_overflow(unsigned long long x,unsigned long long y)367 unsigned long long test_umulll_overflow(unsigned long long x, unsigned long long y) {
368 // CHECK: @test_umulll_overflow
369 // CHECK: %{{.+}} = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
370 unsigned long long result;
371 if (__builtin_umulll_overflow(x, y, &result))
372 return UnsignedLongLongErrorCode;
373 return result;
374 }
375
test_sadd_overflow(int x,int y)376 int test_sadd_overflow(int x, int y) {
377 // CHECK: @test_sadd_overflow
378 // CHECK: %{{.+}} = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
379 int result;
380 if (__builtin_sadd_overflow(x, y, &result))
381 return IntErrorCode;
382 return result;
383 }
384
test_saddl_overflow(long x,long y)385 long test_saddl_overflow(long x, long y) {
386 // CHECK: @test_saddl_overflow([[UL:i32|i64]] noundef %x
387 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.sadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
388 long result;
389 if (__builtin_saddl_overflow(x, y, &result))
390 return LongErrorCode;
391 return result;
392 }
393
test_saddll_overflow(long long x,long long y)394 long long test_saddll_overflow(long long x, long long y) {
395 // CHECK: @test_saddll_overflow
396 // CHECK: %{{.+}} = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
397 long long result;
398 if (__builtin_saddll_overflow(x, y, &result))
399 return LongLongErrorCode;
400 return result;
401 }
402
test_ssub_overflow(int x,int y)403 int test_ssub_overflow(int x, int y) {
404 // CHECK: @test_ssub_overflow
405 // CHECK: %{{.+}} = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
406 int result;
407 if (__builtin_ssub_overflow(x, y, &result))
408 return IntErrorCode;
409 return result;
410 }
411
test_ssubl_overflow(long x,long y)412 long test_ssubl_overflow(long x, long y) {
413 // CHECK: @test_ssubl_overflow([[UL:i32|i64]] noundef %x
414 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.ssub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
415 long result;
416 if (__builtin_ssubl_overflow(x, y, &result))
417 return LongErrorCode;
418 return result;
419 }
420
test_ssubll_overflow(long long x,long long y)421 long long test_ssubll_overflow(long long x, long long y) {
422 // CHECK: @test_ssubll_overflow
423 // CHECK: %{{.+}} = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
424 long long result;
425 if (__builtin_ssubll_overflow(x, y, &result))
426 return LongLongErrorCode;
427 return result;
428 }
429
test_smul_overflow(int x,int y)430 int test_smul_overflow(int x, int y) {
431 // CHECK: @test_smul_overflow
432 // CHECK: %{{.+}} = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
433 int result;
434 if (__builtin_smul_overflow(x, y, &result))
435 return IntErrorCode;
436 return result;
437 }
438
test_smull_overflow(long x,long y)439 long test_smull_overflow(long x, long y) {
440 // CHECK: @test_smull_overflow([[UL:i32|i64]] noundef %x
441 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.smul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
442 long result;
443 if (__builtin_smull_overflow(x, y, &result))
444 return LongErrorCode;
445 return result;
446 }
447
test_smulll_overflow(long long x,long long y)448 long long test_smulll_overflow(long long x, long long y) {
449 // CHECK: @test_smulll_overflow
450 // CHECK: %{{.+}} = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
451 long long result;
452 if (__builtin_smulll_overflow(x, y, &result))
453 return LongLongErrorCode;
454 return result;
455 }
456
test_mixed_sign_mul_overflow_sext_signed_op(int x,unsigned long long y)457 int test_mixed_sign_mul_overflow_sext_signed_op(int x, unsigned long long y) {
458 // CHECK: @test_mixed_sign_mul_overflow_sext_signed_op
459 // CHECK: [[SignedOp:%.*]] = sext i32 %0 to i64
460 // CHECK: [[IsNeg:%.*]] = icmp slt i64 [[SignedOp]], 0
461 int result;
462 if (__builtin_mul_overflow(x, y, &result))
463 return LongErrorCode;
464 return result;
465 }
466
test_mixed_sign_mul_overflow_zext_unsigned_op(long long x,unsigned y)467 int test_mixed_sign_mul_overflow_zext_unsigned_op(long long x, unsigned y) {
468 // CHECK: @test_mixed_sign_mul_overflow_zext_unsigned_op
469 // CHECK: [[UnsignedOp:%.*]] = zext i32 %1 to i64
470 // CHECK: [[IsNeg:%.*]] = icmp slt i64 %0, 0
471 // CHECK: @llvm.umul.with.overflow.i64({{.*}}, i64 [[UnsignedOp]])
472 int result;
473 if (__builtin_mul_overflow(x, y, &result))
474 return LongErrorCode;
475 return result;
476 }
477
test_mixed_sign_mull_overflow(int x,unsigned y)478 int test_mixed_sign_mull_overflow(int x, unsigned y) {
479 // CHECK: @test_mixed_sign_mull_overflow
480 // CHECK: [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
481 // CHECK-NEXT: [[Signed:%.*]] = sub i32 0, [[Op1]]
482 // CHECK-NEXT: [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
483 // CHECK-NEXT: call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
484 // CHECK-NEXT: [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
485 // CHECK-NEXT: [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
486 // CHECK-NEXT: [[IsNegZext:%.*]] = zext i1 [[IsNeg]] to i32
487 // CHECK-NEXT: [[MaxResult:%.*]] = add i32 2147483647, [[IsNegZext]]
488 // CHECK-NEXT: [[SignedOFlow:%.*]] = icmp ugt i32 [[UnsignedResult]], [[MaxResult]]
489 // CHECK-NEXT: [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[SignedOFlow]]
490 // CHECK-NEXT: [[NegativeResult:%.*]] = sub i32 0, [[UnsignedResult]]
491 // CHECK-NEXT: [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegativeResult]], i32 [[UnsignedResult]]
492 // CHECK-NEXT: store i32 [[Result]], i32* %{{.*}}, align 4
493 // CHECK: br i1 [[OFlow]]
494
495 int result;
496 if (__builtin_mul_overflow(x, y, &result))
497 return LongErrorCode;
498 return result;
499 }
500
test_mixed_sign_mull_overflow_unsigned(int x,unsigned y)501 int test_mixed_sign_mull_overflow_unsigned(int x, unsigned y) {
502 // CHECK: @test_mixed_sign_mull_overflow_unsigned
503 // CHECK: [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
504 // CHECK-NEXT: [[Signed:%.*]] = sub i32 0, [[Op1]]
505 // CHECK-NEXT: [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
506 // CHECK-NEXT: call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
507 // CHECK-NEXT: [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
508 // CHECK-NEXT: [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
509 // CHECK-NEXT: [[NotNull:%.*]] = icmp ne i32 [[UnsignedResult]], 0
510 // CHECK-NEXT: [[Underflow:%.*]] = and i1 [[IsNeg]], [[NotNull]]
511 // CHECK-NEXT: [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[Underflow]]
512 // CHECK-NEXT: [[NegatedResult:%.*]] = sub i32 0, [[UnsignedResult]]
513 // CHECK-NEXT: [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegatedResult]], i32 [[UnsignedResult]]
514 // CHECK-NEXT: store i32 [[Result]], i32* %{{.*}}, align 4
515 // CHECK: br i1 [[OFlow]]
516
517 unsigned result;
518 if (__builtin_mul_overflow(x, y, &result))
519 return LongErrorCode;
520 return result;
521 }
522
test_mixed_sign_mull_overflow_swapped(int x,unsigned y)523 int test_mixed_sign_mull_overflow_swapped(int x, unsigned y) {
524 // CHECK: @test_mixed_sign_mull_overflow_swapped
525 // CHECK: call { i32, i1 } @llvm.umul.with.overflow.i32
526 // CHECK: add i32 2147483647
527 int result;
528 if (__builtin_mul_overflow(y, x, &result))
529 return LongErrorCode;
530 return result;
531 }
532
test_mixed_sign_mulll_overflow(long long x,unsigned long long y)533 long long test_mixed_sign_mulll_overflow(long long x, unsigned long long y) {
534 // CHECK: @test_mixed_sign_mulll_overflow
535 // CHECK: call { i64, i1 } @llvm.umul.with.overflow.i64
536 // CHECK: add i64 92233720368547
537 long long result;
538 if (__builtin_mul_overflow(x, y, &result))
539 return LongLongErrorCode;
540 return result;
541 }
542
test_mixed_sign_mulll_overflow_swapped(long long x,unsigned long long y)543 long long test_mixed_sign_mulll_overflow_swapped(long long x, unsigned long long y) {
544 // CHECK: @test_mixed_sign_mulll_overflow_swapped
545 // CHECK: call { i64, i1 } @llvm.umul.with.overflow.i64
546 // CHECK: add i64 92233720368547
547 long long result;
548 if (__builtin_mul_overflow(y, x, &result))
549 return LongLongErrorCode;
550 return result;
551 }
552
test_mixed_sign_mulll_overflow_trunc_signed(long long x,unsigned long long y)553 long long test_mixed_sign_mulll_overflow_trunc_signed(long long x, unsigned long long y) {
554 // CHECK: @test_mixed_sign_mulll_overflow_trunc_signed
555 // CHECK: call { i64, i1 } @llvm.umul.with.overflow.i64
556 // CHECK: add i64 2147483647
557 // CHECK: trunc
558 // CHECK: store
559 int result;
560 if (__builtin_mul_overflow(y, x, &result))
561 return LongLongErrorCode;
562 return result;
563 }
564
test_mixed_sign_mulll_overflow_trunc_unsigned(long long x,unsigned long long y)565 long long test_mixed_sign_mulll_overflow_trunc_unsigned(long long x, unsigned long long y) {
566 // CHECK: @test_mixed_sign_mulll_overflow_trunc_unsigned
567 // CHECK: call { i64, i1 } @llvm.umul.with.overflow.i64
568 // CHECK: [[NON_ZERO:%.*]] = icmp ne i64 [[UNSIGNED_RESULT:%.*]], 0
569 // CHECK-NEXT: [[UNDERFLOW:%.*]] = and i1 {{.*}}, [[NON_ZERO]]
570 // CHECK-NEXT: [[OVERFLOW_PRE_TRUNC:%.*]] = or i1 {{.*}}, [[UNDERFLOW]]
571 // CHECK-NEXT: [[TRUNC_OVERFLOW:%.*]] = icmp ugt i64 [[UNSIGNED_RESULT]], 4294967295
572 // CHECK-NEXT: [[OVERFLOW:%.*]] = or i1 [[OVERFLOW_PRE_TRUNC]], [[TRUNC_OVERFLOW]]
573 // CHECK-NEXT: [[NEGATED:%.*]] = sub i64 0, [[UNSIGNED_RESULT]]
574 // CHECK-NEXT: [[RESULT:%.*]] = select i1 {{.*}}, i64 [[NEGATED]], i64 [[UNSIGNED_RESULT]]
575 // CHECK-NEXT: trunc i64 [[RESULT]] to i32
576 // CHECK-NEXT: store
577 unsigned result;
578 if (__builtin_mul_overflow(y, x, &result))
579 return LongLongErrorCode;
580 return result;
581 }
582
test_mixed_sign_mul_overflow_extend_signed(int x,unsigned y)583 long long test_mixed_sign_mul_overflow_extend_signed(int x, unsigned y) {
584 // CHECK: @test_mixed_sign_mul_overflow_extend_signed
585 // CHECK: call { i64, i1 } @llvm.smul.with.overflow.i64
586 long long result;
587 if (__builtin_mul_overflow(y, x, &result))
588 return LongLongErrorCode;
589 return result;
590 }
591
test_mixed_sign_mul_overflow_extend_unsigned(int x,unsigned y)592 long long test_mixed_sign_mul_overflow_extend_unsigned(int x, unsigned y) {
593 // CHECK: @test_mixed_sign_mul_overflow_extend_unsigned
594 // CHECK: call { i65, i1 } @llvm.smul.with.overflow.i65
595 unsigned long long result;
596 if (__builtin_mul_overflow(y, x, &result))
597 return LongLongErrorCode;
598 return result;
599 }
600