xref: /llvm-project/clang/test/CodeGen/builtins-overflow.c (revision 8799ebbc1f03a348f732fc14242ad4c395076bcc)
1 // Test CodeGen for Security Check Overflow Builtins.
2 // rdar://13421498
3 
4 // RUN: %clang_cc1 -triple "i686-unknown-unknown"   -emit-llvm -x c %s -o - | FileCheck %s
5 // RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
6 // RUN: %clang_cc1 -triple "x86_64-mingw32"         -emit-llvm -x c %s -o - | FileCheck %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 
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 
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(_ExtInt(31) x, _ExtInt(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   _ExtInt(31) r;
53   if (__builtin_add_overflow(x, y, &r))
54     overflowed();
55   return r;
56 }
57 
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 
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(_ExtInt(31) x, _ExtInt(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   _ExtInt(31) r;
95   if (__builtin_sub_overflow(x, y, &r))
96     overflowed();
97   return r;
98 }
99 
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 
114 int test_mul_overflow_int_int_int(int x, int y) {
115   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_int_int_int
116   // CHECK-NOT: ext
117   // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
118   // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
119   // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
120   // CHECK: store i32 [[Q]], i32*
121   // CHECK: br i1 [[C]]
122   int r;
123   if (__builtin_mul_overflow(x, y, &r))
124     overflowed();
125   return r;
126 }
127 
128 int test_mul_overflow_xint31_xint31_xint31(_ExtInt(31) x, _ExtInt(31) y) {
129   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint31_xint31_xint31({{.+}})
130   // CHECK-NOT: ext
131   // CHECK: [[S:%.+]] = call { i31, i1 } @llvm.smul.with.overflow.i31(i31 %{{.+}}, i31 %{{.+}})
132   // CHECK-DAG: [[C:%.+]] = extractvalue { i31, i1 } [[S]], 1
133   // CHECK-DAG: [[Q:%.+]] = extractvalue { i31, i1 } [[S]], 0
134   // CHECK: store i31 [[Q]], i31*
135   // CHECK: br i1 [[C]]
136   _ExtInt(31) r;
137   if (__builtin_mul_overflow(x, y, &r))
138     overflowed();
139   return r;
140 }
141 
142 int test_mul_overflow_xint127_xint127_xint127(_ExtInt(127) x, _ExtInt(127) y) {
143   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint127_xint127_xint127({{.+}})
144   // CHECK-NOT: ext
145   // CHECK: [[S:%.+]] = call { i127, i1 } @llvm.smul.with.overflow.i127(i127 %{{.+}}, i127 %{{.+}})
146   // CHECK-DAG: [[C:%.+]] = extractvalue { i127, i1 } [[S]], 1
147   // CHECK-DAG: [[Q:%.+]] = extractvalue { i127, i1 } [[S]], 0
148   // CHECK: store i127 [[Q]], i127*
149   // CHECK: br i1 [[C]]
150   _ExtInt(127) r;
151   if (__builtin_mul_overflow(x, y, &r))
152     overflowed();
153   return r;
154 }
155 
156 int test_mul_overflow_xint128_xint128_xint128(_ExtInt(128) x, _ExtInt(128) y) {
157   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_xint128_xint128_xint128({{.+}})
158   // CHECK-NOT: ext
159   // CHECK: [[S:%.+]] = call { i128, i1 } @llvm.smul.with.overflow.i128(i128 %{{.+}}, i128 %{{.+}})
160   // CHECK-DAG: [[C:%.+]] = extractvalue { i128, i1 } [[S]], 1
161   // CHECK-DAG: [[Q:%.+]] = extractvalue { i128, i1 } [[S]], 0
162   // CHECK: store i128 [[Q]], i128*
163   // CHECK: br i1 [[C]]
164   _ExtInt(128) r;
165   if (__builtin_mul_overflow(x, y, &r))
166     overflowed();
167   return r;
168 }
169 
170 int test_add_overflow_uint_int_int(unsigned x, int y) {
171   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_int_int
172   // CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
173   // CHECK: [[YE:%.+]] = sext i32 %{{.+}} to i33
174   // CHECK: [[S:%.+]] = call { i33, i1 } @llvm.sadd.with.overflow.i33(i33 [[XE]], i33 [[YE]])
175   // CHECK-DAG: [[Q:%.+]] = extractvalue { i33, i1 } [[S]], 0
176   // CHECK-DAG: [[C1:%.+]] = extractvalue { i33, i1 } [[S]], 1
177   // CHECK: [[QT:%.+]] = trunc i33 [[Q]] to i32
178   // CHECK: [[QTE:%.+]] = sext i32 [[QT]] to i33
179   // CHECK: [[C2:%.+]] = icmp ne i33 [[Q]], [[QTE]]
180   // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
181   // CHECK: store i32 [[QT]], i32*
182   // CHECK: br i1 [[C3]]
183   int r;
184   if (__builtin_add_overflow(x, y, &r))
185     overflowed();
186   return r;
187 }
188 
189 _Bool test_add_overflow_uint_uint_bool(unsigned x, unsigned y) {
190   // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_uint_uint_bool
191   // CHECK-NOT: ext
192   // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
193   // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
194   // CHECK-DAG: [[C1:%.+]] = extractvalue { i32, i1 } [[S]], 1
195   // CHECK: [[QT:%.+]] = trunc i32 [[Q]] to i1
196   // CHECK: [[QTE:%.+]] = zext i1 [[QT]] to i32
197   // CHECK: [[C2:%.+]] = icmp ne i32 [[Q]], [[QTE]]
198   // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
199   // CHECK: [[QT2:%.+]] = zext i1 [[QT]] to i8
200   // CHECK: store i8 [[QT2]], i8*
201   // CHECK: br i1 [[C3]]
202   _Bool r;
203   if (__builtin_add_overflow(x, y, &r))
204     overflowed();
205   return r;
206 }
207 
208 unsigned test_add_overflow_bool_bool_uint(_Bool x, _Bool y) {
209   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_bool_bool_uint
210   // CHECK: [[XE:%.+]] = zext i1 %{{.+}} to i32
211   // CHECK: [[YE:%.+]] = zext i1 %{{.+}} to i32
212   // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[XE]], i32 [[YE]])
213   // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
214   // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
215   // CHECK: store i32 [[Q]], i32*
216   // CHECK: br i1 [[C]]
217   unsigned r;
218   if (__builtin_add_overflow(x, y, &r))
219     overflowed();
220   return r;
221 }
222 
223 _Bool test_add_overflow_bool_bool_bool(_Bool x, _Bool y) {
224   // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_bool_bool_bool
225   // CHECK: [[S:%.+]] = call { i1, i1 } @llvm.uadd.with.overflow.i1(i1 %{{.+}}, i1 %{{.+}})
226   // CHECK-DAG: [[Q:%.+]] = extractvalue { i1, i1 } [[S]], 0
227   // CHECK-DAG: [[C:%.+]] = extractvalue { i1, i1 } [[S]], 1
228   // CHECK: [[QT2:%.+]] = zext i1 [[Q]] to i8
229   // CHECK: store i8 [[QT2]], i8*
230   // CHECK: br i1 [[C]]
231   _Bool r;
232   if (__builtin_add_overflow(x, y, &r))
233     overflowed();
234   return r;
235 }
236 
237 int test_add_overflow_volatile(int x, int y) {
238   // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_volatile
239   // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
240   // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
241   // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
242   // CHECK: store volatile i32 [[Q]], i32*
243   // CHECK: br i1 [[C]]
244   volatile int result;
245   if (__builtin_add_overflow(x, y, &result))
246     overflowed();
247   return result;
248 }
249 
250 unsigned test_uadd_overflow(unsigned x, unsigned y) {
251 // CHECK: @test_uadd_overflow
252 // CHECK: %{{.+}} = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
253   unsigned result;
254   if (__builtin_uadd_overflow(x, y, &result))
255     return UnsignedErrorCode;
256   return result;
257 }
258 
259 unsigned long test_uaddl_overflow(unsigned long x, unsigned long y) {
260 // CHECK: @test_uaddl_overflow([[UL:i32|i64]] %x
261 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
262   unsigned long result;
263   if (__builtin_uaddl_overflow(x, y, &result))
264     return UnsignedLongErrorCode;
265   return result;
266 }
267 
268 unsigned long long test_uaddll_overflow(unsigned long long x, unsigned long long y) {
269 // CHECK: @test_uaddll_overflow
270 // CHECK: %{{.+}} = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
271   unsigned long long result;
272   if (__builtin_uaddll_overflow(x, y, &result))
273     return UnsignedLongLongErrorCode;
274   return result;
275 }
276 
277 unsigned test_usub_overflow(unsigned x, unsigned y) {
278 // CHECK: @test_usub_overflow
279 // CHECK: %{{.+}} = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
280   unsigned result;
281   if (__builtin_usub_overflow(x, y, &result))
282     return UnsignedErrorCode;
283   return result;
284 }
285 
286 unsigned long test_usubl_overflow(unsigned long x, unsigned long y) {
287 // CHECK: @test_usubl_overflow([[UL:i32|i64]] %x
288 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
289   unsigned long result;
290   if (__builtin_usubl_overflow(x, y, &result))
291     return UnsignedLongErrorCode;
292   return result;
293 }
294 
295 unsigned long long test_usubll_overflow(unsigned long long x, unsigned long long y) {
296 // CHECK: @test_usubll_overflow
297 // CHECK: %{{.+}} = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
298   unsigned long long result;
299   if (__builtin_usubll_overflow(x, y, &result))
300     return UnsignedLongLongErrorCode;
301   return result;
302 }
303 
304 unsigned test_umul_overflow(unsigned x, unsigned y) {
305 // CHECK: @test_umul_overflow
306 // CHECK: %{{.+}} = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
307   unsigned result;
308   if (__builtin_umul_overflow(x, y, &result))
309     return UnsignedErrorCode;
310   return result;
311 }
312 
313 unsigned long test_umull_overflow(unsigned long x, unsigned long y) {
314 // CHECK: @test_umull_overflow([[UL:i32|i64]] %x
315 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.umul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
316   unsigned long result;
317   if (__builtin_umull_overflow(x, y, &result))
318     return UnsignedLongErrorCode;
319   return result;
320 }
321 
322 unsigned long long test_umulll_overflow(unsigned long long x, unsigned long long y) {
323 // CHECK: @test_umulll_overflow
324 // CHECK: %{{.+}} = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
325   unsigned long long result;
326   if (__builtin_umulll_overflow(x, y, &result))
327     return UnsignedLongLongErrorCode;
328   return result;
329 }
330 
331 int test_sadd_overflow(int x, int y) {
332 // CHECK: @test_sadd_overflow
333 // CHECK: %{{.+}} = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
334   int result;
335   if (__builtin_sadd_overflow(x, y, &result))
336     return IntErrorCode;
337   return result;
338 }
339 
340 long test_saddl_overflow(long x, long y) {
341 // CHECK: @test_saddl_overflow([[UL:i32|i64]] %x
342 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.sadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
343   long result;
344   if (__builtin_saddl_overflow(x, y, &result))
345     return LongErrorCode;
346   return result;
347 }
348 
349 long long test_saddll_overflow(long long x, long long y) {
350 // CHECK: @test_saddll_overflow
351 // CHECK: %{{.+}} = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
352   long long result;
353   if (__builtin_saddll_overflow(x, y, &result))
354     return LongLongErrorCode;
355   return result;
356 }
357 
358 int test_ssub_overflow(int x, int y) {
359 // CHECK: @test_ssub_overflow
360 // CHECK: %{{.+}} = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
361   int result;
362   if (__builtin_ssub_overflow(x, y, &result))
363     return IntErrorCode;
364   return result;
365 }
366 
367 long test_ssubl_overflow(long x, long y) {
368 // CHECK: @test_ssubl_overflow([[UL:i32|i64]] %x
369 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.ssub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
370   long result;
371   if (__builtin_ssubl_overflow(x, y, &result))
372     return LongErrorCode;
373   return result;
374 }
375 
376 long long test_ssubll_overflow(long long x, long long y) {
377 // CHECK: @test_ssubll_overflow
378 // CHECK: %{{.+}} = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
379   long long result;
380   if (__builtin_ssubll_overflow(x, y, &result))
381     return LongLongErrorCode;
382   return result;
383 }
384 
385 int test_smul_overflow(int x, int y) {
386 // CHECK: @test_smul_overflow
387 // CHECK: %{{.+}} = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
388   int result;
389   if (__builtin_smul_overflow(x, y, &result))
390     return IntErrorCode;
391   return result;
392 }
393 
394 long test_smull_overflow(long x, long y) {
395 // CHECK: @test_smull_overflow([[UL:i32|i64]] %x
396 // CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.smul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
397   long result;
398   if (__builtin_smull_overflow(x, y, &result))
399     return LongErrorCode;
400   return result;
401 }
402 
403 long long test_smulll_overflow(long long x, long long y) {
404 // CHECK: @test_smulll_overflow
405 // CHECK: %{{.+}} = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
406   long long result;
407   if (__builtin_smulll_overflow(x, y, &result))
408     return LongLongErrorCode;
409   return result;
410 }
411 
412 int test_mixed_sign_mul_overflow_sext_signed_op(int x, unsigned long long y) {
413 // CHECK: @test_mixed_sign_mul_overflow_sext_signed_op
414 // CHECK: [[SignedOp:%.*]] = sext i32 %0 to i64
415 // CHECK: [[IsNeg:%.*]] = icmp slt i64 [[SignedOp]], 0
416   int result;
417   if (__builtin_mul_overflow(x, y, &result))
418     return LongErrorCode;
419   return result;
420 }
421 
422 int test_mixed_sign_mul_overflow_zext_unsigned_op(long long x, unsigned y) {
423 // CHECK: @test_mixed_sign_mul_overflow_zext_unsigned_op
424 // CHECK: [[UnsignedOp:%.*]] = zext i32 %1 to i64
425 // CHECK: [[IsNeg:%.*]] = icmp slt i64 %0, 0
426 // CHECK: @llvm.umul.with.overflow.i64({{.*}}, i64 [[UnsignedOp]])
427   int result;
428   if (__builtin_mul_overflow(x, y, &result))
429     return LongErrorCode;
430   return result;
431 }
432 
433 int test_mixed_sign_mull_overflow(int x, unsigned y) {
434 // CHECK: @test_mixed_sign_mull_overflow
435 // CHECK:       [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
436 // CHECK-NEXT:  [[Signed:%.*]] = sub i32 0, [[Op1]]
437 // CHECK-NEXT:  [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
438 // CHECK-NEXT:  call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
439 // CHECK-NEXT:  [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
440 // CHECK-NEXT:  [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
441 // CHECK-NEXT:  [[IsNegZext:%.*]] = zext i1 [[IsNeg]] to i32
442 // CHECK-NEXT:  [[MaxResult:%.*]] = add i32 2147483647, [[IsNegZext]]
443 // CHECK-NEXT:  [[SignedOFlow:%.*]] = icmp ugt i32 [[UnsignedResult]], [[MaxResult]]
444 // CHECK-NEXT:  [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[SignedOFlow]]
445 // CHECK-NEXT:  [[NegativeResult:%.*]] = sub i32 0, [[UnsignedResult]]
446 // CHECK-NEXT:  [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegativeResult]], i32 [[UnsignedResult]]
447 // CHECK-NEXT:  store i32 [[Result]], i32* %{{.*}}, align 4
448 // CHECK:       br i1 [[OFlow]]
449 
450   int result;
451   if (__builtin_mul_overflow(x, y, &result))
452     return LongErrorCode;
453   return result;
454 }
455 
456 int test_mixed_sign_mull_overflow_unsigned(int x, unsigned y) {
457 // CHECK: @test_mixed_sign_mull_overflow_unsigned
458 // CHECK:       [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
459 // CHECK-NEXT:  [[Signed:%.*]] = sub i32 0, [[Op1]]
460 // CHECK-NEXT:  [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
461 // CHECK-NEXT:  call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
462 // CHECK-NEXT:  [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
463 // CHECK-NEXT:  [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
464 // CHECK-NEXT:  [[NotNull:%.*]] = icmp ne i32 [[UnsignedResult]], 0
465 // CHECK-NEXT:  [[Underflow:%.*]] = and i1 [[IsNeg]], [[NotNull]]
466 // CHECK-NEXT:  [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[Underflow]]
467 // CHECK-NEXT:  [[NegatedResult:%.*]] = sub i32 0, [[UnsignedResult]]
468 // CHECK-NEXT:  [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegatedResult]], i32 [[UnsignedResult]]
469 // CHECK-NEXT:  store i32 [[Result]], i32* %{{.*}}, align 4
470 // CHECK:       br i1 [[OFlow]]
471 
472   unsigned result;
473   if (__builtin_mul_overflow(x, y, &result))
474     return LongErrorCode;
475   return result;
476 }
477 
478 int test_mixed_sign_mull_overflow_swapped(int x, unsigned y) {
479 // CHECK: @test_mixed_sign_mull_overflow_swapped
480 // CHECK:  call { i32, i1 } @llvm.umul.with.overflow.i32
481 // CHECK:  add i32 2147483647
482   int result;
483   if (__builtin_mul_overflow(y, x, &result))
484     return LongErrorCode;
485   return result;
486 }
487 
488 long long test_mixed_sign_mulll_overflow(long long x, unsigned long long y) {
489 // CHECK: @test_mixed_sign_mulll_overflow
490 // CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
491 // CHECK:  add i64 92233720368547
492   long long result;
493   if (__builtin_mul_overflow(x, y, &result))
494     return LongLongErrorCode;
495   return result;
496 }
497 
498 long long test_mixed_sign_mulll_overflow_swapped(long long x, unsigned long long y) {
499 // CHECK: @test_mixed_sign_mulll_overflow_swapped
500 // CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
501 // CHECK:  add i64 92233720368547
502   long long result;
503   if (__builtin_mul_overflow(y, x, &result))
504     return LongLongErrorCode;
505   return result;
506 }
507 
508 long long test_mixed_sign_mulll_overflow_trunc_signed(long long x, unsigned long long y) {
509 // CHECK: @test_mixed_sign_mulll_overflow_trunc_signed
510 // CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
511 // CHECK:  add i64 2147483647
512 // CHECK:  trunc
513 // CHECK:  store
514   int result;
515   if (__builtin_mul_overflow(y, x, &result))
516     return LongLongErrorCode;
517   return result;
518 }
519 
520 long long test_mixed_sign_mulll_overflow_trunc_unsigned(long long x, unsigned long long y) {
521 // CHECK: @test_mixed_sign_mulll_overflow_trunc_unsigned
522 // CHECK:       call { i64, i1 } @llvm.umul.with.overflow.i64
523 // CHECK:       [[NON_ZERO:%.*]] = icmp ne i64 [[UNSIGNED_RESULT:%.*]], 0
524 // CHECK-NEXT:  [[UNDERFLOW:%.*]] = and i1 {{.*}}, [[NON_ZERO]]
525 // CHECK-NEXT:  [[OVERFLOW_PRE_TRUNC:%.*]] = or i1 {{.*}}, [[UNDERFLOW]]
526 // CHECK-NEXT:  [[TRUNC_OVERFLOW:%.*]] = icmp ugt i64 [[UNSIGNED_RESULT]], 4294967295
527 // CHECK-NEXT:  [[OVERFLOW:%.*]] = or i1 [[OVERFLOW_PRE_TRUNC]], [[TRUNC_OVERFLOW]]
528 // CHECK-NEXT:  [[NEGATED:%.*]] = sub i64 0, [[UNSIGNED_RESULT]]
529 // CHECK-NEXT:  [[RESULT:%.*]] = select i1 {{.*}}, i64 [[NEGATED]], i64 [[UNSIGNED_RESULT]]
530 // CHECK-NEXT:  trunc i64 [[RESULT]] to i32
531 // CHECK-NEXT:  store
532   unsigned result;
533   if (__builtin_mul_overflow(y, x, &result))
534     return LongLongErrorCode;
535   return result;
536 }
537 
538 long long test_mixed_sign_mul_overflow_extend_signed(int x, unsigned y) {
539 // CHECK: @test_mixed_sign_mul_overflow_extend_signed
540 // CHECK:  call { i64, i1 } @llvm.smul.with.overflow.i64
541   long long result;
542   if (__builtin_mul_overflow(y, x, &result))
543     return LongLongErrorCode;
544   return result;
545 }
546 
547 long long test_mixed_sign_mul_overflow_extend_unsigned(int x, unsigned y) {
548 // CHECK: @test_mixed_sign_mul_overflow_extend_unsigned
549 // CHECK:  call { i65, i1 } @llvm.smul.with.overflow.i65
550   unsigned long long result;
551   if (__builtin_mul_overflow(y, x, &result))
552     return LongLongErrorCode;
553   return result;
554 }
555