Clang Project

clang_source_code/test/CodeGen/builtins-overflow.c
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
8extern unsigned UnsignedErrorCode;
9extern unsigned long UnsignedLongErrorCode;
10extern unsigned long long UnsignedLongLongErrorCode;
11extern int IntErrorCode;
12extern long LongErrorCode;
13extern long long LongLongErrorCode;
14void overflowed(void);
15
16unsigned 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
30int 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
44unsigned test_sub_overflow_uint_uint_uint(unsigned x, unsigned y) {
45  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_uint_uint_uint
46  // CHECK-NOT: ext
47  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
48  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
49  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
50  // CHECK: store i32 [[Q]], i32*
51  // CHECK: br i1 [[C]]
52  unsigned r;
53  if (__builtin_sub_overflow(x, y, &r))
54    overflowed();
55  return r;
56}
57
58int test_sub_overflow_int_int_int(int x, int y) {
59  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_sub_overflow_int_int_int
60  // CHECK-NOT: ext
61  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
62  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
63  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
64  // CHECK: store i32 [[Q]], i32*
65  // CHECK: br i1 [[C]]
66  int r;
67  if (__builtin_sub_overflow(x, y, &r))
68    overflowed();
69  return r;
70}
71
72unsigned test_mul_overflow_uint_uint_uint(unsigned x, unsigned y) {
73  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_uint_uint_uint
74  // CHECK-NOT: ext
75  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
76  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
77  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
78  // CHECK: store i32 [[Q]], i32*
79  // CHECK: br i1 [[C]]
80  unsigned r;
81  if (__builtin_mul_overflow(x, y, &r))
82    overflowed();
83  return r;
84}
85
86int test_mul_overflow_int_int_int(int x, int y) {
87  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_mul_overflow_int_int_int
88  // CHECK-NOT: ext
89  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
90  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
91  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
92  // CHECK: store i32 [[Q]], i32*
93  // CHECK: br i1 [[C]]
94  int r;
95  if (__builtin_mul_overflow(x, y, &r))
96    overflowed();
97  return r;
98}
99
100int test_add_overflow_uint_int_int(unsigned x, int y) {
101  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_uint_int_int
102  // CHECK: [[XE:%.+]] = zext i32 %{{.+}} to i33
103  // CHECK: [[YE:%.+]] = sext i32 %{{.+}} to i33
104  // CHECK: [[S:%.+]] = call { i33, i1 } @llvm.sadd.with.overflow.i33(i33 [[XE]], i33 [[YE]])
105  // CHECK-DAG: [[Q:%.+]] = extractvalue { i33, i1 } [[S]], 0
106  // CHECK-DAG: [[C1:%.+]] = extractvalue { i33, i1 } [[S]], 1
107  // CHECK: [[QT:%.+]] = trunc i33 [[Q]] to i32
108  // CHECK: [[QTE:%.+]] = sext i32 [[QT]] to i33
109  // CHECK: [[C2:%.+]] = icmp ne i33 [[Q]], [[QTE]]
110  // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
111  // CHECK: store i32 [[QT]], i32*
112  // CHECK: br i1 [[C3]]
113  int r;
114  if (__builtin_add_overflow(x, y, &r))
115    overflowed();
116  return r;
117}
118
119_Bool test_add_overflow_uint_uint_bool(unsigned x, unsigned y) {
120  // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_uint_uint_bool
121  // CHECK-NOT: ext
122  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
123  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
124  // CHECK-DAG: [[C1:%.+]] = extractvalue { i32, i1 } [[S]], 1
125  // CHECK: [[QT:%.+]] = trunc i32 [[Q]] to i1
126  // CHECK: [[QTE:%.+]] = zext i1 [[QT]] to i32
127  // CHECK: [[C2:%.+]] = icmp ne i32 [[Q]], [[QTE]]
128  // CHECK: [[C3:%.+]] = or i1 [[C1]], [[C2]]
129  // CHECK: [[QT2:%.+]] = zext i1 [[QT]] to i8
130  // CHECK: store i8 [[QT2]], i8*
131  // CHECK: br i1 [[C3]]
132  _Bool r;
133  if (__builtin_add_overflow(x, y, &r))
134    overflowed();
135  return r;
136}
137
138unsigned test_add_overflow_bool_bool_uint(_Bool x, _Bool y) {
139  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_bool_bool_uint
140  // CHECK: [[XE:%.+]] = zext i1 %{{.+}} to i32
141  // CHECK: [[YE:%.+]] = zext i1 %{{.+}} to i32
142  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[XE]], i32 [[YE]])
143  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
144  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
145  // CHECK: store i32 [[Q]], i32*
146  // CHECK: br i1 [[C]]
147  unsigned r;
148  if (__builtin_add_overflow(x, y, &r))
149    overflowed();
150  return r;
151}
152
153_Bool test_add_overflow_bool_bool_bool(_Bool x, _Bool y) {
154  // CHECK-LABEL: define {{.*}} i1 @test_add_overflow_bool_bool_bool
155  // CHECK: [[S:%.+]] = call { i1, i1 } @llvm.uadd.with.overflow.i1(i1 %{{.+}}, i1 %{{.+}})
156  // CHECK-DAG: [[Q:%.+]] = extractvalue { i1, i1 } [[S]], 0
157  // CHECK-DAG: [[C:%.+]] = extractvalue { i1, i1 } [[S]], 1
158  // CHECK: [[QT2:%.+]] = zext i1 [[Q]] to i8
159  // CHECK: store i8 [[QT2]], i8*
160  // CHECK: br i1 [[C]]
161  _Bool r;
162  if (__builtin_add_overflow(x, y, &r))
163    overflowed();
164  return r;
165}
166
167int test_add_overflow_volatile(int x, int y) {
168  // CHECK-LABEL: define {{(dso_local )?}}i32 @test_add_overflow_volatile
169  // CHECK: [[S:%.+]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
170  // CHECK-DAG: [[Q:%.+]] = extractvalue { i32, i1 } [[S]], 0
171  // CHECK-DAG: [[C:%.+]] = extractvalue { i32, i1 } [[S]], 1
172  // CHECK: store volatile i32 [[Q]], i32*
173  // CHECK: br i1 [[C]]
174  volatile int result;
175  if (__builtin_add_overflow(x, y, &result))
176    overflowed();
177  return result;
178}
179
180unsigned test_uadd_overflow(unsigned x, unsigned y) {
181// CHECK: @test_uadd_overflow
182// CHECK: %{{.+}} = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
183  unsigned result;
184  if (__builtin_uadd_overflow(x, y, &result))
185    return UnsignedErrorCode;
186  return result;
187}
188
189unsigned long test_uaddl_overflow(unsigned long x, unsigned long y) {
190// CHECK: @test_uaddl_overflow([[UL:i32|i64]] %x
191// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
192  unsigned long result;
193  if (__builtin_uaddl_overflow(x, y, &result))
194    return UnsignedLongErrorCode;
195  return result;
196}
197
198unsigned long long test_uaddll_overflow(unsigned long long x, unsigned long long y) {
199// CHECK: @test_uaddll_overflow
200// CHECK: %{{.+}} = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
201  unsigned long long result;
202  if (__builtin_uaddll_overflow(x, y, &result))
203    return UnsignedLongLongErrorCode;
204  return result;
205}
206
207unsigned test_usub_overflow(unsigned x, unsigned y) {
208// CHECK: @test_usub_overflow
209// CHECK: %{{.+}} = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
210  unsigned result;
211  if (__builtin_usub_overflow(x, y, &result))
212    return UnsignedErrorCode;
213  return result;
214}
215
216unsigned long test_usubl_overflow(unsigned long x, unsigned long y) {
217// CHECK: @test_usubl_overflow([[UL:i32|i64]] %x
218// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
219  unsigned long result;
220  if (__builtin_usubl_overflow(x, y, &result))
221    return UnsignedLongErrorCode;
222  return result;
223}
224
225unsigned long long test_usubll_overflow(unsigned long long x, unsigned long long y) {
226// CHECK: @test_usubll_overflow
227// CHECK: %{{.+}} = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
228  unsigned long long result;
229  if (__builtin_usubll_overflow(x, y, &result))
230    return UnsignedLongLongErrorCode;
231  return result;
232}
233
234unsigned test_umul_overflow(unsigned x, unsigned y) {
235// CHECK: @test_umul_overflow
236// CHECK: %{{.+}} = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
237  unsigned result;
238  if (__builtin_umul_overflow(x, y, &result))
239    return UnsignedErrorCode;
240  return result;
241}
242
243unsigned long test_umull_overflow(unsigned long x, unsigned long y) {
244// CHECK: @test_umull_overflow([[UL:i32|i64]] %x
245// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.umul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
246  unsigned long result;
247  if (__builtin_umull_overflow(x, y, &result))
248    return UnsignedLongErrorCode;
249  return result;
250}
251
252unsigned long long test_umulll_overflow(unsigned long long x, unsigned long long y) {
253// CHECK: @test_umulll_overflow
254// CHECK: %{{.+}} = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
255  unsigned long long result;
256  if (__builtin_umulll_overflow(x, y, &result))
257    return UnsignedLongLongErrorCode;
258  return result;
259}
260
261int test_sadd_overflow(int x, int y) {
262// CHECK: @test_sadd_overflow
263// CHECK: %{{.+}} = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
264  int result;
265  if (__builtin_sadd_overflow(x, y, &result))
266    return IntErrorCode;
267  return result;
268}
269
270long test_saddl_overflow(long x, long y) {
271// CHECK: @test_saddl_overflow([[UL:i32|i64]] %x
272// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.sadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
273  long result;
274  if (__builtin_saddl_overflow(x, y, &result))
275    return LongErrorCode;
276  return result;
277}
278
279long long test_saddll_overflow(long long x, long long y) {
280// CHECK: @test_saddll_overflow
281// CHECK: %{{.+}} = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
282  long long result;
283  if (__builtin_saddll_overflow(x, y, &result))
284    return LongLongErrorCode;
285  return result;
286}
287
288int test_ssub_overflow(int x, int y) {
289// CHECK: @test_ssub_overflow
290// CHECK: %{{.+}} = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
291  int result;
292  if (__builtin_ssub_overflow(x, y, &result))
293    return IntErrorCode;
294  return result;
295}
296
297long test_ssubl_overflow(long x, long y) {
298// CHECK: @test_ssubl_overflow([[UL:i32|i64]] %x
299// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.ssub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
300  long result;
301  if (__builtin_ssubl_overflow(x, y, &result))
302    return LongErrorCode;
303  return result;
304}
305
306long long test_ssubll_overflow(long long x, long long y) {
307// CHECK: @test_ssubll_overflow
308// CHECK: %{{.+}} = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
309  long long result;
310  if (__builtin_ssubll_overflow(x, y, &result))
311    return LongLongErrorCode;
312  return result;
313}
314
315int test_smul_overflow(int x, int y) {
316// CHECK: @test_smul_overflow
317// CHECK: %{{.+}} = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %{{.+}}, i32 %{{.+}})
318  int result;
319  if (__builtin_smul_overflow(x, y, &result))
320    return IntErrorCode;
321  return result;
322}
323
324long test_smull_overflow(long x, long y) {
325// CHECK: @test_smull_overflow([[UL:i32|i64]] %x
326// CHECK: %{{.+}} = call { [[UL]], i1 } @llvm.smul.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %{{.+}})
327  long result;
328  if (__builtin_smull_overflow(x, y, &result))
329    return LongErrorCode;
330  return result;
331}
332
333long long test_smulll_overflow(long long x, long long y) {
334// CHECK: @test_smulll_overflow
335// CHECK: %{{.+}} = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %{{.+}}, i64 %{{.+}})
336  long long result;
337  if (__builtin_smulll_overflow(x, y, &result))
338    return LongLongErrorCode;
339  return result;
340}
341
342int test_mixed_sign_mul_overflow_sext_signed_op(int x, unsigned long long y) {
343// CHECK: @test_mixed_sign_mul_overflow_sext_signed_op
344// CHECK: [[SignedOp:%.*]] = sext i32 %0 to i64
345// CHECK: [[IsNeg:%.*]] = icmp slt i64 [[SignedOp]], 0
346  int result;
347  if (__builtin_mul_overflow(x, y, &result))
348    return LongErrorCode;
349  return result;
350}
351
352int test_mixed_sign_mul_overflow_zext_unsigned_op(long long x, unsigned y) {
353// CHECK: @test_mixed_sign_mul_overflow_zext_unsigned_op
354// CHECK: [[UnsignedOp:%.*]] = zext i32 %1 to i64
355// CHECK: [[IsNeg:%.*]] = icmp slt i64 %0, 0
356// CHECK: @llvm.umul.with.overflow.i64({{.*}}, i64 [[UnsignedOp]])
357  int result;
358  if (__builtin_mul_overflow(x, y, &result))
359    return LongErrorCode;
360  return result;
361}
362
363int test_mixed_sign_mull_overflow(int x, unsigned y) {
364// CHECK: @test_mixed_sign_mull_overflow
365// CHECK:       [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
366// CHECK-NEXT:  [[Signed:%.*]] = sub i32 0, [[Op1]]
367// CHECK-NEXT:  [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
368// CHECK-NEXT:  call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
369// CHECK-NEXT:  [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
370// CHECK-NEXT:  [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
371// CHECK-NEXT:  [[IsNegZext:%.*]] = zext i1 [[IsNeg]] to i32
372// CHECK-NEXT:  [[MaxResult:%.*]] = add i32 2147483647, [[IsNegZext]]
373// CHECK-NEXT:  [[SignedOFlow:%.*]] = icmp ugt i32 [[UnsignedResult]], [[MaxResult]]
374// CHECK-NEXT:  [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[SignedOFlow]]
375// CHECK-NEXT:  [[NegativeResult:%.*]] = sub i32 0, [[UnsignedResult]]
376// CHECK-NEXT:  [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegativeResult]], i32 [[UnsignedResult]]
377// CHECK-NEXT:  store i32 [[Result]], i32* %{{.*}}, align 4
378// CHECK:       br i1 [[OFlow]]
379
380  int result;
381  if (__builtin_mul_overflow(x, y, &result))
382    return LongErrorCode;
383  return result;
384}
385
386int test_mixed_sign_mull_overflow_unsigned(int x, unsigned y) {
387// CHECK: @test_mixed_sign_mull_overflow_unsigned
388// CHECK:       [[IsNeg:%.*]] = icmp slt i32 [[Op1:%.*]], 0
389// CHECK-NEXT:  [[Signed:%.*]] = sub i32 0, [[Op1]]
390// CHECK-NEXT:  [[AbsSigned:%.*]] = select i1 [[IsNeg]], i32 [[Signed]], i32 [[Op1]]
391// CHECK-NEXT:  call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[AbsSigned]], i32 %{{.*}})
392// CHECK-NEXT:  [[UnsignedOFlow:%.*]] = extractvalue { i32, i1 } %{{.*}}, 1
393// CHECK-NEXT:  [[UnsignedResult:%.*]] = extractvalue { i32, i1 } %{{.*}}, 0
394// CHECK-NEXT:  [[NotNull:%.*]] = icmp ne i32 [[UnsignedResult]], 0
395// CHECK-NEXT:  [[Underflow:%.*]] = and i1 [[IsNeg]], [[NotNull]]
396// CHECK-NEXT:  [[OFlow:%.*]] = or i1 [[UnsignedOFlow]], [[Underflow]]
397// CHECK-NEXT:  [[NegatedResult:%.*]] = sub i32 0, [[UnsignedResult]]
398// CHECK-NEXT:  [[Result:%.*]] = select i1 [[IsNeg]], i32 [[NegatedResult]], i32 [[UnsignedResult]]
399// CHECK-NEXT:  store i32 [[Result]], i32* %{{.*}}, align 4
400// CHECK:       br i1 [[OFlow]]
401
402  unsigned result;
403  if (__builtin_mul_overflow(x, y, &result))
404    return LongErrorCode;
405  return result;
406}
407
408int test_mixed_sign_mull_overflow_swapped(int x, unsigned y) {
409// CHECK: @test_mixed_sign_mull_overflow_swapped
410// CHECK:  call { i32, i1 } @llvm.umul.with.overflow.i32
411// CHECK:  add i32 2147483647
412  int result;
413  if (__builtin_mul_overflow(y, x, &result))
414    return LongErrorCode;
415  return result;
416}
417
418long long test_mixed_sign_mulll_overflow(long long x, unsigned long long y) {
419// CHECK: @test_mixed_sign_mulll_overflow
420// CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
421// CHECK:  add i64 92233720368547
422  long long result;
423  if (__builtin_mul_overflow(x, y, &result))
424    return LongLongErrorCode;
425  return result;
426}
427
428long long test_mixed_sign_mulll_overflow_swapped(long long x, unsigned long long y) {
429// CHECK: @test_mixed_sign_mulll_overflow_swapped
430// CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
431// CHECK:  add i64 92233720368547
432  long long result;
433  if (__builtin_mul_overflow(y, x, &result))
434    return LongLongErrorCode;
435  return result;
436}
437
438long long test_mixed_sign_mulll_overflow_trunc_signed(long long x, unsigned long long y) {
439// CHECK: @test_mixed_sign_mulll_overflow_trunc_signed
440// CHECK:  call { i64, i1 } @llvm.umul.with.overflow.i64
441// CHECK:  add i64 2147483647
442// CHECK:  trunc
443// CHECK:  store
444  int result;
445  if (__builtin_mul_overflow(y, x, &result))
446    return LongLongErrorCode;
447  return result;
448}
449
450long long test_mixed_sign_mulll_overflow_trunc_unsigned(long long x, unsigned long long y) {
451// CHECK: @test_mixed_sign_mulll_overflow_trunc_unsigned
452// CHECK:       call { i64, i1 } @llvm.umul.with.overflow.i64
453// CHECK:       [[NON_ZERO:%.*]] = icmp ne i64 [[UNSIGNED_RESULT:%.*]], 0
454// CHECK-NEXT:  [[UNDERFLOW:%.*]] = and i1 {{.*}}, [[NON_ZERO]]
455// CHECK-NEXT:  [[OVERFLOW_PRE_TRUNC:%.*]] = or i1 {{.*}}, [[UNDERFLOW]]
456// CHECK-NEXT:  [[TRUNC_OVERFLOW:%.*]] = icmp ugt i64 [[UNSIGNED_RESULT]], 4294967295
457// CHECK-NEXT:  [[OVERFLOW:%.*]] = or i1 [[OVERFLOW_PRE_TRUNC]], [[TRUNC_OVERFLOW]]
458// CHECK-NEXT:  [[NEGATED:%.*]] = sub i64 0, [[UNSIGNED_RESULT]]
459// CHECK-NEXT:  [[RESULT:%.*]] = select i1 {{.*}}, i64 [[NEGATED]], i64 [[UNSIGNED_RESULT]]
460// CHECK-NEXT:  trunc i64 [[RESULT]] to i32
461// CHECK-NEXT:  store
462  unsigned result;
463  if (__builtin_mul_overflow(y, x, &result))
464    return LongLongErrorCode;
465  return result;
466}
467
468long long test_mixed_sign_mul_overflow_extend_signed(int x, unsigned y) {
469// CHECK: @test_mixed_sign_mul_overflow_extend_signed
470// CHECK:  call { i64, i1 } @llvm.smul.with.overflow.i64
471  long long result;
472  if (__builtin_mul_overflow(y, x, &result))
473    return LongLongErrorCode;
474  return result;
475}
476
477long long test_mixed_sign_mul_overflow_extend_unsigned(int x, unsigned y) {
478// CHECK: @test_mixed_sign_mul_overflow_extend_unsigned
479// CHECK:  call { i65, i1 } @llvm.smul.with.overflow.i65
480  unsigned long long result;
481  if (__builtin_mul_overflow(y, x, &result))
482    return LongLongErrorCode;
483  return result;
484}
485