diff options
Diffstat (limited to 'test/CodeGen')
121 files changed, 4973 insertions, 625 deletions
diff --git a/test/CodeGen/2006-01-13-StackSave.c b/test/CodeGen/2006-01-13-StackSave.c index 7c506b3..82f4584 100644 --- a/test/CodeGen/2006-01-13-StackSave.c +++ b/test/CodeGen/2006-01-13-StackSave.c @@ -1,6 +1,6 @@ // PR691 -// RUN: %clang_cc1 %s -emit-llvm -o - | opt -std-compile-opts | \ -// RUN: llvm-dis | grep llvm.stacksave +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// CHECK: call i8* @llvm.stacksave() void test(int N) { int i; diff --git a/test/CodeGen/2007-06-18-SextAttrAggregate.c b/test/CodeGen/2007-06-18-SextAttrAggregate.c index 27ae6a9..f548951 100644 --- a/test/CodeGen/2007-06-18-SextAttrAggregate.c +++ b/test/CodeGen/2007-06-18-SextAttrAggregate.c @@ -1,6 +1,14 @@ // RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s +// XFAIL: aarch64 + // PR1513 +// AArch64 ABI actually requires the reverse of what this is testing: the callee +// does any extensions and remaining bits are unspecified. + +// Technically this test wasn't written to test that feature, but it's a +// valuable check nevertheless. + struct s{ long a; long b; diff --git a/test/CodeGen/2008-01-07-UnusualIntSize.c b/test/CodeGen/2008-01-07-UnusualIntSize.c index bf0ca55..c37c89e 100644 --- a/test/CodeGen/2008-01-07-UnusualIntSize.c +++ b/test/CodeGen/2008-01-07-UnusualIntSize.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// FIXME: 32-bit target? +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s // PR1721 struct s { @@ -8,8 +9,8 @@ struct s { // This should have %0 and %1 truncated to 33 bits before any operation. // This can be done using i33 or an explicit and. _Bool test(void) { - // CHECK: and i64 %[[TMP1:[0-9]+]], 8589934591 + // CHECK: and i64 %[[TMP1:[^,]+]], 8589934591 // CHECK-NOT: and i64 [[TMP1]], 8589934591 - // CHECK: and i64 %{{[0-9]}}, 8589934591 + // CHECK: and i64 %{{[^,]+}}, 8589934591 return a.u33 + b.u33 != 0; } diff --git a/test/CodeGen/2008-04-08-NoExceptions.c b/test/CodeGen/2008-04-08-NoExceptions.c index ab2781b..1213492 100644 --- a/test/CodeGen/2008-04-08-NoExceptions.c +++ b/test/CodeGen/2008-04-08-NoExceptions.c @@ -2,9 +2,11 @@ void f(void); void g(void) { - // CHECK: define void @g() nounwind + // CHECK: define void @g() [[NUW:#[0-9]+]] // CHECK-NOT: call void @f() nounwind f(); } -// CHECK-NOT: declare void @f() nounwind +// CHECK-NOT: declare void @f() [[NUW]] + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/2008-07-30-implicit-initialization.c b/test/CodeGen/2008-07-30-implicit-initialization.c index 8c719bb..e516259 100644 --- a/test/CodeGen/2008-07-30-implicit-initialization.c +++ b/test/CodeGen/2008-07-30-implicit-initialization.c @@ -1,6 +1,10 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t -// RUN: grep "ret i32" %t | count 2 -// RUN: grep "ret i32 0" %t | count 2 +// RUN: %clang_cc1 -triple i386-unknown-unknown -O1 -emit-llvm -o - %s | FileCheck %s +// CHECK: define i32 @f0() +// CHECK: ret i32 0 +// CHECK: define i32 @f1() +// CHECK: ret i32 0 +// CHECK: define i32 @f2() +// CHECK: ret i32 0 // <rdar://problem/6113085> struct s0 { @@ -12,14 +16,10 @@ int f0() { return x.y; } -#if 0 -/* Optimizer isn't smart enough to reduce this since we use - memset. Hrm. */ int f1() { struct s0 x[2] = { {0} }; return x[1].x; } -#endif int f2() { int x[2] = { 0 }; diff --git a/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c b/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c index de06263..429fb1f 100644 --- a/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c +++ b/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c @@ -1,4 +1,10 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis | grep "ret i32 1" | count 3 +// RUN: %clang_cc1 -triple i386-unknown-unknown -O1 -emit-llvm -o - %s | FileCheck %s +// CHECK: define i32 @f0 +// CHECK: ret i32 1 +// CHECK: define i32 @f1 +// CHECK: ret i32 1 +// CHECK: define i32 @f2 +// CHECK: ret i32 1 // <rdr://6115726> int f0() { diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c index 8a9dfdd..c48ad28 100644 --- a/test/CodeGen/2009-10-20-GlobalDebug.c +++ b/test/CodeGen/2009-10-20-GlobalDebug.c @@ -6,5 +6,5 @@ int main() { return 0; } -// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !5, metadata !"localstatic", metadata !"localstatic", metadata !"", metadata !6, i32 5, metadata !9, i32 1, i32 1, i32* @main.localstatic} ; [ DW_TAG_variable ] -// CHECK: metadata !{i32 {{.*}}, i32 0, null, metadata !"global", metadata !"global", metadata !"", metadata !6, i32 3, metadata !9, i32 0, i32 1, i32* @global} ; [ DW_TAG_variable ] +// CHECK: metadata !{i32 {{.*}}, i32 0, metadata !{{.*}}, metadata !"localstatic", metadata !"localstatic", metadata !"", metadata !{{.*}}, i32 5, metadata !{{.*}}, i32 1, i32 1, i32* @main.localstatic, null} ; [ DW_TAG_variable ] +// CHECK: metadata !{i32 {{.*}}, i32 0, null, metadata !"global", metadata !"global", metadata !"", metadata !{{.*}}, i32 3, metadata !{{.*}}, i32 0, i32 1, i32* @global, null} ; [ DW_TAG_variable ] diff --git a/test/CodeGen/2010-02-16-DbgScopes.c b/test/CodeGen/2010-02-16-DbgScopes.c index b11f920..36484a4 100644 --- a/test/CodeGen/2010-02-16-DbgScopes.c +++ b/test/CodeGen/2010-02-16-DbgScopes.c @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 -emit-llvm -g < %s | grep lexical | count 5 +// RUN: %clang_cc1 -emit-llvm -g < %s | FileCheck %s // Test to check number of lexical scope identified in debug info. +// CHECK: DW_TAG_lexical_block +// CHECK: DW_TAG_lexical_block +// CHECK: DW_TAG_lexical_block +// CHECK: DW_TAG_lexical_block extern int bar(); extern void foobar(); diff --git a/test/CodeGen/2010-03-5-LexicalScope.c b/test/CodeGen/2010-03-5-LexicalScope.c index 0f63ff6..e0e41dd 100644 --- a/test/CodeGen/2010-03-5-LexicalScope.c +++ b/test/CodeGen/2010-03-5-LexicalScope.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm -O0 -g %s -o - | grep DW_TAG_lexical_block | count 3 +// RUN: %clang_cc1 -emit-llvm -O0 -g %s -o - | FileCheck %s +// CHECK: DW_TAG_lexical_block +// CHECK: DW_TAG_lexical_block int foo(int i) { if (i) { int j = 2; diff --git a/test/CodeGen/PR4611-bitfield-layout.c b/test/CodeGen/PR4611-bitfield-layout.c index 3975ed0..a383f34 100644 --- a/test/CodeGen/PR4611-bitfield-layout.c +++ b/test/CodeGen/PR4611-bitfield-layout.c @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o %t -// RUN: grep "struct.object_entry = type { i8, \[2 x i8\], i8 }" %t +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// +// CHECK: struct.object_entry = type { [4 x i8] } struct object_entry { unsigned int type:3, pack_id:16, depth:13; diff --git a/test/CodeGen/a5.c b/test/CodeGen/a5.c new file mode 100644 index 0000000..b342d35 --- /dev/null +++ b/test/CodeGen/a5.c @@ -0,0 +1,5 @@ +// RUN: %clang -target armv7-none-linux-gnueabi -mcpu=cortex-a5 -emit-llvm -S %s -o /dev/null + +int main() { + return 0; +} diff --git a/test/CodeGen/aarch64-arguments.c b/test/CodeGen/aarch64-arguments.c new file mode 100644 index 0000000..901e734 --- /dev/null +++ b/test/CodeGen/aarch64-arguments.c @@ -0,0 +1,194 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s + +// Sign extension is performed by the callee on AArch64, which means +// that we *shouldn't* tag arguments and returns with their extension. + +// PCS: define i8 @f0(i16 %a) +char f0(short a) { + return a; +} + +// PCS: define [1 x i64] @f1() +struct s1 { char f0; }; +struct s1 f1(void) {} + +// PCS: define [1 x i64] @f2() +struct s2 { short f0; }; +struct s2 f2(void) {} + +// PCS: define [1 x i64] @f3() +struct s3 { int f0; }; +struct s3 f3(void) {} + +// PCS: define [1 x i64] @f4() +struct s4 { struct s4_0 { int f0; } f0; }; +struct s4 f4(void) {} + +// PCS: define [1 x i64] @f5() +struct s5 { struct { } f0; int f1; }; +struct s5 f5(void) {} + +// PCS: define [1 x i64] @f6() +struct s6 { int f0[1]; }; +struct s6 f6(void) {} + +// PCS: define void @f7() +struct s7 { struct { int : 0; } f0; }; +struct s7 f7(void) {} + +// PCS: define void @f8() +struct s8 { struct { int : 0; } f0[1]; }; +struct s8 f8(void) {} + +// PCS: define [1 x i64] @f9() +struct s9 { long f0; int : 0; }; +struct s9 f9(void) {} + +// PCS: define [1 x i64] @f10() +struct s10 { long f0; int : 0; int : 0; }; +struct s10 f10(void) {} + +// PCS: define [1 x i64] @f11() +struct s11 { int : 0; long f0; }; +struct s11 f11(void) {} + +// PCS: define [1 x i64] @f12() +union u12 { char f0; short f1; int f2; long f3; }; +union u12 f12(void) {} + +// PCS: define %struct.s13 @f13() +struct s13 { float f0; }; +struct s13 f13(void) {} + +// PCS: define %union.u14 @f14() +union u14 { float f0; }; +union u14 f14(void) {} + +// PCS: define void @f15() +void f15(struct s7 a0) {} + +// PCS: define void @f16() +void f16(struct s8 a0) {} + +// PCS: define [1 x i64] @f17() +struct s17 { short f0 : 13; char f1 : 4; }; +struct s17 f17(void) {} + +// PCS: define [1 x i64] @f18() +struct s18 { short f0; char f1 : 4; }; +struct s18 f18(void) {} + +// PCS: define [1 x i64] @f19() +struct s19 { long f0; struct s8 f1; }; +struct s19 f19(void) {} + +// PCS: define [1 x i64] @f20() +struct s20 { struct s8 f1; long f0; }; +struct s20 f20(void) {} + +// PCS: define [1 x i64] @f21() +struct s21 { struct {} f1; long f0 : 4; }; +struct s21 f21(void) {} + +// PCS: define { float, float } @f22() +// PCS: define { double, double } @f23( +_Complex float f22(void) {} +_Complex double f23(void) {} + +// PCS: define [1 x i64] @f24() +struct s24 { _Complex char f0; }; +struct s24 f24() {} + +// PCS: define [1 x i64] @f25() +struct s25 { _Complex short f0; }; +struct s25 f25() {} + +// PCS: define [1 x i64] @f26() +struct s26 { _Complex int f0; }; +struct s26 f26() {} + +// PCS: define [2 x i64] @f27() +struct s27 { _Complex long f0; }; +struct s27 f27() {} + +// PCS: define void @f28(i8 %a, i16 %b, i32 %c, i64 %d, float %e, double %f) +void f28(char a, short b, int c, long d, float e, double f) {} + +// PCS: define void @f29([2 x i64] %a +struct s29 { int arr[4]; }; +void f29(struct s29 a) {} + +// PCS: define void @f30(%struct.s30* %a) +struct s30 { int arr[4]; char c;}; +void f30(struct s30 a) {} + +// PCS: define void @f31([4 x double] %a +struct s31 { double arr[4]; }; +void f31(struct s31 a) {} + +// PCS: define void @f32(%struct.s32* %a) +struct s32 { float arr[5]; }; +void f32(struct s32 a) {} + +// Not the only solution, but it *is* an HFA. +// PCS: define void @f33([3 x float] %a.coerce0, float %a.coerce1) +struct s33 { float arr[3]; float a; }; +void f33(struct s33 a) {} + +// PCS: define void @f34(%struct.s34* noalias sret +struct s34 { int a[4]; char b }; +struct s34 f34(void) {} + +// PCS: define void @f35() +struct s35 {}; +void f35(struct s35 a) {} + +// Check padding is added: +// PCS: @f36(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s36* byval align 8 %stacked) +struct s36 { long a, b; }; +void f36(int x0, int x1, int x2, int x3, int x4, int x5, int x6, struct s36 stacked) {} + +// But only once: +// PCS: @f37(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s37* byval align 8 %stacked, %struct.s37* byval align 8 %stacked2) +struct s37 { long a, b; }; +void f37(int x0, int x1, int x2, int x3, int x4, int x5, int x6, struct s37 stacked, struct s37 stacked2) {} + +// Check for HFA padding args. Also, they should not end up on the stack in a +// way which will have holes in when lowered further by LLVM. In particular [3 x +// float] would be unacceptable. + +// PCS: @f38(float %s0, double %d1, float %s2, float %s3, float %s4, float %s5, [2 x float], %struct.s38* byval align 4 %stacked) +struct s38 { float a, b, c; }; +void f38(float s0, double d1, float s2, float s3, float s4, float s5, struct s38 stacked) {} + +// Check both VFP and integer arguments are padded (also that pointers and enums +// get counted as integer types correctly). +struct s39_int { long a, b; }; +struct s39_float { float a, b, c, d; }; +enum s39_enum { Val1, Val2 }; +// PCS: @f39(float %s0, i32 %x0, float %s1, i32* %x1, float %s2, i32 %x2, float %s3, float %s4, i32 %x3, [3 x float], %struct.s39_float* byval align 4 %stacked, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s39_int* byval align 8 %stacked2) +void f39(float s0, int x0, float s1, int *x1, float s2, enum s39_enum x2, float s3, float s4, + int x3, struct s39_float stacked, int x4, int x5, int x6, + struct s39_int stacked2) {} + +struct s40 { __int128 a; }; +// PCS: @f40(i32 %x0, [1 x i128] %x2_3.coerce, i32 %x4, i32 %x5, i32 %x6, [1 x i64], %struct.s40* byval align 16 %stacked) +void f40(int x0, struct s40 x2_3, int x4, int x5, int x6, struct s40 stacked) {} + +// Checking: __int128 will get properly aligned type, with padding so big struct doesn't use x7. +struct s41 { int arr[5]; }; +// PCS: @f41(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5, i32 %x6, [1 x i64], i128* byval align 16, %struct.s41* %stacked2) +int f41(int x0, int x1, int x2, int x3, int x4, int x5, int x6, __int128 stacked, struct s41 stacked2) {} + +// Checking: __int128 needing to be aligned in registers will consume correct +// number. Previously padding was inserted before "stacked" because x6_7 was +// "allocated" to x5 and x6 by clang. +// PCS: @f42(i32 %x0, i32 %x1, i32 %x2, i32 %x3, i32 %x4, i128 %x6_7, i128* byval align 16) +void f42(int x0, int x1, int x2, int x3, int x4, __int128 x6_7, __int128 stacked) {} + +// Checking: __fp16 is extended to double when calling variadic functions +void variadic(int a, ...); +void f43(__fp16 *in) { + variadic(42, *in); +// CHECK: call void @variadic(i32 42, double +} diff --git a/test/CodeGen/aarch64-inline-asm.c b/test/CodeGen/aarch64-inline-asm.c new file mode 100644 index 0000000..ca39c6e --- /dev/null +++ b/test/CodeGen/aarch64-inline-asm.c @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s + +// The only part clang really deals with is the lvalue/rvalue +// distinction on constraints. It's sufficient to emit llvm and make +// sure that's sane. + +long var; + +void test_generic_constraints(int var32, long var64) { + asm("add %0, %1, %1" : "=r"(var32) : "0"(var32)); +// CHECK: [[R32_ARG:%[a-zA-Z0-9]+]] = load i32* +// CHECK: call i32 asm "add $0, $1, $1", "=r,0"(i32 [[R32_ARG]]) + + asm("add %0, %1, %1" : "=r"(var64) : "0"(var64)); +// CHECK: [[R32_ARG:%[a-zA-Z0-9]+]] = load i64* +// CHECK: call i64 asm "add $0, $1, $1", "=r,0"(i64 [[R32_ARG]]) + + asm("ldr %0, %1" : "=r"(var32) : "m"(var)); + asm("ldr %0, [%1]" : "=r"(var64) : "r"(&var)); +// CHECK: call i32 asm "ldr $0, $1", "=r,*m"(i64* @var) +// CHECK: call i64 asm "ldr $0, [$1]", "=r,r"(i64* @var) +} + +float f; +double d; +void test_constraint_w() { + asm("fadd %s0, %s1, %s1" : "=w"(f) : "w"(f)); +// CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load float* @f +// CHECK: call float asm "fadd ${0:s}, ${1:s}, ${1:s}", "=w,w"(float [[FLT_ARG]]) + + asm("fadd %d0, %d1, %d1" : "=w"(d) : "w"(d)); +// CHECK: [[DBL_ARG:%[a-zA-Z_0-9]+]] = load double* @d +// CHECK: call double asm "fadd ${0:d}, ${1:d}, ${1:d}", "=w,w"(double [[DBL_ARG]]) +} + +void test_constraints_immed(void) { + asm("add x0, x0, %0" : : "I"(4095) : "x0"); + asm("and w0, w0, %0" : : "K"(0xaaaaaaaa) : "w0"); + asm("and x0, x0, %0" : : "L"(0xaaaaaaaaaaaaaaaa) : "x0"); +// CHECK: call void asm sideeffect "add x0, x0, $0", "I,~{x0}"(i32 4095) +// CHECK: call void asm sideeffect "and w0, w0, $0", "K,~{w0}"(i32 -1431655766) +// CHECK: call void asm sideeffect "and x0, x0, $0", "L,~{x0}"(i64 -6148914691236517206) +} + +void test_constraint_S(void) { + int *addr; + asm("adrp %0, %A1\n\t" + "add %0, %0, %L1" : "=r"(addr) : "S"(&var)); +// CHECK: call i32* asm "adrp $0, ${1:A}\0A\09add $0, $0, ${1:L}", "=r,S"(i64* @var) +} + +void test_constraint_Q(void) { + int val; + asm("ldxr %0, %1" : "=r"(val) : "Q"(var)); +// CHECK: call i32 asm "ldxr $0, $1", "=r,*Q"(i64* @var) +} diff --git a/test/CodeGen/aarch64-type-sizes.c b/test/CodeGen/aarch64-type-sizes.c new file mode 100644 index 0000000..3b9c9fc --- /dev/null +++ b/test/CodeGen/aarch64-type-sizes.c @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -w -o - %s | FileCheck %s + +// char by definition has size 1 + +int check_short() { + return sizeof(short); +// CHECK: ret i32 2 +} + +int check_int() { + return sizeof(int); +// CHECK: ret i32 4 +} + +int check_long() { +// Both 4 and 8 are permitted under the PCS, Linux says 8! + return sizeof(long); +// CHECK: ret i32 8 +} + +int check_longlong() { + return sizeof(long long); +// CHECK: ret i32 8 +} + +int check_int128() { + return sizeof(__int128); +// CHECK: ret i32 16 +} + +int check_fp16() { + return sizeof(__fp16); +// CHECK: ret i32 2 +} + +int check_float() { + return sizeof(float); +// CHECK: ret i32 4 +} + +int check_double() { + return sizeof(double); +// CHECK: ret i32 8 +} + +int check_longdouble() { + return sizeof(long double); +// CHECK: ret i32 16 +} + +int check_floatComplex() { + return sizeof(float _Complex); +// CHECK: ret i32 8 +} + +int check_doubleComplex() { + return sizeof(double _Complex); +// CHECK: ret i32 16 +} + +int check_longdoubleComplex() { + return sizeof(long double _Complex); +// CHECK: ret i32 32 +} + +int check_bool() { + return sizeof(_Bool); +// CHECK: ret i32 1 +} + +int check_wchar() { +// PCS allows either unsigned short or unsigned int. Linux again says "bigger!" + return sizeof(__WCHAR_TYPE__); +// CHECK: ret i32 4 +} + +int check_wchar_unsigned() { + return (__WCHAR_TYPE__)-1 > (__WCHAR_TYPE__)0; +// CHECK: ret i32 1 +} + +enum Small { + Item +}; + +int foo() { + return sizeof(enum Small); +// CHECK: ret i32 4 +} + diff --git a/test/CodeGen/aarch64-varargs.c b/test/CodeGen/aarch64-varargs.c new file mode 100644 index 0000000..324a070 --- /dev/null +++ b/test/CodeGen/aarch64-varargs.c @@ -0,0 +1,238 @@ +// RUN: %clang_cc1 -triple aarch64 -emit-llvm -o - %s | FileCheck %s +#include <stdarg.h> + +// Obviously there's more than one way to implement va_arg. This test should at +// least prevent unintentional regressions caused by refactoring. + +va_list the_list; + +int simple_int(void) { +// CHECK: define i32 @simple_int + return va_arg(the_list, int); +// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) +// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i32* +// CHECK: br label %[[VAARG_END:[a-z._0-9]+]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to i32* +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi i32* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32* [[ADDR]] +// CHECK: ret i32 [[RESULT]] +} + +__int128 aligned_int(void) { +// CHECK: define i128 @aligned_int + return va_arg(the_list, __int128); +// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15 +// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16 +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) +// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[ALIGNED_REGOFFS]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i128* +// CHECK: br label %[[VAARG_END:[a-z._0-9]+]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[STACKINT:%[a-z_0-9]+]] = ptrtoint i8* [[STACK]] to i64 +// CHECK: [[ALIGN_STACK:%[a-z_0-9]+]] = add i64 [[STACKINT]], 15 +// CHECK: [[ALIGNED_STACK_INT:%[a-z_0-9]+]] = and i64 [[ALIGN_STACK]], -16 +// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9]+]] = inttoptr i64 [[ALIGNED_STACK_INT]] to i8* +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[ALIGNED_STACK_PTR]], i32 16 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[ALIGNED_STACK_PTR]] to i128* +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi i128* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +// CHECK: [[RESULT:%[a-z_0-9]+]] = load i128* [[ADDR]] +// CHECK: ret i128 [[RESULT]] +} + +struct bigstruct { + int a[10]; +}; + +struct bigstruct simple_indirect(void) { +// CHECK: define void @simple_indirect + return va_arg(the_list, struct bigstruct); +// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK-NOT: and i32 +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) +// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.bigstruct** +// CHECK: br label %[[VAARG_END:[a-z._0-9]+]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK-NOT: and i64 +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.bigstruct** +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +// CHECK: load %struct.bigstruct** [[ADDR]] +} + +struct aligned_bigstruct { + float a; + long double b; +}; + +struct aligned_bigstruct simple_aligned_indirect(void) { +// CHECK: define void @simple_aligned_indirect + return va_arg(the_list, struct aligned_bigstruct); +// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) +// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.aligned_bigstruct** +// CHECK: br label %[[VAARG_END:[a-z._0-9]+]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.aligned_bigstruct** +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.aligned_bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +// CHECK: load %struct.aligned_bigstruct** [[ADDR]] +} + +double simple_double(void) { +// CHECK: define double @simple_double + return va_arg(the_list, double); +// CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK]], label %[[VAARG_MAYBE_REG]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 16 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) +// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to double* +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to double* +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi double* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +// CHECK: [[RESULT:%[a-z_0-9]+]] = load double* [[ADDR]] +// CHECK: ret double [[RESULT]] +} + +struct hfa { + float a, b; +}; + +struct hfa simple_hfa(void) { +// CHECK: define %struct.hfa @simple_hfa + return va_arg(the_list, struct hfa); +// CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) +// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0 +// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] + +// CHECK: [[VAARG_MAYBE_REG]] +// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 32 +// CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) +// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 +// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] + +// CHECK: [[VAARG_IN_REG]] +// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) +// CHECK: [[FIRST_REG:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] +// CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 0 +// CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* +// CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA:[a-z_.0-9]+]], i32 0, i32 0 +// CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]] +// CHECK: store float [[EL]], float* [[EL_TMPADDR]] +// CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 16 +// CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* +// CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA]], i32 0, i32 1 +// CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]] +// CHECK: store float [[EL]], float* [[EL_TMPADDR]] +// CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast [2 x float]* %[[TMP_HFA]] to %struct.hfa* +// CHECK: br label %[[VAARG_END:[a-z_.0-9]+]] + +// CHECK: [[VAARG_ON_STACK]] +// CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 +// CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.hfa* +// CHECK: br label %[[VAARG_END]] + +// CHECK: [[VAARG_END]] +// CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.hfa* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] +} + +void check_start(int n, ...) { +// CHECK: define void @check_start(i32 %n, ...) + + va_list the_list; + va_start(the_list, n); +// CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list +// CHECK: [[VOIDP_THE_LIST:%[a-z_0-9]+]] = bitcast %struct.__va_list* [[THE_LIST]] to i8* +// CHECK: call void @llvm.va_start(i8* [[VOIDP_THE_LIST]]) +} + + diff --git a/test/CodeGen/address-safety-attr.cpp b/test/CodeGen/address-safety-attr.cpp index 5c9862d..f94efd6 100644 --- a/test/CodeGen/address-safety-attr.cpp +++ b/test/CodeGen/address-safety-attr.cpp @@ -1,41 +1,80 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix ASAN %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix=ASAN %s +// RUN: echo "src:%s" > %t.file.blacklist +// RUN: echo "fun:*BlacklistedFunction*" > %t.func.blacklist +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s -// The address_safety attribute should be attached to functions -// when AddressSanitizer is enabled, unless no_address_safety_analysis attribute +// FIXME: %t.file.blacklist is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp" +// REQUIRES: shell + +// The sanitize_address attribute should be attached to functions +// when AddressSanitizer is enabled, unless no_sanitize_address attribute // is present. -// CHECK-NOT: NoAddressSafety1{{.*}} address_safety -// ASAN-NOT: NoAddressSafety1{{.*}} address_safety -__attribute__((no_address_safety_analysis)) +// WITHOUT: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] +// BLFILE: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] +// BLFUNC: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] +// ASAN: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] +__attribute__((no_sanitize_address)) int NoAddressSafety1(int *a) { return *a; } -// CHECK-NOT: NoAddressSafety2{{.*}} address_safety -// ASAN-NOT: NoAddressSafety2{{.*}} address_safety -__attribute__((no_address_safety_analysis)) +// WITHOUT: NoAddressSafety2{{.*}}) [[NOATTR]] +// BLFILE: NoAddressSafety2{{.*}}) [[NOATTR]] +// BLFUNC: NoAddressSafety2{{.*}}) [[NOATTR]] +// ASAN: NoAddressSafety2{{.*}}) [[NOATTR]] +__attribute__((no_sanitize_address)) int NoAddressSafety2(int *a); int NoAddressSafety2(int *a) { return *a; } -// CHECK-NOT: AddressSafetyOk{{.*}} address_safety -// ASAN: AddressSafetyOk{{.*}} address_safety +// WITHOUT: AddressSafetyOk{{.*}}) [[NOATTR]] +// BLFILE: AddressSafetyOk{{.*}}) [[NOATTR]] +// BLFUNC: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]] +// ASAN: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]] int AddressSafetyOk(int *a) { return *a; } -// CHECK-NOT: TemplateNoAddressSafety{{.*}} address_safety -// ASAN-NOT: TemplateNoAddressSafety{{.*}} address_safety -template<int i> -__attribute__((no_address_safety_analysis)) -int TemplateNoAddressSafety() { return i; } +// WITHOUT: BlacklistedFunction{{.*}}) [[NOATTR]] +// BLFILE: BlacklistedFunction{{.*}}) [[NOATTR]] +// BLFUNC: BlacklistedFunction{{.*}}) [[NOATTR]] +// ASAN: BlacklistedFunction{{.*}}) [[WITH]] +int BlacklistedFunction(int *a) { return *a; } -// CHECK-NOT: TemplateAddressSafetyOk{{.*}} address_safety -// ASAN: TemplateAddressSafetyOk{{.*}} address_safety +// WITHOUT: TemplateAddressSafetyOk{{.*}}) [[NOATTR]] +// BLFILE: TemplateAddressSafetyOk{{.*}}) [[NOATTR]] +// BLFUNC: TemplateAddressSafetyOk{{.*}}) [[WITH]] +// ASAN: TemplateAddressSafetyOk{{.*}}) [[WITH]] template<int i> int TemplateAddressSafetyOk() { return i; } +// WITHOUT: TemplateNoAddressSafety{{.*}}) [[NOATTR]] +// BLFILE: TemplateNoAddressSafety{{.*}}) [[NOATTR]] +// BLFUNC: TemplateNoAddressSafety{{.*}}) [[NOATTR]] +// ASAN: TemplateNoAddressSafety{{.*}}) [[NOATTR]] +template<int i> +__attribute__((no_sanitize_address)) +int TemplateNoAddressSafety() { return i; } + int force_instance = TemplateAddressSafetyOk<42>() + TemplateNoAddressSafety<42>(); -// Check that __cxx_global_var_init* get the address_safety attribute. +// Check that __cxx_global_var_init* get the sanitize_address attribute. int global1 = 0; int global2 = *(int*)((char*)&global1+1); -// CHECK-NOT: @__cxx_global_var_init{{.*}}address_safety -// ASAN: @__cxx_global_var_init{{.*}}address_safety +// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// BLFILE: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] +// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] + +// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} } +// WITHOUT: attributes [[NOATTR_NO_TF]] = { nounwind } + +// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} } +// BLFILE: attributes [[NOATTR_NO_TF]] = { nounwind } + +// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} } +// BLFUNC: attributes [[WITH]] = { nounwind sanitize_address{{.*}} } +// BLFUNC: attributes [[WITH_NO_TF]] = { nounwind sanitize_address } + +// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} } +// ASAN: attributes [[WITH]] = { nounwind sanitize_address{{.*}} } +// ASAN: attributes [[WITH_NO_TF]] = { nounwind sanitize_address } diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c index e9c1871..c6b3181 100644 --- a/test/CodeGen/address-space-field1.c +++ b/test/CodeGen/address-space-field1.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 < %s -o - | FileCheck %s // CHECK:%struct.S = type { i32, i32 } -// CHECK:define void @test_addrspace(%struct.S addrspace(1)* %p1, %struct.S addrspace(2)* %p2) nounwind +// CHECK:define void @test_addrspace(%struct.S addrspace(1)* %p1, %struct.S addrspace(2)* %p2) [[NUW:#[0-9]+]] // CHECK: [[p1addr:%.*]] = alloca %struct.S addrspace(1)* // CHECK: [[p2addr:%.*]] = alloca %struct.S addrspace(2)* // CHECK: store %struct.S addrspace(1)* %p1, %struct.S addrspace(1)** [[p1addr]] @@ -36,3 +36,5 @@ void test_addrspace(__addr1 S* p1, __addr2 S*p2) { p1->a = p2->b; p1->b = p2->a; } + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c index 0ccbca6..a8380a3 100644 --- a/test/CodeGen/alias.c +++ b/test/CodeGen/alias.c @@ -14,7 +14,7 @@ void f0(void) { } extern void f1(void); extern void f1(void) __attribute((alias("f0"))); // CHECKBASIC: @f1 = alias void ()* @f0 -// CHECKBASIC: define void @f0() nounwind { +// CHECKBASIC: define void @f0() [[NUW:#[0-9]+]] { // Make sure that aliases cause referenced values to be emitted. // PR3200 @@ -34,13 +34,17 @@ static int inner_weak(int a) { return 0; } extern __typeof(inner) inner_a __attribute__((alias("inner"))); static __typeof(inner_weak) inner_weak_a __attribute__((weakref, alias("inner_weak"))); // CHECKCC: @inner_a = alias i32 (i32)* @inner -// CHECKCC: define internal arm_aapcs_vfpcc i32 @inner(i32 %a) nounwind { +// CHECKCC: define internal arm_aapcs_vfpcc i32 @inner(i32 %a) [[NUW:#[0-9]+]] { int outer(int a) { return inner(a); } -// CHECKCC: define arm_aapcs_vfpcc i32 @outer(i32 %a) nounwind { +// CHECKCC: define arm_aapcs_vfpcc i32 @outer(i32 %a) [[NUW]] { // CHECKCC: call arm_aapcs_vfpcc i32 @inner(i32 %{{.*}}) int outer_weak(int a) { return inner_weak_a(a); } -// CHECKCC: define arm_aapcs_vfpcc i32 @outer_weak(i32 %a) nounwind { +// CHECKCC: define arm_aapcs_vfpcc i32 @outer_weak(i32 %a) [[NUW]] { // CHECKCC: call arm_aapcs_vfpcc i32 @inner_weak(i32 %{{.*}}) -// CHECKCC: define internal arm_aapcs_vfpcc i32 @inner_weak(i32 %a) nounwind { +// CHECKCC: define internal arm_aapcs_vfpcc i32 @inner_weak(i32 %a) [[NUW]] { + +// CHECKBASIC: attributes [[NUW]] = { nounwind{{.*}} } + +// CHECKCC: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/always-inline.c b/test/CodeGen/always-inline.c index dc74be5..c9fd1ae 100644 --- a/test/CodeGen/always-inline.c +++ b/test/CodeGen/always-inline.c @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | grep call | not grep foo +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fno-inline -emit-llvm %s -o - | FileCheck %s + +// CHECK-NOT: foo void bar() { } diff --git a/test/CodeGen/arm-asm-warn.c b/test/CodeGen/arm-asm-warn.c index 0c4e97a..9b52dd6 100644 --- a/test/CodeGen/arm-asm-warn.c +++ b/test/CodeGen/arm-asm-warn.c @@ -1,7 +1,20 @@ // REQUIRES: arm-registered-target // RUN: %clang_cc1 -triple armv7 %s -emit-llvm -o /dev/null -// <rdar://problem/12284092> +char bar(); + +void t1(int x, char y) { + __asm__ volatile("mcr p15, 0, %1, c9, c12, 5;" + "mrc p15, 0, %0, c9, c13, 2;" + : "=r" (x) + : "r" (bar())); // no warning + __asm__ volatile("foo %0, %1" + : "+r" (x), + "+r" (y) + :); +} + +// <rdar://problem/12284092> typedef __attribute__((neon_vector_type(2))) long long int64x2_t; typedef struct int64x2x4_t { int64x2_t val[4]; @@ -9,10 +22,10 @@ typedef struct int64x2x4_t { int64x2x4_t t2(const long long a[]) { int64x2x4_t r; __asm__("vldm %[a], { %q[r0], %q[r1], %q[r2], %q[r3] }" - : [r0] "=r"(r.val[0]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}} - [r1] "=r"(r.val[1]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}} - [r2] "=r"(r.val[2]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}} - [r3] "=r"(r.val[3]) // expected-warning {{the size being stored is truncated, use a modifier to specify the size}} + : [r0] "=r"(r.val[0]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}} + [r1] "=r"(r.val[1]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}} + [r2] "=r"(r.val[2]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}} + [r3] "=r"(r.val[3]) // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}} : [a] "r"(a)); return r; } diff --git a/test/CodeGen/arm-neon-fma.c b/test/CodeGen/arm-neon-fma.c new file mode 100644 index 0000000..994702d --- /dev/null +++ b/test/CodeGen/arm-neon-fma.c @@ -0,0 +1,19 @@ +// REQUIRES: arm-registered-target +// RUN: %clang_cc1 -triple thumbv7-none-linux-gnueabihf \ +// RUN: -target-abi aapcs \ +// RUN: -target-cpu cortex-a8 \ +// RUN: -mfloat-abi hard \ +// RUN: -ffreestanding \ +// RUN: -O3 -S -emit-llvm -o - %s | FileCheck %s + +#include <arm_neon.h> + +float32x2_t test_fma_order(float32x2_t accum, float32x2_t lhs, float32x2_t rhs) { + return vfma_f32(accum, lhs, rhs); +// CHECK: call <2 x float> @llvm.fma.v2f32(<2 x float> %lhs, <2 x float> %rhs, <2 x float> %accum) +} + +float32x4_t test_fmaq_order(float32x4_t accum, float32x4_t lhs, float32x4_t rhs) { + return vfmaq_f32(accum, lhs, rhs); +// CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %lhs, <4 x float> %rhs, <4 x float> %accum) +} diff --git a/test/CodeGen/atomic_ops.c b/test/CodeGen/atomic_ops.c index 481d1e0..910e9b9 100644 --- a/test/CodeGen/atomic_ops.c +++ b/test/CodeGen/atomic_ops.c @@ -15,9 +15,4 @@ void foo(int x) // CHECK: sdiv i32 // CHECK: cmpxchg i16* - // These should be emitting atomicrmw instructions, but they aren't yet - i += 2; // CHECK: cmpxchg - i -= 2; // CHECK: cmpxchg - i++; // CHECK: cmpxchg - i--; // CHECK: cmpxchg } diff --git a/test/CodeGen/atomics-inlining.c b/test/CodeGen/atomics-inlining.c new file mode 100644 index 0000000..9b0d413 --- /dev/null +++ b/test/CodeGen/atomics-inlining.c @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=PPC32 +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=PPC64 +// RUN: %clang_cc1 -triple mipsel-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS32 +// RUN: %clang_cc1 -triple mips64el-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64 + +unsigned char c1, c2; +unsigned short s1, s2; +unsigned int i1, i2; +unsigned long long ll1, ll2; + +enum memory_order { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +}; + +void test1(void) { + (void)__atomic_load(&c1, &c2, memory_order_seq_cst); + (void)__atomic_load(&s1, &s2, memory_order_seq_cst); + (void)__atomic_load(&i1, &i2, memory_order_seq_cst); + (void)__atomic_load(&ll1, &ll2, memory_order_seq_cst); + +// PPC32: define void @test1 +// PPC32: load atomic i8* @c1 seq_cst +// PPC32: load atomic i16* @s1 seq_cst +// PPC32: load atomic i32* @i1 seq_cst +// PPC32: call void @__atomic_load(i32 8, i8* bitcast (i64* @ll1 to i8*) + +// PPC64: define void @test1 +// PPC64: load atomic i8* @c1 seq_cst +// PPC64: load atomic i16* @s1 seq_cst +// PPC64: load atomic i32* @i1 seq_cst +// PPC64: load atomic i64* @ll1 seq_cst + +// MIPS32: define void @test1 +// MIPS32: load atomic i8* @c1 seq_cst +// MIPS32: load atomic i16* @s1 seq_cst +// MIPS32: load atomic i32* @i1 seq_cst +// MIPS32: call void @__atomic_load(i32 8, i8* bitcast (i64* @ll1 to i8*) + +// MIPS64: define void @test1 +// MIPS64: load atomic i8* @c1 seq_cst +// MIPS64: load atomic i16* @s1 seq_cst +// MIPS64: load atomic i32* @i1 seq_cst +// MIPS64: load atomic i64* @ll1 seq_cst +} diff --git a/test/CodeGen/attr-coldhot.c b/test/CodeGen/attr-coldhot.c index b9bb299..a277119 100644 --- a/test/CodeGen/attr-coldhot.c +++ b/test/CodeGen/attr-coldhot.c @@ -4,6 +4,8 @@ int test1() __attribute__((__cold__)) { return 42; // Check that we set the optsize attribute on the function. -// CHECK: @test1{{.*}}optsize +// CHECK: @test1{{.*}}[[ATTR:#[0-9]+]] // CHECK: ret } + +// CHECK: attributes [[ATTR]] = { {{.*}}optsize{{.*}} } diff --git a/test/CodeGen/attr-minsize.cpp b/test/CodeGen/attr-minsize.cpp index a422a62..997194d 100644 --- a/test/CodeGen/attr-minsize.cpp +++ b/test/CodeGen/attr-minsize.cpp @@ -7,29 +7,29 @@ // Check that we set the minsize attribute on each function // when Oz optimization level is set. +__attribute__((minsize)) int test1() { return 42; -// Oz: @{{.*}}test1{{.*}}minsize -// Oz: ret -// OTHER: @{{.*}}test1 -// OTHER-NOT: minsize -// OTHER: ret +// Oz: @{{.*}}test1{{.*}}[[MINSIZE:#[0-9]+]] +// OTHER: @{{.*}}test1{{.*}}[[MS:#[0-9]+]] } int test2() { return 42; -// Oz: @{{.*}}test2{{.*}}minsize +// Oz: @{{.*}}test2{{.*}}[[MINSIZE]] // Oz: ret // OTHER: @{{.*}}test2 -// OTHER-NOT: minsize +// OTHER-NOT: [[MS]] // OTHER: ret } -__attribute__((minsize)) int test3() { return 42; -// Oz: @{{.*}}test3{{.*}}minsize -// OTHER: @{{.*}}test3{{.*}}minsize +// Oz: @{{.*}}test3{{.*}}[[MINSIZE]] +// Oz: ret +// OTHER: @{{.*}}test3 +// OTHER-NOT: [[MS]] +// OTHER: ret } // Check that the minsize attribute is well propagated through @@ -44,16 +44,16 @@ void test4(T arg) { template void test4<int>(int arg); // Oz: define{{.*}}void @{{.*}}test4 -// Oz: minsize +// Oz: [[MINSIZE]] // OTHER: define{{.*}}void @{{.*}}test4 -// OTHER: minsize +// OTHER: [[MS]] template void test4<float>(float arg); // Oz: define{{.*}}void @{{.*}}test4 -// Oz: minsize +// Oz: [[MINSIZE]] // OTHER: define{{.*}}void @{{.*}}test4 -// OTHER: minsize +// OTHER: [[MS]] template<typename T> void test5(T arg) { @@ -63,13 +63,17 @@ void test5(T arg) { template void test5<int>(int arg); // Oz: define{{.*}}void @{{.*}}test5 -// Oz: minsize +// Oz: [[MINSIZE]] // OTHER: define{{.*}}void @{{.*}}test5 -// OTHER-NOT: minsize +// OTHER-NOT: define{{.*}}void @{{.*}}test5{{.*}}[[MS]] template void test5<float>(float arg); // Oz: define{{.*}}void @{{.*}}test5 -// Oz: minsize +// Oz: [[MINSIZE]] // OTHER: define{{.*}}void @{{.*}}test5 -// OTHER-NOT: minsize +// OTHER-NOT: define{{.*}}void @{{.*}}test5{{.*}}[[MS]] + +// Oz: attributes [[MINSIZE]] = { minsize{{.*}} } + +// OTHER: attributes [[MS]] = { minsize nounwind{{.*}} } diff --git a/test/CodeGen/attr-naked.c b/test/CodeGen/attr-naked.c index 2387d28..c07dd8d 100644 --- a/test/CodeGen/attr-naked.c +++ b/test/CodeGen/attr-naked.c @@ -4,13 +4,15 @@ void t1() __attribute__((naked)); // Basic functionality check // (Note that naked needs to imply noinline to work properly.) -// CHECK: define void @t1() nounwind noinline naked { +// CHECK: define void @t1() [[NAKED:#[0-9]+]] { void t1() { } // Make sure this doesn't explode in the verifier. // (It doesn't really make sense, but it isn't invalid.) -// CHECK: define void @t2() nounwind noinline naked { +// CHECK: define void @t2() [[NAKED]] { __attribute((naked, always_inline)) void t2() { } + +// CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 00688dc..356a179 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -36,39 +36,39 @@ int t17() { return t15() + t16; } -// CHECK: define void @t1() noreturn nounwind { +// CHECK: define void @t1() [[NR:#[0-9]+]] { void t1() __attribute__((noreturn)); void t1() { while (1) {} } -// CHECK: define void @t2() nounwind { +// CHECK: define void @t2() [[NUW:#[0-9]+]] { void t2() __attribute__((nothrow)); void t2() {} -// CHECK: define weak void @t3() nounwind { +// CHECK: define weak void @t3() [[NUW]] { void t3() __attribute__((weak)); void t3() {} -// CHECK: define hidden void @t4() nounwind { +// CHECK: define hidden void @t4() [[NUW]] { void t4() __attribute__((visibility("hidden"))); void t4() {} -// CHECK: define void @t7() noreturn nounwind { +// CHECK: define void @t7() [[NR]] { void t7() __attribute__((noreturn, nothrow)); void t7() { while (1) {} } -// CHECK: define void @t10() nounwind section "SECT" { +// CHECK: define void @t10() [[NUW]] section "SECT" { void t10(void) __attribute__((section("SECT"))); void t10(void) {} -// CHECK: define void @t11() nounwind section "SECT" { +// CHECK: define void @t11() [[NUW]] section "SECT" { void __attribute__((section("SECT"))) t11(void) {} -// CHECK: define i32 @t19() nounwind { +// CHECK: define i32 @t19() [[NUW]] { extern int t19(void) __attribute__((weak_import)); int t19(void) { return 10; } -// CHECK:define void @t20() nounwind { +// CHECK:define void @t20() [[NUW]] { // CHECK: call void @abort() // CHECK-NEXT: unreachable void t20(void) { @@ -88,4 +88,7 @@ void t21(void) { void __attribute__((section(".foo"))) t22(void); void __attribute__((section(".bar"))) t22(void) {} -// CHECK: define void @t22() nounwind section ".bar" +// CHECK: define void @t22() [[NUW]] section ".bar" + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} } diff --git a/test/CodeGen/bitfield-2.c b/test/CodeGen/bitfield-2.c index 69ed5b1..bec55ff 100644 --- a/test/CodeGen/bitfield-2.c +++ b/test/CodeGen/bitfield-2.c @@ -9,17 +9,12 @@ // PR6176 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s0 +// CHECK-RECORD: Record: RecordDecl{{.*}}s0 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:%struct.s0 = type <{ [3 x i8] }> // CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ -// CHECK-RECORD: <CGBitFieldInfo Size:24 IsSigned:1 -// CHECK-RECORD: NumComponents:2 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:0 FieldBitStart:0 AccessWidth:16 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:0 TargetBitWidth:16> -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:2 FieldBitStart:0 AccessWidth:8 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:16 TargetBitWidth:8> +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:24 IsSigned:1 StorageSize:24 StorageAlignment:1> struct __attribute((packed)) s0 { int f0 : 24; }; @@ -54,22 +49,13 @@ unsigned long long test_0() { // PR5591 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s1 +// CHECK-RECORD: Record: RecordDecl{{.*}}s1 // CHECK-RECORD: Layout: <CGRecordLayout -// CHECK-RECORD: LLVMType:%struct.s1 = type <{ [2 x i8], i8 }> +// CHECK-RECORD: LLVMType:%struct.s1 = type <{ [3 x i8] }> // CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ -// CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1 -// CHECK-RECORD: NumComponents:1 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:0 FieldBitStart:0 AccessWidth:16 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:0 TargetBitWidth:10> -// CHECK-RECORD: ]> -// CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1 -// CHECK-RECORD: NumComponents:2 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:0 FieldBitStart:10 AccessWidth:16 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:0 TargetBitWidth:6> -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:2 FieldBitStart:0 AccessWidth:8 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:6 TargetBitWidth:4> +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:10 IsSigned:1 StorageSize:24 StorageAlignment:1> +// CHECK-RECORD: <CGBitFieldInfo Offset:10 Size:10 IsSigned:1 StorageSize:24 StorageAlignment:1> #pragma pack(push) #pragma pack(1) @@ -111,15 +97,12 @@ unsigned long long test_1() { // PR5567 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: union u2 +// CHECK-RECORD: Record: RecordDecl{{.*}}u2 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:%union.u2 = type <{ i8 }> // CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ -// CHECK-RECORD: <CGBitFieldInfo Size:3 IsSigned:0 -// CHECK-RECORD: NumComponents:1 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:0 FieldBitStart:0 AccessWidth:8 -// CHECK-RECORD: AccessAlignment:1 TargetBitOffset:0 TargetBitWidth:3> +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:8 StorageAlignment:1> union __attribute__((packed)) u2 { unsigned long long f0 : 3; @@ -286,20 +269,13 @@ _Bool test_6() { // Check that we compute the best alignment possible for each access. // // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s7 +// CHECK-RECORD: Record: RecordDecl{{.*}}s7 // CHECK-RECORD: Layout: <CGRecordLayout // CHECK-RECORD: LLVMType:%struct.s7 = type { i32, i32, i32, i8, [3 x i8], [4 x i8], [12 x i8] } // CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ -// CHECK-RECORD: <CGBitFieldInfo Size:5 IsSigned:1 -// CHECK-RECORD: NumComponents:1 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:12 FieldBitStart:0 AccessWidth:32 -// CHECK-RECORD: AccessAlignment:4 TargetBitOffset:0 TargetBitWidth:5> -// CHECK-RECORD: ]> -// CHECK-RECORD: <CGBitFieldInfo Size:29 IsSigned:1 -// CHECK-RECORD: NumComponents:1 Components: [ -// CHECK-RECORD: <AccessInfo FieldIndex:0 FieldByteOffset:16 FieldBitStart:0 AccessWidth:32 -// CHECK-RECORD: AccessAlignment:16 TargetBitOffset:0 TargetBitWidth:29> +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:8 StorageAlignment:4> +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:29 IsSigned:1 StorageSize:32 StorageAlignment:16> struct __attribute__((aligned(16))) s7 { int a, b, c; diff --git a/test/CodeGen/blocks-seq.c b/test/CodeGen/blocks-seq.c index 3557b48..8db9e60 100644 --- a/test/CodeGen/blocks-seq.c +++ b/test/CodeGen/blocks-seq.c @@ -1,13 +1,11 @@ -// FIXME: We forcibly strip the names so that the test doesn't vary between -// builds with and without asserts. We need a better solution for this. - -// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -emit-llvm-bc -o - %s | opt -strip | llvm-dis > %t -// RUN: grep '%6 = call i32 (...)\* @rhs()' %t | count 1 -// RUN: grep '%7 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1 -// RUN: grep '%8 = load %0\*\* %7' %t | count 1 -// RUN: grep '%10 = call i32 (...)\* @rhs()' %t | count 1 -// RUN: grep '%11 = getelementptr inbounds %0\* %1, i32 0, i32 1' %t | count 1 -// RUN: grep '%12 = load %0\*\* %11' %t | count 1 +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// CHECK: [[Vi:%.+]] = alloca %struct.__block_byref_i, align 8 +// CHECK: call i32 (...)* @rhs() +// CHECK: [[V7:%.+]] = getelementptr inbounds %struct.__block_byref_i* [[Vi]], i32 0, i32 1 +// CHECK: load %struct.__block_byref_i** [[V7]] +// CHECK: call i32 (...)* @rhs() +// CHECK: [[V11:%.+]] = getelementptr inbounds %struct.__block_byref_i* [[Vi]], i32 0, i32 1 +// CHECK: load %struct.__block_byref_i** [[V11]] int rhs(); diff --git a/test/CodeGen/bool_test.c b/test/CodeGen/bool_test.c index 715f846..83d8330 100644 --- a/test/CodeGen/bool_test.c +++ b/test/CodeGen/bool_test.c @@ -1,6 +1,18 @@ // REQUIRES: ppc32-registered-target -// RUN: %clang_cc1 -triple powerpc-apple-darwin -emit-llvm -o - %s| FileCheck -check-prefix=DARWINPPC-CHECK %s +// RUN: %clang_cc1 -triple powerpc-apple-macosx10.4.0 -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s int boolsize = sizeof(_Bool); -//DARWINPPC-CHECK: boolsize = global i32 4, align 4 +// CHECK: boolsize = global i32 4, align 4 +void f(_Bool *x, _Bool *y) { + *x = *y; +} + +// CHECK: define void @f( +// CHECK: [[FROMMEM:%.*]] = load i32* % +// CHECK: [[BOOLVAL:%.*]] = trunc i32 [[FROMMEM]] to i1 +// CHECK: [[TOMEM:%.*]] = zext i1 [[BOOLVAL]] to i32 +// CHECK: store i32 [[TOMEM]] +// CHECK: ret void + +// CHECK: metadata !{i32 0, i32 2} diff --git a/test/CodeGen/bounds-checking.c b/test/CodeGen/bounds-checking.c index e278620..fa7541f 100644 --- a/test/CodeGen/bounds-checking.c +++ b/test/CodeGen/bounds-checking.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fbounds-checking=4 -emit-llvm -triple x86_64-apple-darwin10 < %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=bounds -emit-llvm -triple x86_64-apple-darwin10 < %s | FileCheck %s // CHECK: @f double f(int b, int i) { diff --git a/test/CodeGen/builtin-attributes.c b/test/CodeGen/builtin-attributes.c index 1d3a943..c5c35c3 100644 --- a/test/CodeGen/builtin-attributes.c +++ b/test/CodeGen/builtin-attributes.c @@ -12,7 +12,7 @@ void f1() { exit(1); } -// CHECK: call i8* @strstr{{.*}} nounwind +// CHECK: call i8* @strstr{{.*}} [[NUW:#[0-9]+]] char* f2(char* a, char* b) { return __builtin_strstr(a, b); } @@ -57,3 +57,5 @@ int f3(double x) { __builtin_remquol(x, x, &e); return e; } + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c index 3611650..e6c7ced 100644 --- a/test/CodeGen/builtins-arm.c +++ b/test/CodeGen/builtins-arm.c @@ -11,3 +11,10 @@ void f1(char *a, char *b) { } // CHECK: call {{.*}} @__clear_cache + +void test_eh_return_data_regno() +{ + volatile int res; + res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 0 + res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 1 +} diff --git a/test/CodeGen/builtins-mips.c b/test/CodeGen/builtins-mips.c index ef4662c..c6be896 100644 --- a/test/CodeGen/builtins-mips.c +++ b/test/CodeGen/builtins-mips.c @@ -532,3 +532,10 @@ void foo() { v4i8_r = __builtin_mips_subuh_r_qb(v4i8_a, v4i8_b); // CHECK: call <4 x i8> @llvm.mips.subuh.r.qb } + +void test_eh_return_data_regno() +{ + volatile int res; + res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 4 + res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 5 +} diff --git a/test/CodeGen/builtins-multiprecision.c b/test/CodeGen/builtins-multiprecision.c new file mode 100644 index 0000000..172f683 --- /dev/null +++ b/test/CodeGen/builtins-multiprecision.c @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 -triple "i686-unknown-unknown" -emit-llvm -x c %s -o - -O3 | FileCheck %s +// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - -O3 | FileCheck %s +// RUN: %clang_cc1 -triple "x86_64-mingw32" -emit-llvm -x c %s -o - -O3 | FileCheck %s + +unsigned short test_addcs(unsigned short x, unsigned short y, + unsigned short carryin, unsigned short *z) { + // CHECK: @test_addcs + // CHECK: %{{.+}} = {{.*}} call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 %x, i16 %y) + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 %{{.+}}, i16 %carryin) + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i16 + // CHECK: store i16 %{{.+}}, i16* %z, align 2 + + unsigned short carryout; + *z = __builtin_addcs(x, y, carryin, &carryout); + + return carryout; +} + +unsigned test_addc(unsigned x, unsigned y, unsigned carryin, unsigned *z) { + // CHECK: @test_addc + // CHECK: %{{.+}} = {{.*}} call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %{{.+}}, i32 %carryin) + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i32 + // CHECK: store i32 %{{.+}}, i32* %z, align 4 + unsigned carryout; + *z = __builtin_addc(x, y, carryin, &carryout); + + return carryout; +} + +unsigned long test_addcl(unsigned long x, unsigned long y, + unsigned long carryin, unsigned long *z) { + // long is i32 on i686, i64 on x86_64. + // CHECK: @test_addcl([[UL:i32|i64]] %x + // CHECK: %{{.+}} = {{.*}} call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %x, [[UL]] %y) + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { [[UL]], i1 } @llvm.uadd.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %carryin) + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to [[UL]] + // CHECK: store [[UL]] %{{.+}}, [[UL]]* %z + unsigned long carryout; + *z = __builtin_addcl(x, y, carryin, &carryout); + + return carryout; +} + +unsigned long long test_addcll(unsigned long long x, unsigned long long y, + unsigned long long carryin, + unsigned long long *z) { + // CHECK: @test_addcll + // CHECK: %{{.+}} = {{.*}} call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %x, i64 %y) + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %{{.+}}, i64 %carryin) + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i64 + // CHECK: store i64 %{{.+}}, i64* %z + unsigned long long carryout; + *z = __builtin_addcll(x, y, carryin, &carryout); + + return carryout; +} + +unsigned short test_subcs(unsigned short x, unsigned short y, + unsigned short carryin, unsigned short *z) { + // CHECK: @test_subcs + // CHECK: %{{.+}} = {{.*}} call { i16, i1 } @llvm.usub.with.overflow.i16(i16 %x, i16 %y) + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i16, i1 } @llvm.usub.with.overflow.i16(i16 %{{.+}}, i16 %carryin) + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i16, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i16 + // CHECK: store i16 %{{.+}}, i16* %z, align 2 + + unsigned short carryout; + *z = __builtin_subcs(x, y, carryin, &carryout); + + return carryout; +} + +unsigned test_subc(unsigned x, unsigned y, unsigned carryin, unsigned *z) { + // CHECK: @test_subc + // CHECK: %{{.+}} = {{.*}} call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y) + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %{{.+}}, i32 %carryin) + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i32, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i32 + // CHECK: store i32 %{{.+}}, i32* %z, align 4 + unsigned carryout; + *z = __builtin_subc(x, y, carryin, &carryout); + + return carryout; +} + +unsigned long test_subcl(unsigned long x, unsigned long y, + unsigned long carryin, unsigned long *z) { + // CHECK: @test_subcl([[UL:i32|i64]] %x + // CHECK: %{{.+}} = {{.*}} call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %x, [[UL]] %y) + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { [[UL]], i1 } @llvm.usub.with.overflow.[[UL]]([[UL]] %{{.+}}, [[UL]] %carryin) + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { [[UL]], i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to [[UL]] + // CHECK: store [[UL]] %{{.+}}, [[UL]]* %z + unsigned long carryout; + *z = __builtin_subcl(x, y, carryin, &carryout); + + return carryout; +} + +unsigned long long test_subcll(unsigned long long x, unsigned long long y, + unsigned long long carryin, + unsigned long long *z) { + // CHECK: @test_subcll + // CHECK: %{{.+}} = {{.*}} call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %x, i64 %y) + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %{{.+}}, i64 %carryin) + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i64, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i64 + // CHECK: store i64 %{{.+}}, i64* %z + unsigned long long carryout; + *z = __builtin_subcll(x, y, carryin, &carryout); + + return carryout; +} diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c index e885cb0..9427a8a 100644 --- a/test/CodeGen/builtins-ppc-altivec.c +++ b/test/CodeGen/builtins-ppc-altivec.c @@ -484,20 +484,20 @@ void test6() { res_vf = vec_lvx(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvx /* vec_lde */ - res_vsc = vec_lde(0, &vsc); // CHECK: @llvm.ppc.altivec.lvebx - res_vuc = vec_lde(0, &vuc); // CHECK: @llvm.ppc.altivec.lvebx - res_vs = vec_lde(0, &vs); // CHECK: @llvm.ppc.altivec.lvehx - res_vus = vec_lde(0, &vus); // CHECK: @llvm.ppc.altivec.lvehx - res_vi = vec_lde(0, &vi); // CHECK: @llvm.ppc.altivec.lvewx - res_vui = vec_lde(0, &vui); // CHECK: @llvm.ppc.altivec.lvewx - res_vf = vec_lde(0, &vf); // CHECK: @llvm.ppc.altivec.lvewx - res_vsc = vec_lvebx(0, &vsc); // CHECK: @llvm.ppc.altivec.lvebx - res_vuc = vec_lvebx(0, &vuc); // CHECK: @llvm.ppc.altivec.lvebx - res_vs = vec_lvehx(0, &vs); // CHECK: @llvm.ppc.altivec.lvehx - res_vus = vec_lvehx(0, &vus); // CHECK: @llvm.ppc.altivec.lvehx - res_vi = vec_lvewx(0, &vi); // CHECK: @llvm.ppc.altivec.lvewx - res_vui = vec_lvewx(0, &vui); // CHECK: @llvm.ppc.altivec.lvewx - res_vf = vec_lvewx(0, &vf); // CHECK: @llvm.ppc.altivec.lvewx + res_vsc = vec_lde(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvebx + res_vuc = vec_lde(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvebx + res_vs = vec_lde(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvehx + res_vus = vec_lde(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvehx + res_vi = vec_lde(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvewx + res_vui = vec_lde(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvewx + res_vf = vec_lde(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvewx + res_vsc = vec_lvebx(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvebx + res_vuc = vec_lvebx(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvebx + res_vs = vec_lvehx(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvehx + res_vus = vec_lvehx(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvehx + res_vi = vec_lvewx(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvewx + res_vui = vec_lvewx(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvewx + res_vf = vec_lvewx(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvewx /* vec_ldl */ res_vsc = vec_ldl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl diff --git a/test/CodeGen/builtins-ppc.c b/test/CodeGen/builtins-ppc.c new file mode 100644 index 0000000..ee27a4c --- /dev/null +++ b/test/CodeGen/builtins-ppc.c @@ -0,0 +1,9 @@ +// REQUIRES: ppc32-registered-target +// RUN: %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +void test_eh_return_data_regno() +{ + volatile int res; + res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 3 + res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 4 +} diff --git a/test/CodeGen/builtinshufflevector2.c b/test/CodeGen/builtinshufflevector2.c index faf7a3e..ac0e07a 100644 --- a/test/CodeGen/builtinshufflevector2.c +++ b/test/CodeGen/builtinshufflevector2.c @@ -16,14 +16,14 @@ void clang_shufflevector_v_v( float4* A, float4 x, uint4 mask ) { // CHECK: [[I:%.*]] = extractelement <4 x i32> [[MASK]], i32 1 // CHECK: [[E:%.*]] = extractelement <4 x float> [[X]], i32 [[I]] -// CHECK: [[V:%.*]] = insertelement <4 x float> [[V]], float [[E]], i32 1 +// CHECK: [[V2:%.*]] = insertelement <4 x float> [[V]], float [[E]], i32 1 // CHECK: [[I:%.*]] = extractelement <4 x i32> [[MASK]], i32 2 // CHECK: [[E:%.*]] = extractelement <4 x float> [[X]], i32 [[I]] -// CHECK: [[V:%.*]] = insertelement <4 x float> [[V]], float [[E]], i32 2 +// CHECK: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[E]], i32 2 // CHECK: [[I:%.*]] = extractelement <4 x i32> [[MASK]], i32 3 // CHECK: [[E:%.*]] = extractelement <4 x float> [[X]], i32 [[I]] -// CHECK: [[V:%.*]] = insertelement <4 x float> [[V]], float [[E]], i32 3 -// CHECK: store <4 x float> [[V]], <4 x float>* {{%.*}}, +// CHECK: [[V4:%.*]] = insertelement <4 x float> [[V3]], float [[E]], i32 3 +// CHECK: store <4 x float> [[V4]], <4 x float>* {{%.*}}, *A = __builtin_shufflevector( x, mask ); } diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c index 4fbeb7b..1021010 100644 --- a/test/CodeGen/c-strings.c +++ b/test/CodeGen/c-strings.c @@ -1,36 +1,55 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: grep "hello" %t | count 3 -// RUN: grep 'c"hello\\00"' %t | count 2 -// RUN: grep 'c"hello\\00\\00\\00"' %t | count 1 -// RUN: grep 'c"ola"' %t | count 1 +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -/* Should be 3 hello string, two global (of different sizes), the rest - are shared. */ +// Should be 3 hello strings, two global (of different sizes), the rest are +// shared. +// CHECK: @.str = private unnamed_addr constant [6 x i8] c"hello\00" +// CHECK: @f1.x = internal global i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0) +// CHECK: @f2.x = internal global [6 x i8] c"hello\00", align 1 +// CHECK: @f3.x = internal global [8 x i8] c"hello\00\00\00", align 1 +// CHECK: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0) } +// CHECK: @x = global [3 x i8] c"ola", align 1 + +void bar(const char *); + +// CHECK: define void @f0() void f0() { bar("hello"); + // CHECK: call void @bar({{.*}} @.str } +// CHECK: define void @f1() void f1() { static char *x = "hello"; bar(x); + // CHECK: [[T1:%.*]] = load i8** @f1.x + // CHECK: call void @bar(i8* [[T1:%.*]]) } +// CHECK: define void @f2() void f2() { static char x[] = "hello"; bar(x); + // CHECK: call void @bar({{.*}} @f2.x } +// CHECK: define void @f3() void f3() { static char x[8] = "hello"; bar(x); + // CHECK: call void @bar({{.*}} @f3.x } +void gaz(void *); + +// CHECK: define void @f4() void f4() { static struct s { char *name; } x = { "hello" }; gaz(&x); + // CHECK: call void @gaz({{.*}} @f4.x } char x[3] = "ola"; + diff --git a/test/CodeGen/c11atomics-ios.c b/test/CodeGen/c11atomics-ios.c new file mode 100644 index 0000000..d1c9b14 --- /dev/null +++ b/test/CodeGen/c11atomics-ios.c @@ -0,0 +1,214 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-apple-ios -std=c11 | FileCheck %s + +// There isn't really anything special about iOS; it just happens to +// only deploy on processors with native atomics support, so it's a good +// way to test those code-paths. + +// This work was done in pursuit of <rdar://13338582>. + +// CHECK: define arm_aapcscc void @testFloat(float* +void testFloat(_Atomic(float) *fp) { +// CHECK: [[FP:%.*]] = alloca float* +// CHECK-NEXT: [[X:%.*]] = alloca float +// CHECK-NEXT: [[F:%.*]] = alloca float +// CHECK-NEXT: store float* {{%.*}}, float** [[FP]] + +// CHECK-NEXT: [[T0:%.*]] = load float** [[FP]] +// CHECK-NEXT: store float 1.000000e+00, float* [[T0]], align 4 + __c11_atomic_init(fp, 1.0f); + +// CHECK-NEXT: store float 2.000000e+00, float* [[X]], align 4 + _Atomic(float) x = 2.0f; + +// CHECK-NEXT: [[T0:%.*]] = load float** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast float* [[T0]] to i32* +// CHECK-NEXT: [[T2:%.*]] = load atomic i32* [[T1]] seq_cst, align 4 +// CHECK-NEXT: [[T3:%.*]] = bitcast i32 [[T2]] to float +// CHECK-NEXT: store float [[T3]], float* [[F]] + float f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load float* [[F]], align 4 +// CHECK-NEXT: [[T1:%.*]] = load float** [[FP]], align 4 +// CHECK-NEXT: [[T2:%.*]] = bitcast float [[T0]] to i32 +// CHECK-NEXT: [[T3:%.*]] = bitcast float* [[T1]] to i32* +// CHECK-NEXT: store atomic i32 [[T2]], i32* [[T3]] seq_cst, align 4 + *fp = f; + +// CHECK-NEXT: ret void +} + +// CHECK: define arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]* +void testComplexFloat(_Atomic(_Complex float) *fp) { +// CHECK: [[FP:%.*]] = alloca [[CF]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[CF]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: store [[CF]]* + +// CHECK-NEXT: [[P:%.*]] = load [[CF]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 1 +// CHECK-NEXT: store float 1.000000e+00, float* [[T0]] +// CHECK-NEXT: store float 0.000000e+00, float* [[T1]] + __c11_atomic_init(fp, 1.0f); + +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 1 +// CHECK-NEXT: store float 2.000000e+00, float* [[T0]] +// CHECK-NEXT: store float 0.000000e+00, float* [[T1]] + _Atomic(_Complex float) x = 2.0f; + +// CHECK-NEXT: [[T0:%.*]] = load [[CF]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[T0]] to i64* +// CHECK-NEXT: [[T2:%.*]] = load atomic i64* [[T1]] seq_cst, align 8 +// CHECK-NEXT: [[T3:%.*]] = bitcast [[CF]]* [[TMP0]] to i64* +// CHECK-NEXT: store i64 [[T2]], i64* [[T3]], align 8 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[R:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[I:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1 +// CHECK-NEXT: store float [[R]], float* [[T0]] +// CHECK-NEXT: store float [[I]], float* [[T1]] + _Complex float f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0 +// CHECK-NEXT: [[R:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1 +// CHECK-NEXT: [[I:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[DEST:%.*]] = load [[CF]]** [[FP]], align 4 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store float [[R]], float* [[T0]] +// CHECK-NEXT: store float [[I]], float* [[T1]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[CF]]* [[TMP1]] to i64* +// CHECK-NEXT: [[T1:%.*]] = load i64* [[T0]], align 8 +// CHECK-NEXT: [[T2:%.*]] = bitcast [[CF]]* [[DEST]] to i64* +// CHECK-NEXT: store atomic i64 [[T1]], i64* [[T2]] seq_cst, align 8 + *fp = f; + +// CHECK-NEXT: ret void +} + +typedef struct { short x, y, z, w; } S; +// CHECK: define arm_aapcscc void @testStruct([[S:.*]]* +void testStruct(_Atomic(S) *fp) { +// CHECK: [[FP:%.*]] = alloca [[S]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[S:%.*]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[S]], align 8 +// CHECK-NEXT: store [[S]]* + +// CHECK-NEXT: [[P:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[S]]* [[P]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 3 +// CHECK-NEXT: store i16 4, i16* [[T0]], align 2 + __c11_atomic_init(fp, (S){1,2,3,4}); + +// CHECK-NEXT: [[T0:%.*]] = bitcast [[S]]* [[X]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 3 +// CHECK-NEXT: store i16 4, i16* [[T0]], align 2 + _Atomic(S) x = (S){1,2,3,4}; + +// CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[T0]] to i64* +// CHECK-NEXT: [[T2:%.*]] = load atomic i64* [[T1]] seq_cst, align 8 +// CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[F]] to i64* +// CHECK-NEXT: store i64 [[T2]], i64* [[T3]], align 2 + S f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false) +// CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[TMP0]] to i64* +// CHECK-NEXT: [[T4:%.*]] = load i64* [[T3]], align 8 +// CHECK-NEXT: [[T5:%.*]] = bitcast [[S]]* [[T0]] to i64* +// CHECK-NEXT: store atomic i64 [[T4]], i64* [[T5]] seq_cst, align 8 + *fp = f; + +// CHECK-NEXT: ret void +} + +typedef struct { short x, y, z; } PS; +// CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]* +void testPromotedStruct(_Atomic(PS) *fp) { +// CHECK: [[FP:%.*]] = alloca [[APS]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[PS:%.*]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: store [[APS]]* + +// CHECK-NEXT: [[P:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T1]], align 2 + __c11_atomic_init(fp, (PS){1,2,3}); + +// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T1]], align 2 + _Atomic(PS) x = (PS){1,2,3}; + +// CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i64* +// CHECK-NEXT: [[T2:%.*]] = load atomic i64* [[T1]] seq_cst, align 8 +// CHECK-NEXT: [[T3:%.*]] = bitcast [[APS]]* [[TMP0]] to i64* +// CHECK-NEXT: store i64 [[T2]], i64* [[T3]], align 8 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false) + PS f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]]* [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false) +// CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[TMP1]] to i64* +// CHECK-NEXT: [[T5:%.*]] = load i64* [[T4]], align 8 +// CHECK-NEXT: [[T6:%.*]] = bitcast [[APS]]* [[T0]] to i64* +// CHECK-NEXT: store atomic i64 [[T5]], i64* [[T6]] seq_cst, align 8 + *fp = f; + +// CHECK-NEXT: ret void +} + +void testPromotedStructOps(_Atomic(PS) *p) { + PS a = __c11_atomic_load(p, 5); + __c11_atomic_store(p, a, 5); + PS b = __c11_atomic_exchange(p, a, 5); + + _Bool v = __c11_atomic_compare_exchange_strong(p, &b, a, 5, 5); + v = __c11_atomic_compare_exchange_weak(p, &b, a, 5, 5); +} diff --git a/test/CodeGen/c11atomics.c b/test/CodeGen/c11atomics.c new file mode 100644 index 0000000..8d298af --- /dev/null +++ b/test/CodeGen/c11atomics.c @@ -0,0 +1,344 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-freebsd -std=c11 | FileCheck %s + +// Test that we are generating atomicrmw instructions, rather than +// compare-exchange loops for common atomic ops. This makes a big difference +// on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for +// the load and then another ll/sc in the loop, expanding to about 30 +// instructions when it should be only 4. It has a smaller, but still +// noticeable, impact on platforms like x86 and RISC-V, where there are atomic +// RMW instructions. +// +// We currently emit cmpxchg loops for most operations on _Bools, because +// they're sufficiently rare that it's not worth making sure that the semantics +// are correct. + +typedef int __attribute__((vector_size(16))) vector; + +_Atomic(_Bool) b; +_Atomic(int) i; +_Atomic(long long) l; +_Atomic(short) s; +_Atomic(char*) p; +_Atomic(float) f; +_Atomic(vector) v; + +// CHECK: testinc +void testinc(void) +{ + // Special case for suffix bool++, sets to true and returns the old value. + // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst + b++; + // CHECK: atomicrmw add i32* @i, i32 1 seq_cst + i++; + // CHECK: atomicrmw add i64* @l, i64 1 seq_cst + l++; + // CHECK: atomicrmw add i16* @s, i16 1 seq_cst + s++; + // Prefix increment + // Special case for bool: set to true and return true + // CHECK: store atomic i8 1, i8* @b seq_cst, align 1 + ++b; + // Currently, we have no variant of atomicrmw that returns the new value, so + // we have to generate an atomic add, which returns the old value, and then a + // non-atomic add. + // CHECK: atomicrmw add i32* @i, i32 1 seq_cst + // CHECK: add i32 + ++i; + // CHECK: atomicrmw add i64* @l, i64 1 seq_cst + // CHECK: add i64 + ++l; + // CHECK: atomicrmw add i16* @s, i16 1 seq_cst + // CHECK: add i16 + ++s; +} +// CHECK: testdec +void testdec(void) +{ + // CHECK: cmpxchg i8* @b + b--; + // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst + i--; + // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst + l--; + // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst + s--; + // CHECK: cmpxchg i8* @b + --b; + // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst + // CHECK: sub i32 + --i; + // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst + // CHECK: sub i64 + --l; + // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst + // CHECK: sub i16 + --s; +} +// CHECK: testaddeq +void testaddeq(void) +{ + // CHECK: cmpxchg i8* @b + // CHECK: atomicrmw add i32* @i, i32 42 seq_cst + // CHECK: atomicrmw add i64* @l, i64 42 seq_cst + // CHECK: atomicrmw add i16* @s, i16 42 seq_cst + b += 42; + i += 42; + l += 42; + s += 42; +} +// CHECK: testsubeq +void testsubeq(void) +{ + // CHECK: cmpxchg i8* @b + // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst + // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst + // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst + b -= 42; + i -= 42; + l -= 42; + s -= 42; +} +// CHECK: testxoreq +void testxoreq(void) +{ + // CHECK: cmpxchg i8* @b + // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst + // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst + // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst + b ^= 42; + i ^= 42; + l ^= 42; + s ^= 42; +} +// CHECK: testoreq +void testoreq(void) +{ + // CHECK: cmpxchg i8* @b + // CHECK: atomicrmw or i32* @i, i32 42 seq_cst + // CHECK: atomicrmw or i64* @l, i64 42 seq_cst + // CHECK: atomicrmw or i16* @s, i16 42 seq_cst + b |= 42; + i |= 42; + l |= 42; + s |= 42; +} +// CHECK: testandeq +void testandeq(void) +{ + // CHECK: cmpxchg i8* @b + // CHECK: atomicrmw and i32* @i, i32 42 seq_cst + // CHECK: atomicrmw and i64* @l, i64 42 seq_cst + // CHECK: atomicrmw and i16* @s, i16 42 seq_cst + b &= 42; + i &= 42; + l &= 42; + s &= 42; +} + +// CHECK: define arm_aapcscc void @testFloat(float* +void testFloat(_Atomic(float) *fp) { +// CHECK: [[FP:%.*]] = alloca float* +// CHECK-NEXT: [[X:%.*]] = alloca float +// CHECK-NEXT: [[F:%.*]] = alloca float +// CHECK-NEXT: [[TMP0:%.*]] = alloca float +// CHECK-NEXT: [[TMP1:%.*]] = alloca float +// CHECK-NEXT: store float* {{%.*}}, float** [[FP]] + +// CHECK-NEXT: [[T0:%.*]] = load float** [[FP]] +// CHECK-NEXT: store float 1.000000e+00, float* [[T0]], align 4 + __c11_atomic_init(fp, 1.0f); + +// CHECK-NEXT: store float 2.000000e+00, float* [[X]], align 4 + _Atomic(float) x = 2.0f; + +// CHECK-NEXT: [[T0:%.*]] = load float** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast float* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast float* [[TMP0]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 4, i8* [[T1]], i8* [[T2]], i32 5) +// CHECK-NEXT: [[T3:%.*]] = load float* [[TMP0]], align 4 +// CHECK-NEXT: store float [[T3]], float* [[F]] + float f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load float* [[F]], align 4 +// CHECK-NEXT: [[T1:%.*]] = load float** [[FP]], align 4 +// CHECK-NEXT: store float [[T0]], float* [[TMP1]], align 4 +// CHECK-NEXT: [[T2:%.*]] = bitcast float* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = bitcast float* [[TMP1]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 4, i8* [[T2]], i8* [[T3]], i32 5) + *fp = f; + +// CHECK-NEXT: ret void +} + +// CHECK: define arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]* +void testComplexFloat(_Atomic(_Complex float) *fp) { +// CHECK: [[FP:%.*]] = alloca [[CF]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[CF]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = alloca [[CF]], align 8 +// CHECK-NEXT: store [[CF]]* + +// CHECK-NEXT: [[P:%.*]] = load [[CF]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 1 +// CHECK-NEXT: store float 1.000000e+00, float* [[T0]] +// CHECK-NEXT: store float 0.000000e+00, float* [[T1]] + __c11_atomic_init(fp, 1.0f); + +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 1 +// CHECK-NEXT: store float 2.000000e+00, float* [[T0]] +// CHECK-NEXT: store float 0.000000e+00, float* [[T1]] + _Atomic(_Complex float) x = 2.0f; + +// CHECK-NEXT: [[T0:%.*]] = load [[CF]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[CF]]* [[TMP0]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[R:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[I:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1 +// CHECK-NEXT: store float [[R]], float* [[T0]] +// CHECK-NEXT: store float [[I]], float* [[T1]] + _Complex float f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0 +// CHECK-NEXT: [[R:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1 +// CHECK-NEXT: [[I:%.*]] = load float* [[T0]] +// CHECK-NEXT: [[DEST:%.*]] = load [[CF]]** [[FP]], align 4 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store float [[R]], float* [[T0]] +// CHECK-NEXT: store float [[I]], float* [[T1]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[CF]]* [[DEST]] to i8* +// CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[TMP1]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T0]], i8* [[T1]], i32 5) + *fp = f; + +// CHECK-NEXT: ret void +} + +typedef struct { short x, y, z, w; } S; +// CHECK: define arm_aapcscc void @testStruct([[S:.*]]* +void testStruct(_Atomic(S) *fp) { +// CHECK: [[FP:%.*]] = alloca [[S]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[S:%.*]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[S]], align 8 +// CHECK-NEXT: store [[S]]* + +// CHECK-NEXT: [[P:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[S]]* [[P]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 3 +// CHECK-NEXT: store i16 4, i16* [[T0]], align 2 + __c11_atomic_init(fp, (S){1,2,3,4}); + +// CHECK-NEXT: [[T0:%.*]] = bitcast [[S]]* [[X]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T0]], align 2 +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 3 +// CHECK-NEXT: store i16 4, i16* [[T0]], align 2 + _Atomic(S) x = (S){1,2,3,4}; + +// CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5) + S f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false) +// CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[T0]] to i8* +// CHECK-NEXT: [[T4:%.*]] = bitcast [[S]]* [[TMP0]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T3]], i8* [[T4]], i32 5) + *fp = f; + +// CHECK-NEXT: ret void +} + +typedef struct { short x, y, z; } PS; +// CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]* +void testPromotedStruct(_Atomic(PS) *fp) { +// CHECK: [[FP:%.*]] = alloca [[APS]]*, align 4 +// CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: [[F:%.*]] = alloca [[PS:%.*]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = alloca [[APS]], align 8 +// CHECK-NEXT: store [[APS]]* + +// CHECK-NEXT: [[P:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[P]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T1]], align 2 + __c11_atomic_init(fp, (PS){1,2,3}); + +// CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8* +// CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[X]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0 +// CHECK-NEXT: store i16 1, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1 +// CHECK-NEXT: store i16 2, i16* [[T1]], align 2 +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2 +// CHECK-NEXT: store i16 3, i16* [[T1]], align 2 + _Atomic(PS) x = (PS){1,2,3}; + +// CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP0]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5) +// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false) + PS f = *fp; + +// CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]] +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]]* [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false) +// CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[T0]] to i8* +// CHECK-NEXT: [[T5:%.*]] = bitcast [[APS]]* [[TMP1]] to i8* +// CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T4]], i8* [[T5]], i32 5) + *fp = f; + +// CHECK-NEXT: ret void +} + +// CHECK: define arm_aapcscc void @testPromotedStructOps([[APS:.*]]* + +// FIXME: none of these look right, but we can leave the "test" here +// to make sure they at least don't crash. +void testPromotedStructOps(_Atomic(PS) *p) { + PS a = __c11_atomic_load(p, 5); + __c11_atomic_store(p, a, 5); + PS b = __c11_atomic_exchange(p, a, 5); + _Bool v = __c11_atomic_compare_exchange_strong(p, &b, a, 5, 5); + v = __c11_atomic_compare_exchange_weak(p, &b, a, 5, 5); +} diff --git a/test/CodeGen/catch-undef-behavior.c b/test/CodeGen/catch-undef-behavior.c index 4198b62..ebe39fe 100644 --- a/test/CodeGen/catch-undef-behavior.c +++ b/test/CodeGen/catch-undef-behavior.c @@ -1,14 +1,14 @@ -// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,divide-by-zero -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -fsanitize-undefined-trap-on-error -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-TRAP // RUN: %clang_cc1 -fsanitize=null -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-NULL // RUN: %clang_cc1 -fsanitize=signed-integer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-OVERFLOW // CHECK: @[[INT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" } // FIXME: When we only emit each type once, use [[INT]] more below. -// CHECK: @[[LINE_100:.*]] = private unnamed_addr constant {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i64 4, i8 1 +// CHECK: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i64 4, i8 1 // CHECK: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 {{.*}}, i64 4, i8 0 -// CHECK: @[[LINE_300_A:.*]] = {{.*}}, i32 300, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} -// CHECK: @[[LINE_300_B:.*]] = {{.*}}, i32 300, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} +// CHECK: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} // CHECK: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} // CHECK: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 {{.*}} @{{.*}}, i64 4, i8 0 } // CHECK: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 3 {{.*}} @{{.*}}, i64 4, i8 1 } @@ -19,49 +19,78 @@ // CHECK: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} } // CHECK: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} } -// CHECK-NULL: @[[LINE_100:.*]] = private unnamed_addr constant {{.*}}, i32 100, i32 5 {{.*}} +// CHECK-NULL: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} // PR6805 // CHECK: @foo // CHECK-NULL: @foo +// CHECK-TRAP: @foo void foo() { union { int i; } u; // CHECK: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null + // CHECK-TRAP: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null // CHECK: %[[I8PTR:.*]] = bitcast i32* %[[PTR]] to i8* // CHECK-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(i8* %[[I8PTR]], i1 false) // CHECK-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 // CHECK-NEXT: %[[CHECK01:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] + // CHECK-TRAP: %[[I8PTR:.*]] = bitcast i32* %[[PTR]] to i8* + // CHECK-TRAP-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64(i8* %[[I8PTR]], i1 false) + // CHECK-TRAP-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 + // CHECK-TRAP-NEXT: %[[CHECK01:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] + // CHECK: %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64 // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3 // CHECK-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 + // CHECK-TRAP: %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64 + // CHECK-TRAP-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3 + // CHECK-TRAP-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 + // CHECK: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] - // CHECK-NEXT: br i1 %[[OK]] + // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]] + + // CHECK-TRAP: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] + // CHECK-TRAP-NEXT: br i1 %[[OK]], {{.*}} // CHECK: %[[ARG:.*]] = ptrtoint {{.*}} %[[PTR]] to i64 - // CHECK-NEXT: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), i64 %[[ARG]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), i64 %[[ARG]]) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW:#[0-9]+]] + // CHECK-TRAP-NEXT: unreachable // With -fsanitize=null, only perform the null check. // CHECK-NULL: %[[NULL:.*]] = icmp ne {{.*}}, null // CHECK-NULL: br i1 %[[NULL]] - // CHECK-NULL: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), i64 %{{.*}}) noreturn nounwind + // CHECK-NULL: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), i64 %{{.*}}) #line 100 u.i=1; } // CHECK: @bar +// CHECK-TRAP: @bar int bar(int *a) { // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4 + // CHECK-TRAP: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 + // CHECK-TRAP-NEXT: icmp uge i64 %[[SIZE]], 4 + // CHECK: %[[PTRINT:.*]] = ptrtoint // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 + // CHECK-TRAP: %[[PTRINT:.*]] = ptrtoint + // CHECK-TRAP-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 + // CHECK-TRAP-NEXT: icmp eq i64 %[[MISALIGN]], 0 + // CHECK: %[[ARG:.*]] = ptrtoint - // CHECK-NEXT: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_200]] to i8*), i64 %[[ARG]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_200]] to i8*), i64 %[[ARG]]) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable + #line 200 return *a; } @@ -73,55 +102,92 @@ int addr_space(int __attribute__((address_space(256))) *a) { } // CHECK: @lsh_overflow +// CHECK-TRAP: @lsh_overflow int lsh_overflow(int a, int b) { // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 - // CHECK-NEXT: br i1 %[[INBOUNDS]] + // CHECK-NEXT: br i1 %[[INBOUNDS]], label %[[CHECKBB:.*]], label %[[CONTBB:.*]] - // FIXME: Only emit one trap block here. - // CHECK: %[[ARG1:.*]] = zext - // CHECK-NEXT: %[[ARG2:.*]] = zext - // CHECK-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_300_A]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) noreturn nounwind + // CHECK-TRAP: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]], label %[[CHECKBB:.*]], label %[[CONTBB:.*]] // CHECK: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]] // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]] // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT]], 0 - // CHECK-NEXT: br i1 %[[NO_OVERFLOW]] + // CHECK-NEXT: br label %[[CONTBB]] + + // CHECK-TRAP: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]] + // CHECK-TRAP-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]] + // CHECK-TRAP-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT]], 0 + // CHECK-TRAP-NEXT: br label %[[CONTBB]] + + // CHECK: %[[VALID:.*]] = phi i1 [ %[[INBOUNDS]], {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECKBB]] ] + // CHECK-NEXT: br i1 %[[VALID]], {{.*}} !prof ![[WEIGHT_MD]] + + // CHECK-TRAP: %[[VALID:.*]] = phi i1 [ %[[INBOUNDS]], {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECKBB]] ] + // CHECK-TRAP-NEXT: br i1 %[[VALID]] + // CHECK: %[[ARG1:.*]] = zext // CHECK-NEXT: %[[ARG2:.*]] = zext - // CHECK-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_300_B]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_300]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) + // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP: unreachable + // CHECK-TRAP-NOT: call void @llvm.trap() // CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]] // CHECK-NEXT: ret i32 %[[RET]] + + // CHECK-TRAP: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]] + // CHECK-TRAP-NEXT: ret i32 %[[RET]] #line 300 return a << b; } // CHECK: @rsh_inbounds +// CHECK-TRAP: @rsh_inbounds int rsh_inbounds(int a, int b) { - // CHECK: %[[INBOUNDS:.*]] = icmp ult i32 %[[RHS:.*]], 32 + // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 // CHECK: br i1 %[[INBOUNDS]] + // CHECK-TRAP: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 + // CHECK-TRAP: br i1 %[[INBOUNDS]] + // CHECK: %[[ARG1:.*]] = zext // CHECK-NEXT: %[[ARG2:.*]] = zext - // CHECK-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_400]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_400]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable // CHECK: %[[RET:.*]] = ashr i32 %[[LHS]], %[[RHS]] // CHECK-NEXT: ret i32 %[[RET]] + + // CHECK-TRAP: %[[RET:.*]] = ashr i32 %[[LHS]], %[[RHS]] + // CHECK-TRAP-NEXT: ret i32 %[[RET]] #line 400 return a >> b; } // CHECK: @load +// CHECK-TRAP: @load int load(int *p) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_500]] to i8*), i64 %{{.*}}) noreturn nounwind + // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_500]] to i8*), i64 %{{.*}}) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable #line 500 return *p; } // CHECK: @store +// CHECK-TRAP: @store void store(int *p, int q) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_600]] to i8*), i64 %{{.*}}) noreturn nounwind + // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_600]] to i8*), i64 %{{.*}}) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable #line 600 *p = q; } @@ -129,22 +195,31 @@ void store(int *p, int q) { struct S { int k; }; // CHECK: @member_access +// CHECK-TRAP: @member_access int *member_access(struct S *p) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_700]] to i8*), i64 %{{.*}}) noreturn nounwind + // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_700]] to i8*), i64 %{{.*}}) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable #line 700 return &p->k; } // CHECK: @signed_overflow +// CHECK-TRAP: @signed_overflow int signed_overflow(int a, int b) { // CHECK: %[[ARG1:.*]] = zext // CHECK-NEXT: %[[ARG2:.*]] = zext - // CHECK-NEXT: call void @__ubsan_handle_add_overflow(i8* bitcast ({{.*}} @[[LINE_800]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_add_overflow(i8* bitcast ({{.*}} @[[LINE_800]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable #line 800 return a + b; } // CHECK: @no_return +// CHECK-TRAP: @no_return int no_return() { // Reaching the end of a noreturn function is fine in C. // FIXME: If the user explicitly requests -fsanitize=return, we should catch @@ -152,6 +227,10 @@ int no_return() { // CHECK-NOT: call // CHECK-NOT: unreachable // CHECK: ret i32 + + // CHECK-TRAP-NOT: call + // CHECK-TRAP-NOT: unreachable + // CHECK-TRAP: ret i32 } // CHECK: @vla_bound @@ -159,7 +238,7 @@ void vla_bound(int n) { // CHECK: icmp sgt i32 %[[PARAM:.*]], 0 // // CHECK: %[[ARG:.*]] = zext i32 %[[PARAM]] to i64 - // CHECK-NEXT: call void @__ubsan_handle_vla_bound_not_positive(i8* bitcast ({{.*}} @[[LINE_900]] to i8*), i64 %[[ARG]]) noreturn nounwind + // CHECK-NEXT: call void @__ubsan_handle_vla_bound_not_positive(i8* bitcast ({{.*}} @[[LINE_900]] to i8*), i64 %[[ARG]]) #line 900 int arr[n * 3]; } @@ -171,55 +250,135 @@ float int_float_no_overflow(__int128 n) { } // CHECK: @int_float_overflow +// CHECK-TRAP: @int_float_overflow float int_float_overflow(unsigned __int128 n) { // This is 2**104. FLT_MAX is 2**128 - 2**104. // CHECK: icmp ule i128 %{{.*}}, -20282409603651670423947251286016 // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK-TRAP: %[[INBOUNDS:.*]] = icmp ule i128 %{{.*}}, -20282409603651670423947251286016 + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable return n; } // CHECK: @int_fp16_overflow +// CHECK-TRAP: @int_fp16_overflow void int_fp16_overflow(int n, __fp16 *p) { // CHECK: %[[GE:.*]] = icmp sge i32 %{{.*}}, -65504 // CHECK: %[[LE:.*]] = icmp sle i32 %{{.*}}, 65504 // CHECK: and i1 %[[GE]], %[[LE]] // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK-TRAP: %[[GE:.*]] = icmp sge i32 %{{.*}}, -65504 + // CHECK-TRAP: %[[LE:.*]] = icmp sle i32 %{{.*}}, 65504 + // CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable *p = n; } // CHECK: @float_int_overflow +// CHECK-TRAP: @float_int_overflow int float_int_overflow(float f) { - // CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0xC1E0000000000000 - // CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 0x41DFFFFFE0000000 + // CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000 + // CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000 // CHECK: and i1 %[[GE]], %[[LE]] - // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK: %[[CAST:.*]] = bitcast float %[[F]] to i32 + // CHECK: %[[ARG:.*]] = zext i32 %[[CAST]] to i64 + // CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]] + + // CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000 + // CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000 + // CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable return f; } +// CHECK: @long_double_int_overflow +// CHECK-TRAP: @long_double_int_overflow +int long_double_int_overflow(long double ld) { + // CHECK: alloca x86_fp80 + // CHECK: %[[GE:.*]] = fcmp ogt x86_fp80 %[[F:.*]], 0xKC01E8000000100000000 + // CHECK: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E8000000000000000 + // CHECK: and i1 %[[GE]], %[[LE]] + + // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]] + // CHECK: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64 + // CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]] + + // CHECK-TRAP: %[[GE:.*]] = fcmp ogt x86_fp80 %[[F:.*]], 0xKC01E800000010000000 + // CHECK-TRAP: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E800000000000000 + // CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable + return ld; +} + // CHECK: @float_uint_overflow +// CHECK-TRAP: @float_uint_overflow unsigned float_uint_overflow(float f) { - // CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0.{{0*}}e+00 - // CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 0x41EFFFFFE0000000 + // CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.{{0*}}e+00 + // CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 0x41F0000000000000 // CHECK: and i1 %[[GE]], %[[LE]] // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.{{0*}}e+00 + // CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 0x41F0000000000000 + // CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable return f; } // CHECK: @fp16_char_overflow +// CHECK-TRAP: @fp16_char_overflow signed char fp16_char_overflow(__fp16 *p) { - // CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], -1.28{{0*}}e+02 - // CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 1.27{{0*}}e+02 + // CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.29{{0*}}e+02 + // CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 1.28{{0*}}e+02 // CHECK: and i1 %[[GE]], %[[LE]] // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.29{{0*}}e+02 + // CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 1.28{{0*}}e+02 + // CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable return *p; } // CHECK: @float_float_overflow +// CHECK-TRAP: @float_float_overflow float float_float_overflow(double f) { - // CHECK: %[[GE:.*]] = fcmp oge double %[[F:.*]], 0xC7EFFFFFE0000000 - // CHECK: %[[LE:.*]] = fcmp ole double %[[F]], 0x47EFFFFFE0000000 + // CHECK: %[[F:.*]] = call double @llvm.fabs.f64( + // CHECK: %[[GE:.*]] = fcmp ogt double %[[F]], 0x47EFFFFFE0000000 + // CHECK: %[[LE:.*]] = fcmp olt double %[[F]], 0x7FF0000000000000 // CHECK: and i1 %[[GE]], %[[LE]] // CHECK: call void @__ubsan_handle_float_cast_overflow( + + // CHECK-TRAP: %[[F:.*]] = call double @llvm.fabs.f64( + // CHECK-TRAP: %[[GE:.*]] = fcmp ogt double %[[F]], 0x47EFFFFFE0000000 + // CHECK-TRAP: %[[LE:.*]] = fcmp olt double %[[F]], 0x7FF0000000000000 + // CHECK-TRAP: %[[OUTOFBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-TRAP: %[[INBOUNDS:.*]] = xor i1 %[[OUTOFBOUNDS]], true + // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP-NEXT: unreachable return f; } @@ -228,6 +387,7 @@ float float_float_overflow(double f) { int int_divide_overflow(int a, int b) { // CHECK: %[[ZERO:.*]] = icmp ne i32 %[[B:.*]], 0 // CHECK-OVERFLOW-NOT: icmp ne i32 %{{.*}}, 0 + // CHECK-TRAP: %[[ZERO:.*]] = icmp ne i32 %[[B:.*]], 0 // CHECK: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 // CHECK-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B]], -1 @@ -237,12 +397,41 @@ int int_divide_overflow(int a, int b) { // CHECK-OVERFLOW-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B:.*]], -1 // CHECK-OVERFLOW-NEXT: %[[OK:.*]] = or i1 %[[AOK]], %[[BOK]] + // CHECK-TRAP: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 + // CHECK-TRAP-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B]], -1 + // CHECK-TRAP-NEXT: %[[OVER:.*]] = or i1 %[[AOK]], %[[BOK]] + // CHECK: %[[OK:.*]] = and i1 %[[ZERO]], %[[OVER]] // CHECK: br i1 %[[OK]] // CHECK-OVERFLOW: br i1 %[[OK]] + + // CHECK-TRAP: %[[OK:.*]] = and i1 %[[ZERO]], %[[OVER]] + // CHECK-TRAP: br i1 %[[OK]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP: unreachable return a / b; // CHECK: } // CHECK-OVERFLOW: } + // CHECK-TRAP: } } + +// CHECK: @sour_bool +_Bool sour_bool(_Bool *p) { + // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 + // CHECK: br i1 %[[OK]] + // CHECK: call void @__ubsan_handle_load_invalid_value(i8* bitcast ({{.*}}), i64 {{.*}}) + + // CHECK-TRAP: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 + // CHECK-TRAP: br i1 %[[OK]] + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP: unreachable + return *p; +} + +// CHECK: ![[WEIGHT_MD]] = metadata !{metadata !"branch_weights", i32 1048575, i32 1} + +// CHECK-TRAP: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/CodeGen/code-coverage.c b/test/CodeGen/code-coverage.c new file mode 100644 index 0000000..1b87d64 --- /dev/null +++ b/test/CodeGen/code-coverage.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-no-function-names-in-data %s -o - | FileCheck %s --check-prefix WITHOUTNAMES + +// <rdar://problem/12843084> + +int test1(int a) { + switch (a % 2) { + case 0: + ++a; + case 1: + a /= 2; + } + return a; +} + +// Check that the noredzone flag is set on the generated functions. + +// CHECK: void @__llvm_gcov_indirect_counter_increment(i32* %{{.*}}, i64** %{{.*}}) unnamed_addr [[NRZ:#[0-9]+]] + +// Inside llvm_gcov_writeout, check that -coverage-no-function-names-in-data +// passes null as the function name. +// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ]] +// CHECK: call void @llvm_gcda_emit_function({{.*}}, i8* getelementptr {{.*}}, {{.*}}) +// WITHOUTNAMES: void @__llvm_gcov_writeout() unnamed_addr +// WITHOUTNAMES: call void @llvm_gcda_emit_function({{.*}}, i8* null, {{.*}}) + +// CHECK: void @__llvm_gcov_flush() unnamed_addr [[NRZ]] +// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]] + +// CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} } diff --git a/test/CodeGen/complex-convert.c b/test/CodeGen/complex-convert.c new file mode 100644 index 0000000..aaa57a0 --- /dev/null +++ b/test/CodeGen/complex-convert.c @@ -0,0 +1,717 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +// Test conversions between complex integer types and standard integer +// types. Tests binary operator conversion and assignment conversion +// with widening, narrowing, and equal-size operands. Signed and unsigned +// variations. Attempts to work for all targets. Assumptions: +// +// * "char" and "long long" are of different lengths (CHSIZE and LLSIZE). +// * Arithmetic is not performed directly on "char" type. + +void foo(signed char sc, unsigned char uc, signed long long sll, + unsigned long long ull, _Complex signed char csc, + _Complex unsigned char cuc, _Complex signed long long csll, + _Complex unsigned long long cull) { + + signed char sc1; + unsigned char uc1; + signed long long sll1; + unsigned long long ull1; + _Complex signed char csc1; + _Complex unsigned char cuc1; + _Complex signed long long csll1; + _Complex unsigned long long cull1; + // CHECK: define void @foo( + // CHECK: alloca i[[CHSIZE:[0-9]+]], align [[CHALIGN:[0-9]+]] + // CHECK-NEXT: alloca i[[CHSIZE]], align [[CHALIGN]] + // CHECK-NEXT: alloca i[[LLSIZE:[0-9]+]], align [[LLALIGN:[0-9]+]] + + sc1 = csc; + // CHECK: %[[VAR1:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR2:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR1]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR2]], i[[CHSIZE]]* %[[SC1:[A-Za-z0-9.]+]], align [[CHALIGN]] + + sc1 = cuc; + // CHECK-NEXT: %[[VAR3:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR4:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR3]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR4]], i[[CHSIZE]]* %[[SC1]], align [[CHALIGN]] + + sc1 = csll; + // CHECK-NEXT: %[[VAR5:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR6:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR5]] + // CHECK-NEXT: %[[VAR7:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR6]] to i[[CHSIZE]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR7]], i[[CHSIZE]]* %[[SC1]], align [[CHALIGN]] + + sc1 = cull; + // CHECK-NEXT: %[[VAR8:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR9:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR8]] + // CHECK-NEXT: %[[VAR10:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR9]] to i[[CHSIZE]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR10]], i[[CHSIZE]]* %[[SC1]], align [[CHALIGN]] + + uc1 = csc; + // CHECK-NEXT: %[[VAR11:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR12:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR11]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR12]], i[[CHSIZE]]* %[[UC1:[A-Za-z0-9.]+]], align [[CHALIGN]] + + uc1 = cuc; + // CHECK-NEXT: %[[VAR13:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR14:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR13]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR14]], i[[CHSIZE]]* %[[UC1]], align [[CHALIGN]] + + uc1 = csll; + // CHECK-NEXT: %[[VAR15:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR16:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR15]] + // CHECK-NEXT: %[[VAR17:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR16]] to i[[CHSIZE]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR17]], i[[CHSIZE]]* %[[UC1]], align [[CHALIGN]] + + uc1 = cull; + // CHECK-NEXT: %[[VAR18:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR19:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR18]] + // CHECK-NEXT: %[[VAR20:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR19]] to i[[CHSIZE]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR20]], i[[CHSIZE]]* %[[UC1]], align [[CHALIGN]] + + sll1 = csc; + // CHECK-NEXT: %[[VAR21:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR22:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR21]] + // CHECK-NEXT: %[[VAR23:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR22]] to i[[LLSIZE]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR23]], i[[LLSIZE]]* %[[SLL1:[A-Za-z0-9]+]], align [[LLALIGN]] + + sll1 = cuc; + // CHECK-NEXT: %[[VAR24:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR25:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR24]] + // CHECK-NEXT: %[[VAR26:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR25]] to i[[LLSIZE]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR26]], i[[LLSIZE]]* %[[SLL1]], align [[LLALIGN]] + + sll1 = csll; + // CHECK-NEXT: %[[VAR27:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR28:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR27]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR28]], i[[LLSIZE]]* %[[SLL1]], align [[LLALIGN]] + + sll1 = cull; + // CHECK-NEXT: %[[VAR29:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR30:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR29]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR30]], i[[LLSIZE]]* %[[SLL1]], align [[LLALIGN]] + + ull1 = csc; + // CHECK-NEXT: %[[VAR31:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR32:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR31]] + // CHECK-NEXT: %[[VAR33:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR32]] to i[[LLSIZE]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR33]], i[[LLSIZE]]* %[[ULL1:[A-Za-z0-9]+]], align [[LLALIGN]] + + ull1 = cuc; + // CHECK-NEXT: %[[VAR34:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR35:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR34]] + // CHECK-NEXT: %[[VAR36:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR35]] to i[[LLSIZE]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR36]], i[[LLSIZE]]* %[[ULL1]], align [[LLALIGN]] + + ull1 = csll; + // CHECK-NEXT: %[[VAR37:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR38:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR37]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR38]], i[[LLSIZE]]* %[[ULL1]], align [[LLALIGN]] + + ull1 = cull; + // CHECK-NEXT: %[[VAR39:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR40:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR39]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR40]], i[[LLSIZE]]* %[[ULL1]], align [[LLALIGN]] + + csc1 = sc; + // CHECK-NEXT: %[[VAR41:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR:[A-Za-z0-9.]+]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR42:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR43:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR41]], i[[CHSIZE]]* %[[VAR42]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR43]] + + csc1 = uc; + // CHECK-NEXT: %[[VAR44:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR:[A-Za-z0-9.]+]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR45:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR46:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR44]], i[[CHSIZE]]* %[[VAR45]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR46]] + + csc1 = sll; + // CHECK-NEXT: %[[VAR47:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR:[A-Za-z0-9.]+]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR48:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR47]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR49:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR50:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR48]], i[[CHSIZE]]* %[[VAR49]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR50]] + + csc1 = ull; + // CHECK-NEXT: %[[VAR51:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR:[A-Za-z0-9.]+]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR52:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR51]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR53:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR54:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR52]], i[[CHSIZE]]* %[[VAR53]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR54]] + + cuc1 = sc; + // CHECK-NEXT: %[[VAR55:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR56:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR57:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR55]], i[[CHSIZE]]* %[[VAR56]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR57]] + + cuc1 = uc; + // CHECK-NEXT: %[[VAR58:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR59:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR60:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR58]], i[[CHSIZE]]* %[[VAR59]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR60]] + + cuc1 = sll; + // CHECK-NEXT: %[[VAR61:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR62:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR61]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR63:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR64:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR62]], i[[CHSIZE]]* %[[VAR63]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR64]] + + cuc1 = ull; + // CHECK-NEXT: %[[VAR65:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR66:[A-Za-z0-9.]+]] = trunc i[[LLSIZE]] %[[VAR65]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR67:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR68:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR66]], i[[CHSIZE]]* %[[VAR67]] + // CHECK-NEXT: store i[[CHSIZE]] 0, i[[CHSIZE]]* %[[VAR68]] + + csll1 = sc; + // CHECK-NEXT: %[[VAR69:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR70:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR69]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR71:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR72:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR70]], i[[LLSIZE]]* %[[VAR71]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR72]] + + csll1 = uc; + // CHECK-NEXT: %[[VAR73:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR74:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR73]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR75:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR76:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR74]], i[[LLSIZE]]* %[[VAR75]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR76]] + + csll1 = sll; + // CHECK-NEXT: %[[VAR77:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR78:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR79:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR77]], i[[LLSIZE]]* %[[VAR78]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR79]] + + csll1 = ull; + // CHECK-NEXT: %[[VAR77:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR78:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR79:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR77]], i[[LLSIZE]]* %[[VAR78]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR79]] + + cull1 = sc; + // CHECK-NEXT: %[[VAR80:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR81:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR80]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR82:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1:[A-Za-z0-9.]+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR83:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR81]], i[[LLSIZE]]* %[[VAR82]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR83]] + + cull1 = uc; + // CHECK-NEXT: %[[VAR84:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR85:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR84]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR86:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR87:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR85]], i[[LLSIZE]]* %[[VAR86]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR87]] + + cull1 = sll; + // CHECK-NEXT: %[[VAR88:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR89:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR90:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR88]], i[[LLSIZE]]* %[[VAR89]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR90]] + + cull1 = ull; + // CHECK-NEXT: %[[VAR91:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR92:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR93:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR91]], i[[LLSIZE]]* %[[VAR92]] + // CHECK-NEXT: store i[[LLSIZE]] 0, i[[LLSIZE]]* %[[VAR93]] + + csc1 = sc + csc; + // CHECK-NEXT: %[[VAR94:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR95:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR94]] to i[[ARSIZE:[0-9]+]] + // CHECK-NEXT: %[[VAR96:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR97:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR96]] + // CHECK-NEXT: %[[VAR98:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR99:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR98]] + // CHECK-NEXT: %[[VAR100:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR97]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR101:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR99]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR102:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR95]], %[[VAR100]] + // CHECK-NEXT: %[[VAR103:[A-Za-z0-9.]+]] = add i[[ARSIZE]] 0, %[[VAR101]] + // CHECK-NEXT: %[[VAR104:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR102]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR105:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR103]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR106:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR107:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR104]], i[[CHSIZE]]* %[[VAR106]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR105]], i[[CHSIZE]]* %[[VAR107]] + + cuc1 = sc + cuc; + // CHECK-NEXT: %[[VAR108:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR109:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR108]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR110:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR111:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR110]] + // CHECK-NEXT: %[[VAR112:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR113:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR112]] + // CHECK-NEXT: %[[VAR114:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR111]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR115:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR113]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR116:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR109]], %[[VAR114]] + // CHECK-NEXT: %[[VAR117:[A-Za-z0-9.]+]] = add i[[ARSIZE]] 0, %[[VAR115]] + // CHECK-NEXT: %[[VAR118:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR116]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR119:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR117]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR120:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR121:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR118]], i[[CHSIZE]]* %[[VAR120]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR119]], i[[CHSIZE]]* %[[VAR121]] + + csll1 = sc + csll; + // CHECK-NEXT: %[[VAR122:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR123:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR122]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR124:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR125:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR124]] + // CHECK-NEXT: %[[VAR126:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR127:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR126]] + // CHECK-NEXT: %[[VAR128:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR123]], %[[VAR125]] + // CHECK-NEXT: %[[VAR129:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR127]] + // CHECK-NEXT: %[[VAR130:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR131:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR128]], i[[LLSIZE]]* %[[VAR130]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR129]], i[[LLSIZE]]* %[[VAR131]] + + cull1 = sc + cull; + // CHECK-NEXT: %[[VAR132:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR133:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR132]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR134:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR135:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR134]] + // CHECK-NEXT: %[[VAR136:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR137:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR136]] + // CHECK-NEXT: %[[VAR138:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR133]], %[[VAR135]] + // CHECK-NEXT: %[[VAR139:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR137]] + // CHECK-NEXT: %[[VAR140:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR141:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR138]], i[[LLSIZE]]* %[[VAR140]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR139]], i[[LLSIZE]]* %[[VAR141]] + + csc1 = uc + csc; + // CHECK-NEXT: %[[VAR142:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR143:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR142]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR144:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR145:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR144]] + // CHECK-NEXT: %[[VAR146:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR147:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR146]] + // CHECK-NEXT: %[[VAR148:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR145]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR149:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR147]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR150:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR143]], %[[VAR148]] + // CHECK-NEXT: %[[VAR151:[A-Za-z0-9.]+]] = add i[[ARSIZE]] 0, %[[VAR149]] + // CHECK-NEXT: %[[VAR152:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR150]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR153:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR151]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR154:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR155:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR152]], i[[CHSIZE]]* %[[VAR154]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR153]], i[[CHSIZE]]* %[[VAR155]] + + cuc1 = uc + cuc; + // CHECK-NEXT: %[[VAR156:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR157:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR156]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR158:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR159:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR158]] + // CHECK-NEXT: %[[VAR160:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR161:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR160]] + // CHECK-NEXT: %[[VAR162:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR159]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR163:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR161]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR164:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR157]], %[[VAR162]] + // CHECK-NEXT: %[[VAR165:[A-Za-z0-9.]+]] = add i[[ARSIZE]] 0, %[[VAR163]] + // CHECK-NEXT: %[[VAR166:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR164]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR167:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR165]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR168:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR169:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR166]], i[[CHSIZE]]* %[[VAR168]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR167]], i[[CHSIZE]]* %[[VAR169]] + + csll1 = uc + csll; + // CHECK-NEXT: %[[VAR170:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR171:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR170]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR172:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR173:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR172]] + // CHECK-NEXT: %[[VAR174:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR175:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR174]] + // CHECK-NEXT: %[[VAR176:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR171]], %[[VAR173]] + // CHECK-NEXT: %[[VAR177:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR175]] + // CHECK-NEXT: %[[VAR178:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR179:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR176]], i[[LLSIZE]]* %[[VAR178]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR177]], i[[LLSIZE]]* %[[VAR179]] + + cull1 = uc + cull; + // CHECK-NEXT: %[[VAR180:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR181:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR180]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR182:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR183:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR182]] + // CHECK-NEXT: %[[VAR184:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR185:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR184]] + // CHECK-NEXT: %[[VAR186:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR181]], %[[VAR183]] + // CHECK-NEXT: %[[VAR187:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR185]] + // CHECK-NEXT: %[[VAR188:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR189:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR186]], i[[LLSIZE]]* %[[VAR188]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR187]], i[[LLSIZE]]* %[[VAR189]] + + csll1 = sll + csc; + // CHECK-NEXT: %[[VAR190:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR191:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR192:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR191]] + // CHECK-NEXT: %[[VAR193:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR194:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR193]] + // CHECK-NEXT: %[[VAR195:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR192]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR196:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR194]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR197:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR190]], %[[VAR195]] + // CHECK-NEXT: %[[VAR198:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR196]] + // CHECK-NEXT: %[[VAR199:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR200:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR197]], i[[LLSIZE]]* %[[VAR199]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR198]], i[[LLSIZE]]* %[[VAR200]] + + csll1 = sll + cuc; + // CHECK-NEXT: %[[VAR201:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR202:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR203:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR202]] + // CHECK-NEXT: %[[VAR204:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR205:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR204]] + // CHECK-NEXT: %[[VAR206:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR203]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR207:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR205]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR208:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR201]], %[[VAR206]] + // CHECK-NEXT: %[[VAR209:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR207]] + // CHECK-NEXT: %[[VAR210:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR211:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR208]], i[[LLSIZE]]* %[[VAR210]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR209]], i[[LLSIZE]]* %[[VAR211]] + + csll1 = sll + csll; + // CHECK-NEXT: %[[VAR212:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR213:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR214:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR213]] + // CHECK-NEXT: %[[VAR215:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR216:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR215]] + // CHECK-NEXT: %[[VAR217:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR212]], %[[VAR214]] + // CHECK-NEXT: %[[VAR218:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR216]] + // CHECK-NEXT: %[[VAR219:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR220:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR217]], i[[LLSIZE]]* %[[VAR219]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR218]], i[[LLSIZE]]* %[[VAR220]] + + csll1 = sll + cull; + // CHECK-NEXT: %[[VAR221:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR222:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR223:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR222]] + // CHECK-NEXT: %[[VAR224:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR225:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR224]] + // CHECK-NEXT: %[[VAR226:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR221]], %[[VAR223]] + // CHECK-NEXT: %[[VAR227:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR225]] + // CHECK-NEXT: %[[VAR228:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR229:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR226]], i[[LLSIZE]]* %[[VAR228]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR227]], i[[LLSIZE]]* %[[VAR229]] + + csll1 = ull + csc; + // CHECK-NEXT: %[[VAR230:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR231:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR232:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR231]] + // CHECK-NEXT: %[[VAR233:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR234:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR233]] + // CHECK-NEXT: %[[VAR235:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR232]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR236:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR234]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR237:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR230]], %[[VAR235]] + // CHECK-NEXT: %[[VAR238:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR236]] + // CHECK-NEXT: %[[VAR239:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR240:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR237]], i[[LLSIZE]]* %[[VAR239]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR238]], i[[LLSIZE]]* %[[VAR240]] + + cull1 = ull + cuc; + // CHECK-NEXT: %[[VAR241:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR242:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR243:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR242]] + // CHECK-NEXT: %[[VAR244:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR245:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR244]] + // CHECK-NEXT: %[[VAR246:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR243]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR247:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR245]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR248:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR241]], %[[VAR246]] + // CHECK-NEXT: %[[VAR249:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR247]] + // CHECK-NEXT: %[[VAR250:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR251:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR248]], i[[LLSIZE]]* %[[VAR250]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR249]], i[[LLSIZE]]* %[[VAR251]] + + csll1 = ull + csll; + // CHECK-NEXT: %[[VAR252:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR253:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR254:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR253]] + // CHECK-NEXT: %[[VAR255:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR256:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR255]] + // CHECK-NEXT: %[[VAR257:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR252]], %[[VAR254]] + // CHECK-NEXT: %[[VAR258:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR256]] + // CHECK-NEXT: %[[VAR259:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR260:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR257]], i[[LLSIZE]]* %[[VAR259]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR258]], i[[LLSIZE]]* %[[VAR260]] + + cull1 = ull + cull; + // CHECK-NEXT: %[[VAR261:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR262:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR263:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR262]] + // CHECK-NEXT: %[[VAR264:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR265:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR264]] + // CHECK-NEXT: %[[VAR266:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR261]], %[[VAR263]] + // CHECK-NEXT: %[[VAR267:[A-Za-z0-9.]+]] = add i[[LLSIZE]] 0, %[[VAR265]] + // CHECK-NEXT: %[[VAR268:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR269:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR266]], i[[LLSIZE]]* %[[VAR268]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR267]], i[[LLSIZE]]* %[[VAR269]] + + csc1 = csc + sc; + // CHECK-NEXT: %[[VAR270:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR271:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR270]] + // CHECK-NEXT: %[[VAR272:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR273:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR272]] + // CHECK-NEXT: %[[VAR274:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR271]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR275:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR273]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR276:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR277:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR276]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR278:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR274]], %[[VAR277]] + // CHECK-NEXT: %[[VAR279:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR275]], 0 + // CHECK-NEXT: %[[VAR280:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR278]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR281:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR279]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR282:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR283:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR280]], i[[CHSIZE]]* %[[VAR282]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR281]], i[[CHSIZE]]* %[[VAR283]] + + csc1 = csc + uc; + // CHECK-NEXT: %[[VAR284:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR285:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR284]] + // CHECK-NEXT: %[[VAR286:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR287:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR286]] + // CHECK-NEXT: %[[VAR288:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR285]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR289:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR287]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR290:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR291:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR290]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR292:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR288]], %[[VAR291]] + // CHECK-NEXT: %[[VAR293:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR289]], 0 + // CHECK-NEXT: %[[VAR294:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR292]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR295:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR293]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR296:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR297:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR294]], i[[CHSIZE]]* %[[VAR296]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR295]], i[[CHSIZE]]* %[[VAR297]] + + csll1 = csc + sll; + // CHECK-NEXT: %[[VAR298:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR299:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR298]] + // CHECK-NEXT: %[[VAR300:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR301:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR300]] + // CHECK-NEXT: %[[VAR302:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR299]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR303:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR301]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR304:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR305:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR302]], %[[VAR304]] + // CHECK-NEXT: %[[VAR306:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR303]], 0 + // CHECK-NEXT: %[[VAR307:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR308:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR305]], i[[LLSIZE]]* %[[VAR307]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR306]], i[[LLSIZE]]* %[[VAR308]] + + csll1 = csc + ull; + // CHECK-NEXT: %[[VAR309:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR310:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR309]] + // CHECK-NEXT: %[[VAR311:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR312:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR311]] + // CHECK-NEXT: %[[VAR313:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR310]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR314:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR312]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR315:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR316:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR313]], %[[VAR315]] + // CHECK-NEXT: %[[VAR317:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR314]], 0 + // CHECK-NEXT: %[[VAR318:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR319:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR316]], i[[LLSIZE]]* %[[VAR318]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR317]], i[[LLSIZE]]* %[[VAR319]] + + csc1 = cuc + sc; + // CHECK-NEXT: %[[VAR320:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR321:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR320]] + // CHECK-NEXT: %[[VAR322:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR323:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR322]] + // CHECK-NEXT: %[[VAR324:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR321]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR325:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR323]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR326:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR327:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR326]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR328:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR324]], %[[VAR327]] + // CHECK-NEXT: %[[VAR329:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR325]], 0 + // CHECK-NEXT: %[[VAR330:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR328]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR331:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR329]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR332:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR333:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CSC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR330]], i[[CHSIZE]]* %[[VAR332]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR331]], i[[CHSIZE]]* %[[VAR333]] + + cuc1 = cuc + uc; + // CHECK-NEXT: %[[VAR334:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR335:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR334]] + // CHECK-NEXT: %[[VAR336:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR337:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR336]] + // CHECK-NEXT: %[[VAR338:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR335]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR339:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR337]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR340:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR341:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR340]] to i[[ARSIZE]] + // CHECK-NEXT: %[[VAR342:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR338]], %[[VAR341]] + // CHECK-NEXT: %[[VAR343:[A-Za-z0-9.]+]] = add i[[ARSIZE]] %[[VAR339]], 0 + // CHECK-NEXT: %[[VAR344:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR342]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR345:[A-Za-z0-9.]+]] = trunc i[[ARSIZE]] %[[VAR343]] to i[[CHSIZE]] + // CHECK-NEXT: %[[VAR346:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR347:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR344]], i[[CHSIZE]]* %[[VAR346]] + // CHECK-NEXT: store i[[CHSIZE]] %[[VAR345]], i[[CHSIZE]]* %[[VAR347]] + + csll1 = cuc + sll; + // CHECK-NEXT: %[[VAR348:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR349:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR348]] + // CHECK-NEXT: %[[VAR350:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR351:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR350]] + // CHECK-NEXT: %[[VAR352:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR349]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR353:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR351]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR354:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR355:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR352]], %[[VAR354]] + // CHECK-NEXT: %[[VAR356:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR353]], 0 + // CHECK-NEXT: %[[VAR357:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR358:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR355]], i[[LLSIZE]]* %[[VAR357]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR356]], i[[LLSIZE]]* %[[VAR358]] + + cull1 = cuc + ull; + // CHECK-NEXT: %[[VAR357:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR358:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR357]] + // CHECK-NEXT: %[[VAR359:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[CHSIZE]], i[[CHSIZE]] }* %[[CUC]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR360:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[VAR359]] + // CHECK-NEXT: %[[VAR361:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR358]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR362:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR360]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR363:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR364:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR361]], %[[VAR363]] + // CHECK-NEXT: %[[VAR365:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR362]], 0 + // CHECK-NEXT: %[[VAR366:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR367:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR364]], i[[LLSIZE]]* %[[VAR366]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR365]], i[[LLSIZE]]* %[[VAR367]] + + csll1 = csll + sc; + // CHECK-NEXT: %[[VAR368:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR369:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR368]] + // CHECK-NEXT: %[[VAR370:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR371:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR370]] + // CHECK-NEXT: %[[VAR372:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR373:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR372]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR374:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR369]], %[[VAR373]] + // CHECK-NEXT: %[[VAR375:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR371]], 0 + // CHECK-NEXT: %[[VAR376:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR377:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR374]], i[[LLSIZE]]* %[[VAR376]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR375]], i[[LLSIZE]]* %[[VAR377]] + + csll1 = csll + uc; + // CHECK-NEXT: %[[VAR378:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR379:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR378]] + // CHECK-NEXT: %[[VAR380:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR381:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR380]] + // CHECK-NEXT: %[[VAR382:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR383:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR382]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR384:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR379]], %[[VAR383]] + // CHECK-NEXT: %[[VAR385:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR381]], 0 + // CHECK-NEXT: %[[VAR386:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR387:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR384]], i[[LLSIZE]]* %[[VAR386]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR385]], i[[LLSIZE]]* %[[VAR387]] + + csll1 = csll + sll; + // CHECK-NEXT: %[[VAR388:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR389:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR388]] + // CHECK-NEXT: %[[VAR390:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR391:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR390]] + // CHECK-NEXT: %[[VAR392:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR393:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR389]], %[[VAR392]] + // CHECK-NEXT: %[[VAR394:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR391]], 0 + // CHECK-NEXT: %[[VAR395:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR396:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR393]], i[[LLSIZE]]* %[[VAR395]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR394]], i[[LLSIZE]]* %[[VAR396]] + + csll1 = csll + ull; + // CHECK-NEXT: %[[VAR397:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR398:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR397]] + // CHECK-NEXT: %[[VAR399:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR400:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR399]] + // CHECK-NEXT: %[[VAR401:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR402:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR398]], %[[VAR401]] + // CHECK-NEXT: %[[VAR403:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR400]], 0 + // CHECK-NEXT: %[[VAR404:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR405:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR402]], i[[LLSIZE]]* %[[VAR404]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR403]], i[[LLSIZE]]* %[[VAR405]] + + csll1 = cull + sc; + // CHECK-NEXT: %[[VAR406:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR407:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR406]] + // CHECK-NEXT: %[[VAR408:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR409:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR408]] + // CHECK-NEXT: %[[VAR410:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[SCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR411:[A-Za-z0-9.]+]] = sext i[[CHSIZE]] %[[VAR410]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR412:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR407]], %[[VAR411]] + // CHECK-NEXT: %[[VAR413:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR409]], 0 + // CHECK-NEXT: %[[VAR414:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR415:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR412]], i[[LLSIZE]]* %[[VAR414]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR413]], i[[LLSIZE]]* %[[VAR415]] + + cull1 = cull + uc; + // CHECK-NEXT: %[[VAR416:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR417:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR416]] + // CHECK-NEXT: %[[VAR418:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR419:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR418]] + // CHECK-NEXT: %[[VAR420:[A-Za-z0-9.]+]] = load i[[CHSIZE]]* %[[UCADDR]], align [[CHALIGN]] + // CHECK-NEXT: %[[VAR421:[A-Za-z0-9.]+]] = zext i[[CHSIZE]] %[[VAR420]] to i[[LLSIZE]] + // CHECK-NEXT: %[[VAR422:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR417]], %[[VAR421]] + // CHECK-NEXT: %[[VAR423:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR419]], 0 + // CHECK-NEXT: %[[VAR424:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR425:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR422]], i[[LLSIZE]]* %[[VAR424]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR423]], i[[LLSIZE]]* %[[VAR425]] + + csll1 = cull + sll; + // CHECK-NEXT: %[[VAR426:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR427:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR426]] + // CHECK-NEXT: %[[VAR428:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR429:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR428]] + // CHECK-NEXT: %[[VAR430:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[SLLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR431:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR427]], %[[VAR430]] + // CHECK-NEXT: %[[VAR432:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR429]], 0 + // CHECK-NEXT: %[[VAR433:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR434:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CSLL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR431]], i[[LLSIZE]]* %[[VAR433]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR432]], i[[LLSIZE]]* %[[VAR434]] + + cull1 = cull + ull; + // CHECK-NEXT: %[[VAR435:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR436:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR435]] + // CHECK-NEXT: %[[VAR437:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: %[[VAR438:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[VAR437]] + // CHECK-NEXT: %[[VAR439:[A-Za-z0-9.]+]] = load i[[LLSIZE]]* %[[ULLADDR]], align [[LLALIGN]] + // CHECK-NEXT: %[[VAR440:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR436]], %[[VAR439]] + // CHECK-NEXT: %[[VAR441:[A-Za-z0-9.]+]] = add i[[LLSIZE]] %[[VAR438]], 0 + // CHECK-NEXT: %[[VAR442:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK-NEXT: %[[VAR443:[A-Za-z0-9.]+]] = getelementptr inbounds { i[[LLSIZE]], i[[LLSIZE]] }* %[[CULL1]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR440]], i[[LLSIZE]]* %[[VAR442]] + // CHECK-NEXT: store i[[LLSIZE]] %[[VAR441]], i[[LLSIZE]]* %[[VAR443]] +} + diff --git a/test/CodeGen/compound-assign-overflow.c b/test/CodeGen/compound-assign-overflow.c new file mode 100644 index 0000000..e82061b --- /dev/null +++ b/test/CodeGen/compound-assign-overflow.c @@ -0,0 +1,36 @@ +// Verify proper type emitted for compound assignments +// RUN: %clang_cc1 -ffreestanding -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=signed-integer-overflow,unsigned-integer-overflow | FileCheck %s + +#include <stdint.h> + +// CHECK: @[[INT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" } +// CHECK: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]] +// CHECK: @[[UINT:.*]] = private unnamed_addr constant { i16, i16, [15 x i8] } { i16 0, i16 10, [15 x i8] c"'unsigned int'\00" } +// CHECK: @[[LINE_200:.*]] = private unnamed_addr global {{.*}}, i32 200, i32 5 {{.*}} @[[UINT]] +// CHECK: @[[DIVINT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" } +// CHECK: @[[LINE_300:.*]] = private unnamed_addr global {{.*}}, i32 300, i32 5 {{.*}} @[[DIVINT]] + +int32_t x; + +// CHECK: @compaddsigned +void compaddsigned() { +#line 100 + x += ((int32_t)1); + // CHECK: @__ubsan_handle_add_overflow(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), {{.*}}) +} + +// CHECK: @compaddunsigned +void compaddunsigned() { +#line 200 + x += ((uint32_t)1U); + // CHECK: @__ubsan_handle_add_overflow(i8* bitcast ({{.*}} @[[LINE_200]] to i8*), {{.*}}) +} + +int8_t a, b; + +// CHECK: @compdiv +void compdiv() { +#line 300 + a /= b; + // CHECK: @__ubsan_handle_divrem_overflow(i8* bitcast ({{.*}} @[[LINE_300]] to i8*), {{.*}}) +} diff --git a/test/CodeGen/compound-literal.c b/test/CodeGen/compound-literal.c index a8eec61..e4bf962 100644 --- a/test/CodeGen/compound-literal.c +++ b/test/CodeGen/compound-literal.c @@ -32,3 +32,37 @@ void f() { s = (S){s.y,s.x}; // CHECK-NEXT: ret void } + +// CHECK: define i48 @g( +struct G { short x, y, z; }; +struct G g(int x, int y, int z) { + // CHECK: [[RESULT:%.*]] = alloca [[G:%.*]], align 2 + // CHECK-NEXT: [[X:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 + // CHECK-NEXT: [[COERCE_TEMP:%.*]] = alloca i48 + // CHECK-NEXT: store i32 + // CHECK-NEXT: store i32 + // CHECK-NEXT: store i32 + + // Evaluate the compound literal directly in the result value slot. + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[G]]* [[RESULT]], i32 0, i32 0 + // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]], align 4 + // CHECK-NEXT: [[T2:%.*]] = trunc i32 [[T1]] to i16 + // CHECK-NEXT: store i16 [[T2]], i16* [[T0]], align 2 + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[G]]* [[RESULT]], i32 0, i32 1 + // CHECK-NEXT: [[T1:%.*]] = load i32* [[Y]], align 4 + // CHECK-NEXT: [[T2:%.*]] = trunc i32 [[T1]] to i16 + // CHECK-NEXT: store i16 [[T2]], i16* [[T0]], align 2 + // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[G]]* [[RESULT]], i32 0, i32 2 + // CHECK-NEXT: [[T1:%.*]] = load i32* [[Z]], align 4 + // CHECK-NEXT: [[T2:%.*]] = trunc i32 [[T1]] to i16 + // CHECK-NEXT: store i16 [[T2]], i16* [[T0]], align 2 + return (struct G) { x, y, z }; + + // CHECK-NEXT: [[T0:%.*]] = bitcast i48* [[COERCE_TEMP]] to i8* + // CHECK-NEXT: [[T1:%.*]] = bitcast [[G]]* [[RESULT]] to i8* + // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 6 + // CHECK-NEXT: [[T0:%.*]] = load i48* [[COERCE_TEMP]] + // CHECK-NEXT: ret i48 [[T0]] +} diff --git a/test/CodeGen/debug-info-args.c b/test/CodeGen/debug-info-args.c index 1d4ea10..3312952 100644 --- a/test/CodeGen/debug-info-args.c +++ b/test/CodeGen/debug-info-args.c @@ -2,8 +2,8 @@ int somefunc(char *x, int y, double z) { - // CHECK: {{.*metadata !8, i32 0, i32 0}.*DW_TAG_subroutine_type}} - // CHECK: {{!8 = .*metadata ![^,]*, metadata ![^,]*, metadata ![^,]*, metadata ![^,]*}} + // CHECK: metadata ![[NUM:[^,]*]], i32 0, i32 0} ; [ DW_TAG_subroutine_type + // CHECK: ![[NUM]] = {{metadata !{metadata ![^,]*, metadata ![^,]*, metadata ![^,]*, metadata ![^,]*}}} return y; } diff --git a/test/CodeGen/debug-info-line.c b/test/CodeGen/debug-info-line.c index 9e6e971..8f869d0 100644 --- a/test/CodeGen/debug-info-line.c +++ b/test/CodeGen/debug-info-line.c @@ -1,9 +1,8 @@ // RUN: %clang -emit-llvm -S -g %s -o - | FileCheck %s // Radar 8396182 -// There is only one lexical block, but we need a DILexicalBlock and two -// DILexicalBlockFile to correctly represent file info. This means we have -// two lexical blocks shown as the latter is also tagged as a lexical block. +// There are no lexical blocks, but we need two DILexicalBlockFiles to +// correctly represent file info. int foo() { int i = 1; @@ -16,7 +15,6 @@ int foo() { } // CHECK: DW_TAG_lexical_block -// CHECK: DW_TAG_lexical_block // CHECK: !"m.h" // CHECK: DW_TAG_lexical_block // CHECK: !"m.c" diff --git a/test/CodeGen/debug-info-scope.c b/test/CodeGen/debug-info-scope.c index 6051e6e..9decaea 100644 --- a/test/CodeGen/debug-info-scope.c +++ b/test/CodeGen/debug-info-scope.c @@ -4,10 +4,12 @@ int main() { int j = 0; int k = 0; -// CHECK: DW_TAG_auto_variable +// CHECK: DW_TAG_auto_variable ] [i] // CHECK-NEXT: DW_TAG_lexical_block for (int i = 0; i < 10; i++) j++; +// CHECK: DW_TAG_auto_variable ] [i] +// CHECK-NEXT: DW_TAG_lexical_block for (int i = 0; i < 10; i++) k++; return 0; diff --git a/test/CodeGen/debug-info-static.c b/test/CodeGen/debug-info-static.c index e75d20f..931c9e2 100644 --- a/test/CodeGen/debug-info-static.c +++ b/test/CodeGen/debug-info-static.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -g -emit-llvm -o - %s | FileCheck %s -// CHECK: xyzzy} ; [ DW_TAG_variable ] +// CHECK: xyzzy, null} ; [ DW_TAG_variable ] void f(void) { static int xyzzy; diff --git a/test/CodeGen/debug-info-vector.c b/test/CodeGen/debug-info-vector.c new file mode 100644 index 0000000..b7135af --- /dev/null +++ b/test/CodeGen/debug-info-vector.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s +typedef int v4si __attribute__((__vector_size__(16))); + +v4si a; + +// Test that we get an array type that's also a vector out of debug. +// CHECK: [ DW_TAG_array_type ] [line 0, size 128, align 128, offset 0] [vector] [from int] diff --git a/test/CodeGen/exceptions.c b/test/CodeGen/exceptions.c index 20eb706..311bc84 100644 --- a/test/CodeGen/exceptions.c +++ b/test/CodeGen/exceptions.c @@ -19,3 +19,12 @@ void test1() { // CHECK-ARM: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) // CHECK-ARM-NEXT: cleanup } + +void test2_helper(); +void test2() { + __block int x = 10; + test2_helper(5, 6, 7); +} +void test2_helper(int x, int y) { +} +// CHECK: invoke void @test2_helper(i32 5, i32 6) diff --git a/test/CodeGen/fast-math.c b/test/CodeGen/fast-math.c new file mode 100644 index 0000000..76cfbbd --- /dev/null +++ b/test/CodeGen/fast-math.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -ffast-math -emit-llvm -o - %s | FileCheck %s +float f0, f1, f2; + +void foo(void) { + // CHECK: define void @foo() + + // CHECK: fadd fast + f0 = f1 + f2; + + // CHECK: ret +} diff --git a/test/CodeGen/finite-math.c b/test/CodeGen/finite-math.c new file mode 100644 index 0000000..bf39cea --- /dev/null +++ b/test/CodeGen/finite-math.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -ffinite-math-only -emit-llvm -o - %s | FileCheck %s +float f0, f1, f2; + +void foo(void) { + // CHECK: define void @foo() + + // CHECK: fadd nnan ninf + f0 = f1 + f2; + + // CHECK: ret +} diff --git a/test/CodeGen/frame-pointer-elim.c b/test/CodeGen/frame-pointer-elim.c deleted file mode 100644 index b105a19..0000000 --- a/test/CodeGen/frame-pointer-elim.c +++ /dev/null @@ -1,40 +0,0 @@ -// REQUIRES: x86-registered-target - -// RUN: %clang -target i386-apple-darwin -S -o - %s | \ -// RUN: FileCheck --check-prefix=DARWIN %s -// DARWIN: f0: -// DARWIN: pushl %ebp -// DARWIN: ret -// DARWIN: f1: -// DARWIN: pushl %ebp -// DARWIN: ret - -// RUN: %clang -target i386-pc-linux-gnu -S -o - %s | \ -// RUN: FileCheck --check-prefix=LINUX %s -// LINUX: f0: -// LINUX-NOT: pushl %ebp -// LINUX: ret -// LINUX: f1: -// LINUX: pushl %ebp -// LINUX: ret - -// RUN: %clang -target i386-darwin -S -o - -fomit-frame-pointer %s | \ -// RUN: FileCheck --check-prefix=OMIT_ALL %s -// OMIT_ALL: f0: -// OMIT_ALL-NOT: pushl %ebp -// OMIT_ALL: ret -// OMIT_ALL: f1: -// OMIT_ALL-NOT: pushl %ebp -// OMIT_ALL: ret - -// RUN: %clang -target i386-darwin -S -o - -momit-leaf-frame-pointer %s | \ -// RUN: FileCheck --check-prefix=OMIT_LEAF %s -// OMIT_LEAF: f0: -// OMIT_LEAF-NOT: pushl %ebp -// OMIT_LEAF: ret -// OMIT_LEAF: f1: -// OMIT_LEAF: pushl %ebp -// OMIT_LEAF: ret - -void f0() {} -void f1() { f0(); } diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c index 6cbf40b..25ca916 100644 --- a/test/CodeGen/function-attributes.c +++ b/test/CodeGen/function-attributes.c @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -Os -o - %s | FileCheck %s -// CHECK: define signext i8 @f0(i32 %x) nounwind -// CHECK: define zeroext i8 @f1(i32 %x) nounwind -// CHECK: define void @f2(i8 signext %x) nounwind -// CHECK: define void @f3(i8 zeroext %x) nounwind -// CHECK: define signext i16 @f4(i32 %x) nounwind -// CHECK: define zeroext i16 @f5(i32 %x) nounwind -// CHECK: define void @f6(i16 signext %x) nounwind -// CHECK: define void @f7(i16 zeroext %x) nounwind +// CHECK: define signext i8 @f0(i32 %x) [[NUW:#[0-9]+]] +// CHECK: define zeroext i8 @f1(i32 %x) [[NUW]] +// CHECK: define void @f2(i8 signext %x) [[NUW]] +// CHECK: define void @f3(i8 zeroext %x) [[NUW]] +// CHECK: define signext i16 @f4(i32 %x) [[NUW]] +// CHECK: define zeroext i16 @f5(i32 %x) [[NUW]] +// CHECK: define void @f6(i16 signext %x) [[NUW]] +// CHECK: define void @f7(i16 zeroext %x) [[NUW]] signed char f0(int x) { return x; } @@ -25,20 +25,25 @@ void f6(signed short x) { } void f7(unsigned short x) { } // CHECK: define void @f8() -// CHECK: nounwind -// CHECK: alwaysinline +// CHECK: [[AI:#[0-9]+]] // CHECK: { void __attribute__((always_inline)) f8(void) { } // CHECK: call void @f9_t() -// CHECK: noreturn -// CHECK: { +// CHECK: [[NR:#[0-9]+]] +// CHECK: } void __attribute__((noreturn)) f9_t(void); void f9(void) { f9_t(); } +// CHECK: call void @f9a() +// CHECK: [[NR]] +// CHECK: } +_Noreturn void f9a(void); +void f9b(void) { f9a(); } + // FIXME: We should be setting nounwind on calls. // CHECK: call i32 @f10_t() -// CHECK: readnone +// CHECK: [[NUW_RN:#[0-9]+]] // CHECK: { int __attribute__((const)) f10_t(void); int f10(void) { return f10_t(); } @@ -50,7 +55,7 @@ int f12(int arg) { return arg ? 0 : f10_t(); } -// CHECK: define void @f13() nounwind readnone +// CHECK: define void @f13() [[NUW]] void f13(void) __attribute__((pure)) __attribute__((const)); void f13(void){} @@ -77,24 +82,24 @@ void f14(int a) { // <rdar://problem/7102668> [irgen] clang isn't setting the optsize bit on functions // CHECK: define void @f15 -// CHECK: optsize +// CHECK: [[NUW]] // CHECK: { void f15(void) { } // PR5254 // CHECK: define void @f16 -// CHECK: alignstack(16) +// CHECK: [[ALIGN:#[0-9]+]] // CHECK: { void __attribute__((force_align_arg_pointer)) f16(void) { } // PR11038 // CHECK: define void @f18() -// CHECK: returns_twice +// CHECK: [[RT:#[0-9]+]] // CHECK: { // CHECK: call void @f17() -// CHECK: returns_twice +// CHECK: [[RT_CALL:#[0-9]+]] // CHECK: ret void __attribute__ ((returns_twice)) void f17(void); __attribute__ ((returns_twice)) void f18(void) { @@ -104,10 +109,18 @@ __attribute__ ((returns_twice)) void f18(void) { // CHECK: define void @f19() // CHECK: { // CHECK: call i32 @setjmp(i32* null) -// CHECK: returns_twice +// CHECK: [[RT_CALL]] // CHECK: ret void typedef int jmp_buf[((9 * 2) + 3 + 16)]; int setjmp(jmp_buf); void f19(void) { setjmp(0); } + +// CHECK: attributes [[NUW]] = { nounwind optsize readnone{{.*}} } +// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize readnone{{.*}} } +// CHECK: attributes [[ALIGN]] = { nounwind optsize readnone alignstack=16{{.*}} } +// CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } +// CHECK: attributes [[NR]] = { noreturn nounwind optsize } +// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } +// CHECK: attributes [[RT_CALL]] = { nounwind optsize returns_twice } diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c index 28e4bd0..8241a3d 100644 --- a/test/CodeGen/functions.c +++ b/test/CodeGen/functions.c @@ -24,7 +24,7 @@ void f0() {} void f1(); void f2(void) { -// CHECK: call void bitcast (void ()* @f1 to void (i32, i32, i32)*)(i32 1, i32 2, i32 3) +// CHECK: call void @f1() f1(1, 2, 3); } // CHECK: define void @f1() diff --git a/test/CodeGen/global-blocks-lines.c b/test/CodeGen/global-blocks-lines.c new file mode 100644 index 0000000..36e4618 --- /dev/null +++ b/test/CodeGen/global-blocks-lines.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fblocks -g -emit-llvm %s -o - | FileCheck %s +// Make sure we do not generate line info for debugging-related frame setup. +// CHECK: define {{.*}}block_invoke +// CHECK-NOT: store {{.*}}%struct.__block_descriptor*{{.*}}dbg +// CHECK: store {{.*}}%struct.__block_descriptor*{{.*}}, align +// CHECK: ret +// CHECK: define {{.*}}block_invoke +// CHECK-NOT: store {{.*}}%struct.__block_descriptor*{{.*}}dbg +// CHECK: store {{.*}}%struct.__block_descriptor*{{.*}}, align +// CHECK: ret +// CHECK: define {{.*}}block_invoke +// CHECK-NOT: store {{.*}}%struct.__block_descriptor*{{.*}}dbg +// CHECK: store {{.*}}%struct.__block_descriptor*{{.*}}, align +// CHECK: ret +int printf(const char*, ...); + +static void* _NSConcreteGlobalBlock; + + +typedef void (^ HelloBlock_t)(const char * name); + + /* Breakpoint for first Block function. */ +HelloBlock_t helloBlock = ^(const char * name) { + printf("Hello there, %s!\n", name); +}; + + /* Breakpoint for second Block function. */ +static HelloBlock_t s_helloBlock = ^(const char * name) { + printf("Hello there, %s!\n", name); +}; + +/* Breakpoint for third Block function. */ +int X = 1234; +int (^CP)(void) = ^{ X = X+1; return X; }; + +int +main(int argc, char * argv[]) +{ + helloBlock("world"); + s_helloBlock("world"); + + CP(); + printf ("X = %d\n", X); + return X - 1235; +} diff --git a/test/CodeGen/incomplete-function-type-2.c b/test/CodeGen/incomplete-function-type-2.c new file mode 100644 index 0000000..41dd5fe --- /dev/null +++ b/test/CodeGen/incomplete-function-type-2.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s + +// PR14355: don't crash +// Keep this test in its own file because CodeGenTypes has global state. +// CHECK: define void @test10_foo({}* %p1.coerce) [[NUW:#[0-9]+]] { +struct test10_B; +typedef struct test10_B test10_F3(double); +void test10_foo(test10_F3 p1); +struct test10_B test10_b(double); +void test10_bar() { + test10_foo(test10_b); +} +struct test10_B {}; +void test10_foo(test10_F3 p1) +{ + p1(0.0); +} + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c index 259d34d..1b0beae 100644 --- a/test/CodeGen/init.c +++ b/test/CodeGen/init.c @@ -130,5 +130,5 @@ void test13(int x) { struct X { int a; int b : 10; int c; }; struct X y = {.c = x}; // CHECK: @test13 - // CHECK: and i32 {{.*}}, -1024 + // CHECK: and i16 {{.*}}, -1024 } diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c index addb30b..442b380 100644 --- a/test/CodeGen/inline.c +++ b/test/CodeGen/inline.c @@ -1,55 +1,55 @@ // RUN: echo "GNU89 tests:" -// RUN: %clang %s -target i386-unknown-unknown -O1 -emit-llvm -S -o %t -std=gnu89 -// RUN: grep "define available_externally i32 @ei()" %t -// RUN: grep "define i32 @foo()" %t -// RUN: grep "define i32 @bar()" %t -// RUN: grep "define void @unreferenced1()" %t -// RUN: not grep unreferenced2 %t -// RUN: grep "define void @gnu_inline()" %t -// RUN: grep "define available_externally void @gnu_ei_inline()" %t -// RUN: grep "define i32 @test1" %t -// RUN: grep "define i32 @test2" %t -// RUN: grep "define void @test3()" %t -// RUN: grep "define available_externally i32 @test4" %t -// RUN: grep "define available_externally i32 @test5" %t -// RUN: grep "define i32 @test6" %t -// RUN: grep "define void @test7" %t -// RUN: grep "define i.. @strlcpy" %t -// RUN: not grep test9 %t -// RUN: grep "define void @testA" %t -// RUN: grep "define void @testB" %t -// RUN: grep "define void @testC" %t +// RUN: %clang %s -target i386-unknown-unknown -O1 -emit-llvm -S -o - -std=gnu89 | FileCheck %s --check-prefix=CHECK1 +// CHECK1: define i32 @foo() +// CHECK1: define i32 @bar() +// CHECK1: define void @unreferenced1() +// CHECK1-NOT: unreferenced2 +// CHECK1: define void @gnu_inline() +// CHECK1: define i32 @test1 +// CHECK1: define i32 @test2 +// CHECK1: define void @test3() +// CHECK1: define available_externally i32 @test4 +// CHECK1: define available_externally i32 @test5 +// CHECK1: define i32 @test6 +// CHECK1: define void @test7 +// CHECK1: define i{{..}} @strlcpy +// CHECK1-NOT: test9 +// CHECK1: define void @testA +// CHECK1: define void @testB +// CHECK1: define void @testC +// CHECK1: define available_externally void @gnu_ei_inline() +// CHECK1: define available_externally i32 @ei() // RUN: echo "C99 tests:" -// RUN: %clang %s -target i386-unknown-unknown -O1 -emit-llvm -S -o %t -std=gnu99 -// RUN: grep "define i32 @ei()" %t -// RUN: grep "define available_externally i32 @foo()" %t -// RUN: grep "define i32 @bar()" %t -// RUN: not grep unreferenced1 %t -// RUN: grep "define void @unreferenced2()" %t -// RUN: grep "define void @gnu_inline()" %t -// RUN: grep "define available_externally void @gnu_ei_inline()" %t -// RUN: grep "define i32 @test1" %t -// RUN: grep "define i32 @test2" %t -// RUN: grep "define void @test3" %t -// RUN: grep "define available_externally i32 @test4" %t -// RUN: grep "define available_externally i32 @test5" %t -// RUN: grep "define i32 @test6" %t -// RUN: grep "define void @test7" %t -// RUN: grep "define available_externally i.. @strlcpy" %t -// RUN: grep "define void @test9" %t -// RUN: grep "define void @testA" %t -// RUN: grep "define void @testB" %t -// RUN: grep "define void @testC" %t +// RUN: %clang %s -target i386-unknown-unknown -O1 -emit-llvm -S -o - -std=gnu99 | FileCheck %s --check-prefix=CHECK2 +// CHECK2: define i32 @ei() +// CHECK2: define i32 @bar() +// CHECK2-NOT: unreferenced1 +// CHECK2: define void @unreferenced2() +// CHECK2: define void @gnu_inline() +// CHECK2: define i32 @test1 +// CHECK2: define i32 @test2 +// CHECK2: define void @test3 +// CHECK2: define available_externally i32 @test4 +// CHECK2: define available_externally i32 @test5 +// CHECK2: define i32 @test6 +// CHECK2: define void @test7 +// CHECK2: define available_externally i{{..}} @strlcpy +// CHECK2: define void @test9 +// CHECK2: define void @testA +// CHECK2: define void @testB +// CHECK2: define void @testC +// CHECK2: define available_externally void @gnu_ei_inline() +// CHECK2: define available_externally i32 @foo() // RUN: echo "C++ tests:" -// RUN: %clang -x c++ %s -target i386-unknown-unknown -O1 -emit-llvm -S -o %t -std=c++98 -// RUN: grep "define linkonce_odr i32 @_Z2eiv()" %t -// RUN: grep "define linkonce_odr i32 @_Z3foov()" %t -// RUN: grep "define i32 @_Z3barv()" %t -// RUN: not grep unreferenced %t -// RUN: grep "define void @_Z10gnu_inlinev()" %t -// RUN: grep "define available_externally void @_Z13gnu_ei_inlinev()" %t +// RUN: %clang -x c++ %s -target i386-unknown-unknown -O1 -emit-llvm -S -o - -std=c++98 | FileCheck %s --check-prefix=CHECK3 +// CHECK3: define i32 @_Z3barv() +// CHECK3: define linkonce_odr i32 @_Z3foov() +// CHECK3-NOT: unreferenced +// CHECK3: define void @_Z10gnu_inlinev() +// CHECK3: define available_externally void @_Z13gnu_ei_inlinev() +// CHECK3: define linkonce_odr i32 @_Z2eiv() extern __inline int ei() { return 123; } diff --git a/test/CodeGen/intel_ocl_bicc.c b/test/CodeGen/intel_ocl_bicc.c new file mode 100644 index 0000000..c5c5229 --- /dev/null +++ b/test/CodeGen/intel_ocl_bicc.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +void __attribute__((intel_ocl_bicc)) f1(void); + +void f2(void) { + f1(); +// CHECK: call intel_ocl_bicc void @f1() +} + +// CHECK: declare intel_ocl_bicc void @f1() diff --git a/test/CodeGen/le32-regparm.c b/test/CodeGen/le32-regparm.c index 6ab5a11..8c1ae5e 100644 --- a/test/CodeGen/le32-regparm.c +++ b/test/CodeGen/le32-regparm.c @@ -34,7 +34,7 @@ int main(void) { // The presence of double c means that foo* d is not passed inreg. This // behavior is different from current x86-32 behavior - // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.foo* null + // CHECK: call void @reduced(i8 inreg signext 0, {{.*}} %struct.foo* null reduced(0, 0.0, 0, 0.0, 0); // CHECK: call void {{.*}}(i32 inreg 1, i32 inreg 2) bar(1,2); diff --git a/test/CodeGen/libcall-declarations.c b/test/CodeGen/libcall-declarations.c index 4517643..d07590f 100644 --- a/test/CodeGen/libcall-declarations.c +++ b/test/CodeGen/libcall-declarations.c @@ -86,106 +86,110 @@ void *use[] = { sqrtf, tan, tanl, tanf, trunc, truncl, truncf }; -// CHECK-NOERRNO: declare double @acos(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @acosl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @acosf(float) nounwind readnone -// CHECK-NOERRNO: declare double @asin(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @asinl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @asinf(float) nounwind readnone -// CHECK-NOERRNO: declare double @atan(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @atanl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @atanf(float) nounwind readnone -// CHECK-NOERRNO: declare double @atan2(double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @atan2f(float, float) nounwind readnone -// CHECK-NOERRNO: declare double @ceil(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @ceill(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @ceilf(float) nounwind readnone -// CHECK-NOERRNO: declare double @copysign(double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @copysignf(float, float) nounwind readnone -// CHECK-NOERRNO: declare double @cos(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @cosl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @cosf(float) nounwind readnone -// CHECK-NOERRNO: declare double @exp(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @expl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @expf(float) nounwind readnone -// CHECK-NOERRNO: declare double @exp2(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @exp2l(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @exp2f(float) nounwind readnone -// CHECK-NOERRNO: declare double @fabs(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @fabsl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @fabsf(float) nounwind readnone -// CHECK-NOERRNO: declare double @floor(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @floorl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @floorf(float) nounwind readnone -// CHECK-NOERRNO: declare double @fma(double, double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @fmal(x86_fp80, x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @fmaf(float, float, float) nounwind readnone -// CHECK-NOERRNO: declare double @fmax(double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @fmaxf(float, float) nounwind readnone -// CHECK-NOERRNO: declare double @fmin(double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @fminf(float, float) nounwind readnone -// CHECK-NOERRNO: declare double @log(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @logl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @logf(float) nounwind readnone -// CHECK-NOERRNO: declare double @log2(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @log2l(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @log2f(float) nounwind readnone -// CHECK-NOERRNO: declare double @nearbyint(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @nearbyintl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @nearbyintf(float) nounwind readnone -// CHECK-NOERRNO: declare double @pow(double, double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @powf(float, float) nounwind readnone -// CHECK-NOERRNO: declare double @rint(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @rintl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @rintf(float) nounwind readnone -// CHECK-NOERRNO: declare double @round(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @roundl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @roundf(float) nounwind readnone -// CHECK-NOERRNO: declare double @sin(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @sinl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @sinf(float) nounwind readnone -// CHECK-NOERRNO: declare double @sqrt(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @sqrtl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @sqrtf(float) nounwind readnone -// CHECK-NOERRNO: declare double @tan(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @tanl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @tanf(float) nounwind readnone -// CHECK-NOERRNO: declare double @trunc(double) nounwind readnone -// CHECK-NOERRNO: declare x86_fp80 @truncl(x86_fp80) nounwind readnone -// CHECK-NOERRNO: declare float @truncf(float) nounwind readnone +// CHECK-NOERRNO: declare double @acos(double) [[NUW:#[0-9]+]] +// CHECK-NOERRNO: declare x86_fp80 @acosl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @acosf(float) [[NUW]] +// CHECK-NOERRNO: declare double @asin(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @asinl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @asinf(float) [[NUW]] +// CHECK-NOERRNO: declare double @atan(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @atanl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @atanf(float) [[NUW]] +// CHECK-NOERRNO: declare double @atan2(double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @atan2f(float, float) [[NUW]] +// CHECK-NOERRNO: declare double @ceil(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @ceilf(float) [[NUW]] +// CHECK-NOERRNO: declare double @copysign(double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @copysignf(float, float) [[NUW]] +// CHECK-NOERRNO: declare double @cos(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @cosl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @cosf(float) [[NUW]] +// CHECK-NOERRNO: declare double @exp(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @expl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @expf(float) [[NUW]] +// CHECK-NOERRNO: declare double @exp2(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @exp2l(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @exp2f(float) [[NUW]] +// CHECK-NOERRNO: declare double @fabs(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @fabsf(float) [[NUW]] +// CHECK-NOERRNO: declare double @floor(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @floorf(float) [[NUW]] +// CHECK-NOERRNO: declare double @fma(double, double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @fmal(x86_fp80, x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @fmaf(float, float, float) [[NUW]] +// CHECK-NOERRNO: declare double @fmax(double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @fmaxf(float, float) [[NUW]] +// CHECK-NOERRNO: declare double @fmin(double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @fminf(float, float) [[NUW]] +// CHECK-NOERRNO: declare double @log(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @logl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @logf(float) [[NUW]] +// CHECK-NOERRNO: declare double @log2(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @log2l(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @log2f(float) [[NUW]] +// CHECK-NOERRNO: declare double @nearbyint(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @nearbyintf(float) [[NUW]] +// CHECK-NOERRNO: declare double @pow(double, double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @powf(float, float) [[NUW]] +// CHECK-NOERRNO: declare double @rint(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @rintf(float) [[NUW]] +// CHECK-NOERRNO: declare double @round(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @roundf(float) [[NUW]] +// CHECK-NOERRNO: declare double @sin(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @sinl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @sinf(float) [[NUW]] +// CHECK-NOERRNO: declare double @sqrt(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @sqrtf(float) [[NUW]] +// CHECK-NOERRNO: declare double @tan(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @tanl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @tanf(float) [[NUW]] +// CHECK-NOERRNO: declare double @trunc(double) [[NUW]] +// CHECK-NOERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUW]] +// CHECK-NOERRNO: declare float @truncf(float) [[NUW]] -// CHECK-ERRNO: declare double @ceil(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @ceill(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @ceilf(float) nounwind readnone -// CHECK-ERRNO: declare double @copysign(double, double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @copysignf(float, float) nounwind readnone -// CHECK-ERRNO: declare double @fabs(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @fabsl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @fabsf(float) nounwind readnone -// CHECK-ERRNO: declare double @floor(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @floorl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @floorf(float) nounwind readnone -// CHECK-ERRNO: declare double @fmax(double, double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @fmaxf(float, float) nounwind readnone -// CHECK-ERRNO: declare double @fmin(double, double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @fminf(float, float) nounwind readnone -// CHECK-ERRNO: declare double @nearbyint(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @nearbyintf(float) nounwind readnone -// CHECK-ERRNO: declare double @rint(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @rintl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @rintf(float) nounwind readnone -// CHECK-ERRNO: declare double @round(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @roundl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @roundf(float) nounwind readnone -// CHECK-ERRNO: declare double @trunc(double) nounwind readnone -// CHECK-ERRNO: declare x86_fp80 @truncl(x86_fp80) nounwind readnone -// CHECK-ERRNO: declare float @truncf(float) nounwind readnone +// CHECK-ERRNO: declare double @ceil(double) [[NUW:#[0-9]+]] +// CHECK-ERRNO: declare x86_fp80 @ceill(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @ceilf(float) [[NUW]] +// CHECK-ERRNO: declare double @copysign(double, double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @copysignf(float, float) [[NUW]] +// CHECK-ERRNO: declare double @fabs(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @fabsl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @fabsf(float) [[NUW]] +// CHECK-ERRNO: declare double @floor(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @floorl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @floorf(float) [[NUW]] +// CHECK-ERRNO: declare double @fmax(double, double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @fmaxf(float, float) [[NUW]] +// CHECK-ERRNO: declare double @fmin(double, double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @fminf(float, float) [[NUW]] +// CHECK-ERRNO: declare double @nearbyint(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @nearbyintf(float) [[NUW]] +// CHECK-ERRNO: declare double @rint(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @rintl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @rintf(float) [[NUW]] +// CHECK-ERRNO: declare double @round(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @roundl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @roundf(float) [[NUW]] +// CHECK-ERRNO: declare double @trunc(double) [[NUW]] +// CHECK-ERRNO: declare x86_fp80 @truncl(x86_fp80) [[NUW]] +// CHECK-ERRNO: declare float @truncf(float) [[NUW]] + +// CHECK-NOERRNO: attributes [[NUW]] = { nounwind readnone{{.*}} } + +// CHECK-ERRNO: attributes [[NUW]] = { nounwind readnone{{.*}} } diff --git a/test/CodeGen/libcalls-complex.c b/test/CodeGen/libcalls-complex.c new file mode 100644 index 0000000..7bcfa60 --- /dev/null +++ b/test/CodeGen/libcalls-complex.c @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fno-builtin -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix YES %s +// RUN: %clang_cc1 -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix NO %s + +extern float crealf(float _Complex); +extern double creal(double _Complex); +extern long double creall(long double _Complex); + +extern float cimagf(float _Complex); +extern double cimag(double _Complex); +extern long double cimagl(long double _Complex); + +double test_creal(double _Complex z) { + return creal(z); + // CHECK-NO-NOT: call double @creal + // CHECK-YES: call double @creal +} + +long double test_creall(double _Complex z) { + return creall(z); + // CHECK-NO-NOT: call x86_fp80 @creall + // CHECK-YES: call x86_fp80 @creall +} + +float test_crealf(double _Complex z) { + return crealf(z); + // CHECK-NO-NOT: call float @crealf + // CHECK-YES: call float @crealf +} + +double test_cimag(double _Complex z) { + return cimag(z); + // CHECK-NO-NOT: call double @cimag + // CHECK-YES: call double @cimag +} + +long double test_cimagl(double _Complex z) { + return cimagl(z); + // CHECK-NO-NOT: call x86_fp80 @cimagl + // CHECK-YES: call x86_fp80 @cimagl +} + +float test_cimagf(double _Complex z) { + return cimagf(z); + // CHECK-NO-NOT: call float @cimagf + // CHECK-YES: call float @cimagf +} diff --git a/test/CodeGen/libcalls.c b/test/CodeGen/libcalls.c index ec895ac..8f8e182 100644 --- a/test/CodeGen/libcalls.c +++ b/test/CodeGen/libcalls.c @@ -24,9 +24,9 @@ void test_sqrt(float a0, double a1, long double a2) { // CHECK-YES: declare float @sqrtf(float) // CHECK-YES: declare double @sqrt(double) // CHECK-YES: declare x86_fp80 @sqrtl(x86_fp80) -// CHECK-NO: declare float @sqrtf(float) nounwind readnone -// CHECK-NO: declare double @sqrt(double) nounwind readnone -// CHECK-NO: declare x86_fp80 @sqrtl(x86_fp80) nounwind readnone +// CHECK-NO: declare float @sqrtf(float) [[NUW_RN:#[0-9]+]] +// CHECK-NO: declare double @sqrt(double) [[NUW_RN]] +// CHECK-NO: declare x86_fp80 @sqrtl(x86_fp80) [[NUW_RN]] // CHECK-YES: define void @test_pow // CHECK-NO: define void @test_pow @@ -47,9 +47,9 @@ void test_pow(float a0, double a1, long double a2) { // CHECK-YES: declare float @powf(float, float) // CHECK-YES: declare double @pow(double, double) // CHECK-YES: declare x86_fp80 @powl(x86_fp80, x86_fp80) -// CHECK-NO: declare float @llvm.pow.f32(float, float) nounwind readonly -// CHECK-NO: declare double @llvm.pow.f64(double, double) nounwind readonly -// CHECK-NO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) nounwind readonly +// CHECK-NO: declare float @llvm.pow.f32(float, float) [[NUW_RO:#[0-9]+]] +// CHECK-NO: declare double @llvm.pow.f64(double, double) [[NUW_RO]] +// CHECK-NO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[NUW_RO]] // CHECK-YES: define void @test_fma // CHECK-NO: define void @test_fma @@ -67,12 +67,12 @@ void test_fma(float a0, double a1, long double a2) { long double l2 = fmal(a2, a2, a2); } -// CHECK-YES: declare float @llvm.fma.f32(float, float, float) nounwind readnone -// CHECK-YES: declare double @llvm.fma.f64(double, double, double) nounwind readnone -// CHECK-YES: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) nounwind readnone -// CHECK-NO: declare float @llvm.fma.f32(float, float, float) nounwind readnone -// CHECK-NO: declare double @llvm.fma.f64(double, double, double) nounwind readnone -// CHECK-NO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) nounwind readnone +// CHECK-YES: declare float @llvm.fma.f32(float, float, float) [[NUW_RN:#[0-9]+]] +// CHECK-YES: declare double @llvm.fma.f64(double, double, double) [[NUW_RN]] +// CHECK-YES: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[NUW_RN]] +// CHECK-NO: declare float @llvm.fma.f32(float, float, float) [[NUW_RN2:#[0-9]+]] +// CHECK-NO: declare double @llvm.fma.f64(double, double, double) [[NUW_RN2]] +// CHECK-NO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[NUW_RN2]] // Just checking to make sure these library functions are marked readnone void test_builtins(double d, float f, long double ld) { @@ -81,40 +81,45 @@ void test_builtins(double d, float f, long double ld) { double atan_ = atan(d); long double atanl_ = atanl(ld); float atanf_ = atanf(f); -// CHECK-NO: declare double @atan(double) nounwind readnone -// CHECK-NO: declare x86_fp80 @atanl(x86_fp80) nounwind readnone -// CHECK-NO: declare float @atanf(float) nounwind readnone -// CHECK-YES-NOT: declare double @atan(double) nounwind readnone -// CHECK-YES-NOT: declare x86_fp80 @atanl(x86_fp80) nounwind readnone -// CHECK-YES-NOT: declare float @atanf(float) nounwind readnone +// CHECK-NO: declare double @atan(double) [[NUW_RN]] +// CHECK-NO: declare x86_fp80 @atanl(x86_fp80) [[NUW_RN]] +// CHECK-NO: declare float @atanf(float) [[NUW_RN]] +// CHECK-YES-NOT: declare double @atan(double) [[NUW_RN]] +// CHECK-YES-NOT: declare x86_fp80 @atanl(x86_fp80) [[NUW_RN]] +// CHECK-YES-NOT: declare float @atanf(float) [[NUW_RN]] double atan2_ = atan2(d, 2); long double atan2l_ = atan2l(ld, ld); float atan2f_ = atan2f(f, f); -// CHECK-NO: declare double @atan2(double, double) nounwind readnone -// CHECK-NO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) nounwind readnone -// CHECK-NO: declare float @atan2f(float, float) nounwind readnone -// CHECK-YES-NOT: declare double @atan2(double, double) nounwind readnone -// CHECK-YES-NOT: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) nounwind readnone -// CHECK-YES-NOT: declare float @atan2f(float, float) nounwind readnone +// CHECK-NO: declare double @atan2(double, double) [[NUW_RN]] +// CHECK-NO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NUW_RN]] +// CHECK-NO: declare float @atan2f(float, float) [[NUW_RN]] +// CHECK-YES-NOT: declare double @atan2(double, double) [[NUW_RN]] +// CHECK-YES-NOT: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NUW_RN]] +// CHECK-YES-NOT: declare float @atan2f(float, float) [[NUW_RN]] double exp_ = exp(d); long double expl_ = expl(ld); float expf_ = expf(f); -// CHECK-NO: declare double @exp(double) nounwind readnone -// CHECK-NO: declare x86_fp80 @expl(x86_fp80) nounwind readnone -// CHECK-NO: declare float @expf(float) nounwind readnone -// CHECK-YES-NOT: declare double @exp(double) nounwind readnone -// CHECK-YES-NOT: declare x86_fp80 @expl(x86_fp80) nounwind readnone -// CHECK-YES-NOT: declare float @expf(float) nounwind readnone +// CHECK-NO: declare double @exp(double) [[NUW_RN]] +// CHECK-NO: declare x86_fp80 @expl(x86_fp80) [[NUW_RN]] +// CHECK-NO: declare float @expf(float) [[NUW_RN]] +// CHECK-YES-NOT: declare double @exp(double) [[NUW_RN]] +// CHECK-YES-NOT: declare x86_fp80 @expl(x86_fp80) [[NUW_RN]] +// CHECK-YES-NOT: declare float @expf(float) [[NUW_RN]] double log_ = log(d); long double logl_ = logl(ld); float logf_ = logf(f); -// CHECK-NO: declare double @log(double) nounwind readnone -// CHECK-NO: declare x86_fp80 @logl(x86_fp80) nounwind readnone -// CHECK-NO: declare float @logf(float) nounwind readnone -// CHECK-YES-NOT: declare double @log(double) nounwind readnone -// CHECK-YES-NOT: declare x86_fp80 @logl(x86_fp80) nounwind readnone -// CHECK-YES-NOT: declare float @logf(float) nounwind readnone +// CHECK-NO: declare double @log(double) [[NUW_RN]] +// CHECK-NO: declare x86_fp80 @logl(x86_fp80) [[NUW_RN]] +// CHECK-NO: declare float @logf(float) [[NUW_RN]] +// CHECK-YES-NOT: declare double @log(double) [[NUW_RN]] +// CHECK-YES-NOT: declare x86_fp80 @logl(x86_fp80) [[NUW_RN]] +// CHECK-YES-NOT: declare float @logf(float) [[NUW_RN]] } + +// CHECK-YES: attributes [[NUW_RN]] = { nounwind readnone } + +// CHECK-NO: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } +// CHECK-NO: attributes [[NUW_RO]] = { nounwind readonly } diff --git a/test/CodeGen/lifetime2.c b/test/CodeGen/lifetime2.c new file mode 100644 index 0000000..ffff5cc --- /dev/null +++ b/test/CodeGen/lifetime2.c @@ -0,0 +1,17 @@ +// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefix=O2 +// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefix=O0 + +extern int bar(char *A, int n); + +// O0-NOT: @llvm.lifetime.start +int foo (int n) { + if (n) { +// O2: @llvm.lifetime.start + char A[100]; + return bar(A, 1); + } else { +// O2: @llvm.lifetime.start + char A[100]; + return bar(A, 2); + } +} diff --git a/test/CodeGen/linkage-redecl.c b/test/CodeGen/linkage-redecl.c index 09b51f0..14112fe 100644 --- a/test/CodeGen/linkage-redecl.c +++ b/test/CodeGen/linkage-redecl.c @@ -1,4 +1,11 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - |grep internal +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s + +// CHECK: @test2_i = internal global i32 99 +static int test2_i = 99; +int test2_f() { + extern int test2_i; + return test2_i; +} // C99 6.2.2p3 // PR3425 @@ -9,3 +16,4 @@ void g0() { } extern void f(int x) { } // still has internal linkage +// CHECK: define internal void @f diff --git a/test/CodeGen/mips-constraint-regs.c b/test/CodeGen/mips-constraint-regs.c index ea063b5..0d533f5 100644 --- a/test/CodeGen/mips-constraint-regs.c +++ b/test/CodeGen/mips-constraint-regs.c @@ -2,16 +2,14 @@ // RUN: | FileCheck %s // This checks that the frontend will accept inline asm constraints -// c', 'l' and 'x'. Semantic checking will happen in the -// llvm backend. Any bad constraint letters will cause the frontend to -// error out. +// c', 'l' and 'x'. int main() { // 'c': 16 bit address register for Mips16, GPR for all others // I am using 'c' to constrain both the target and one of the source // registers. We are looking for syntactical correctness. - // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "addi $0,$1,$2 \0A\09\09", "=c,c,I"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) nounwind, !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "addi $0,$1,$2 \0A\09\09", "=c,c,I"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) [[NUW:#[0-9]+]], !srcloc !{{[0-9]+}} int __s, __v = 17; int __t; __asm__ __volatile__( @@ -22,7 +20,7 @@ int main() // 'l': lo register // We are making it clear that destination register is lo with the // use of the 'l' constraint ("=l"). - // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "mtlo $1 \0A\09\09", "=l,r,~{lo}"(i32 %{{[0-9]+}}) nounwind, !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "mtlo $1 \0A\09\09", "=l,r,~{lo}"(i32 %{{[0-9]+}}) [[NUW]], !srcloc !{{[0-9]+}} int i_temp = 44; int i_result; __asm__ __volatile__( @@ -34,7 +32,7 @@ int main() // 'x': Combined lo/hi registers // We are specifying that destination registers are the hi/lo pair with the // use of the 'x' constraint ("=x"). - // CHECK: %{{[0-9]+}} = call i64 asm sideeffect "mthi $1 \0A\09\09mtlo $2 \0A\09\09", "=x,r,r"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) nounwind, !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i64 asm sideeffect "mthi $1 \0A\09\09mtlo $2 \0A\09\09", "=x,r,r"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) [[NUW]], !srcloc !{{[0-9]+}} int i_hi = 3; int i_lo = 2; long long ll_result = 0; @@ -47,3 +45,5 @@ int main() return 0; } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGen/mips-constraints-mem.c b/test/CodeGen/mips-constraints-mem.c new file mode 100644 index 0000000..ea6bcaf --- /dev/null +++ b/test/CodeGen/mips-constraints-mem.c @@ -0,0 +1,26 @@ +// RUN: %clang -target mipsel-unknown-linux -S -o - -emit-llvm %s \ +// RUN: | FileCheck %s + +// This checks that the frontend will accept inline asm memory constraints. + +int foo() +{ + + // 'R': An address that can be used in a non-macro load or stor' + // This test will result in the higher and lower nibbles being + // switched due to the lwl/lwr instruction pairs. + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "lwl $0, 1 + $1\0A\09lwr $0, 2 + $1\0A\09", "=r,*R"(i32* %{{[0-9,a-f]+}}) #1, !srcloc !0 + + int c = 0xffbbccdd; + + int *p = &c; + int out = 0; + + __asm volatile ( + "lwl %0, 1 + %1\n\t" + "lwr %0, 2 + %1\n\t" + : "=r"(out) + : "R"(*p) + ); + return 0; +} diff --git a/test/CodeGen/mips-target-data.c b/test/CodeGen/mips-target-data.c new file mode 100644 index 0000000..88eadcb --- /dev/null +++ b/test/CodeGen/mips-target-data.c @@ -0,0 +1,14 @@ +// RUN: %clang -target mipsel-linux-gnu -o - -emit-llvm -S %s |\ +// RUN: FileCheck %s -check-prefix=32EL +// RUN: %clang -target mips-linux-gnu -o - -emit-llvm -S %s |\ +// RUN: FileCheck %s -check-prefix=32EB +// RUN: %clang -target mips64el-linux-gnu -o - -emit-llvm -S %s |\ +// RUN: FileCheck %s -check-prefix=64EL +// RUN: %clang -target mips64-linux-gnu -o - -emit-llvm -S %s |\ +// RUN: FileCheck %s -check-prefix=64EB + +// 32EL: e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64 +// 32EB: E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64 +// 64EL: e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v64:64:64-n32:64-S128 +// 64EB: E-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v64:64:64-n32:64-S128 + diff --git a/test/CodeGen/mips-vector-arg.c b/test/CodeGen/mips-vector-arg.c index 584192f..6ffb043 100644 --- a/test/CodeGen/mips-vector-arg.c +++ b/test/CodeGen/mips-vector-arg.c @@ -8,21 +8,24 @@ typedef float v4sf __attribute__ ((__vector_size__ (16))); typedef int v4i32 __attribute__ ((__vector_size__ (16))); -// O32: define void @test_v4sf(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) nounwind +// O32: define void @test_v4sf(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) [[NUW:#[0-9]+]] // O32: declare i32 @test_v4sf_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -// N64: define void @test_v4sf(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) nounwind +// N64: define void @test_v4sf(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) [[NUW:#[0-9]+]] // N64: declare i32 @test_v4sf_2(i64, i64, i32, i64, i64, i64) extern test_v4sf_2(v4sf, int, v4sf); void test_v4sf(v4sf a1, int a2, v4sf a3) { test_v4sf_2(a3, a2, a1); } -// O32: define void @test_v4i32(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) nounwind +// O32: define void @test_v4i32(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) [[NUW]] // O32: declare i32 @test_v4i32_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -// N64: define void @test_v4i32(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) nounwind +// N64: define void @test_v4i32(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) [[NUW]] // N64: declare i32 @test_v4i32_2(i64, i64, i32, i64, i64, i64) extern test_v4i32_2(v4i32, int, v4i32); void test_v4i32(v4i32 a1, int a2, v4i32 a3) { test_v4i32_2(a3, a2, a1); } +// O32: attributes [[NUW]] = { nounwind{{.*}} } + +// N64: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/mips16-attr.c b/test/CodeGen/mips16-attr.c new file mode 100644 index 0000000..18799be --- /dev/null +++ b/test/CodeGen/mips16-attr.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple mipsel-linux-gnu -emit-llvm -o - %s | FileCheck %s +void __attribute__((mips16)) foo (void) { + +} + +// CHECK: define void @foo() [[MIPS16:#[0-9]+]] + +void __attribute__((nomips16)) nofoo (void) { + +} + +// CHECK: define void @nofoo() [[NOMIPS16:#[0-9]+]] + +// CHECK: attributes [[MIPS16]] = { nounwind {{.*}} "mips16" {{.*}} } + +// CHECK: attributes [[NOMIPS16]] = { nounwind {{.*}} "nomips16" {{.*}} } + diff --git a/test/CodeGen/mips64-padding-arg.c b/test/CodeGen/mips64-padding-arg.c index 9d7f877..85dc00c 100644 --- a/test/CodeGen/mips64-padding-arg.c +++ b/test/CodeGen/mips64-padding-arg.c @@ -1,4 +1,5 @@ -// RUN: %clang -target mips64el-unknown-linux -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s +// RUN: %clang -target mipsel-unknown-linux -O3 -S -o - -emit-llvm %s | FileCheck %s -check-prefix=O32 +// RUN: %clang -target mips64el-unknown-linux -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s -check-prefix=N64 typedef struct { double d; @@ -7,9 +8,9 @@ typedef struct { // Insert padding to ensure arguments of type S0 are aligned to 16-byte boundaries. -// CHECK: define void @foo1(i32 %a0, i64, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 %b, i64, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) -// CHECK: tail call void @foo2(i32 1, i32 2, i32 %a0, i64 undef, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 3, i64 undef, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) -// CHECK: declare void @foo2(i32, i32, i32, i64, double, i64, i64, i64, double, i64, i64, i64, i32, i64, double, i64, i64, i64) +// N64: define void @foo1(i32 %a0, i64, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 %b, i64, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) +// N64: tail call void @foo2(i32 1, i32 2, i32 %a0, i64 undef, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 3, i64 undef, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) +// N64: declare void @foo2(i32, i32, i32, i64, double, i64, i64, i64, double, i64, i64, i64, i32, i64, double, i64, i64, i64) extern void foo2(int, int, int, S0, S0, int, S0); @@ -19,9 +20,9 @@ void foo1(int a0, S0 a1, S0 a2, int b, S0 a3) { // Insert padding before long double argument. // -// CHECK: define void @foo3(i32 %a0, i64, fp128 %a1) -// CHECK: tail call void @foo4(i32 1, i32 2, i32 %a0, i64 undef, fp128 %a1) -// CHECK: declare void @foo4(i32, i32, i32, i64, fp128) +// N64: define void @foo3(i32 %a0, i64, fp128 %a1) +// N64: tail call void @foo4(i32 1, i32 2, i32 %a0, i64 undef, fp128 %a1) +// N64: declare void @foo4(i32, i32, i32, i64, fp128) extern void foo4(int, int, int, long double); @@ -31,9 +32,9 @@ void foo3(int a0, long double a1) { // Insert padding after hidden argument. // -// CHECK: define void @foo5(%struct.S0* noalias sret %agg.result, i64, fp128 %a0) -// CHECK: call void @foo6(%struct.S0* sret %agg.result, i32 1, i32 2, i64 undef, fp128 %a0) -// CHECK: declare void @foo6(%struct.S0* sret, i32, i32, i64, fp128) +// N64: define void @foo5(%struct.S0* noalias sret %agg.result, i64, fp128 %a0) +// N64: call void @foo6(%struct.S0* sret %agg.result, i32 1, i32 2, i64 undef, fp128 %a0) +// N64: declare void @foo6(%struct.S0* sret, i32, i32, i64, fp128) extern S0 foo6(int, int, long double); @@ -41,3 +42,14 @@ S0 foo5(long double a0) { return foo6(1, 2, a0); } +// Do not insert padding if ABI is O32. +// +// O32: define void @foo7(float %a0, double %a1) +// O32: declare void @foo8(float, double) + +extern void foo8(float, double); + +void foo7(float a0, double a1) { + foo8(a0 + 1.0f, a1 + 2.0); +} + diff --git a/test/CodeGen/mrtd.c b/test/CodeGen/mrtd.c index d7729a5..a40a59a 100644 --- a/test/CodeGen/mrtd.c +++ b/test/CodeGen/mrtd.c @@ -2,7 +2,7 @@ void baz(int arg); -// CHECK: define x86_stdcallcc void @foo(i32 %arg) nounwind +// CHECK: define x86_stdcallcc void @foo(i32 %arg) [[NUW:#[0-9]+]] void foo(int arg) { // CHECK: call x86_stdcallcc i32 bitcast (i32 (...)* @bar to i32 (i32)*)( bar(arg); @@ -13,3 +13,5 @@ void foo(int arg) { // CHECK: declare x86_stdcallcc i32 @bar(...) // CHECK: declare x86_stdcallcc void @baz(i32) + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c index 91862a7..26bdc58 100644 --- a/test/CodeGen/ms-declspecs.c +++ b/test/CodeGen/ms-declspecs.c @@ -8,17 +8,21 @@ union { struct S s; } u; // CHECK: @u = {{.*}}zeroinitializer, align 16 -// CHECK: define void @t3() nounwind noinline naked { +// CHECK: define void @t3() [[NAKED:#[0-9]+]] { __declspec(naked) void t3() {} -// CHECK: define void @t22() nounwind +// CHECK: define void @t22() [[NUW:#[0-9]+]] void __declspec(nothrow) t22(); void t22() {} -// CHECK: define void @t2() nounwind noinline { +// CHECK: define void @t2() [[NI:#[0-9]+]] { __declspec(noinline) void t2() {} -// CHECK: call void @f20_t() -// CHECK: noreturn +// CHECK: call void @f20_t() [[NR:#[0-9]+]] __declspec(noreturn) void f20_t(void); void f20(void) { f20_t(); } + +// CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noreturn } diff --git a/test/CodeGen/ms-inline-asm-64.c b/test/CodeGen/ms-inline-asm-64.c index a74ede0..8d2940d 100644 --- a/test/CodeGen/ms-inline-asm-64.c +++ b/test/CodeGen/ms-inline-asm-64.c @@ -1,16 +1,18 @@ // REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -O0 -fms-extensions -fenable-experimental-ms-inline-asm -w -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -O0 -fasm-blocks -emit-llvm -o - | FileCheck %s void t1() { int var = 10; __asm mov rax, offset var ; rax = address of myvar // CHECK: t1 -// CHECK: call void asm sideeffect inteldialect "mov rax, $0", "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov rax, $0", "r,~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) [[NUW:#[0-9]+]] } void t2() { int var = 10; __asm mov [eax], offset var // CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) [[NUW]] } + +// CHECK: attributes [[NUW]] = { nounwind } diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c index 7f43da8..d50ecfe 100644 --- a/test/CodeGen/ms-inline-asm.c +++ b/test/CodeGen/ms-inline-asm.c @@ -1,18 +1,18 @@ // REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -O0 -fms-extensions -fenable-experimental-ms-inline-asm -w -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -O0 -fasm-blocks -emit-llvm -o - | FileCheck %s void t1() { // CHECK: @t1 -// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm {} } void t2() { // CHECK: @t2 -// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm nop __asm nop @@ -21,15 +21,15 @@ void t2() { void t3() { // CHECK: @t3 -// CHECK: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm nop __asm nop __asm nop } void t4(void) { // CHECK: @t4 -// CHECK: call void asm sideeffect inteldialect "mov ebx, eax", "~{ebx},~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "mov ecx, ebx", "~{ecx},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "mov ebx, eax", "~{ebx},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov ecx, ebx", "~{ecx},~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm mov ebx, eax __asm mov ecx, ebx @@ -37,7 +37,7 @@ void t4(void) { void t5(void) { // CHECK: @t5 -// CHECK: call void asm sideeffect inteldialect "mov ebx, eax\0A\09mov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "mov ebx, eax\0A\09mov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm mov ebx, eax __asm mov ecx, ebx } @@ -45,7 +45,7 @@ void t5(void) { void t6(void) { __asm int 0x2c // CHECK: t6 -// CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"() } void t7() { @@ -54,8 +54,8 @@ void t7() { } __asm {} // CHECK: t7 -// CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() } int t8() { @@ -64,9 +64,9 @@ int t8() { __asm int 4 return 10; // CHECK: t8 -// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "int $$4", "~{dirflag},~{fpsr},~{flags}"() // CHECK: ret i32 10 } @@ -77,7 +77,7 @@ void t9() { pop ebx } // CHECK: t9 -// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() } unsigned t10(void) { @@ -91,7 +91,7 @@ unsigned t10(void) { // CHECK: [[I:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: [[J:%[a-zA-Z0-9]+]] = alloca i32, align 4 // CHECK: store i32 1, i32* [[I]], align 4 -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) // CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32* [[J]], align 4 // CHECK: ret i32 [[RET]] } @@ -99,7 +99,7 @@ unsigned t10(void) { void t11(void) { __asm mov eax, 1 // CHECK: t11 -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() } unsigned t12(void) { @@ -112,7 +112,7 @@ unsigned t12(void) { } return j + m; // CHECK: t12 -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $2\0A\09mov dword ptr $0, eax\0A\09mov eax, dword ptr $3\0A\09mov dword ptr $1, eax", "=*m,=*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $2\0A\09mov dword ptr $0, eax\0A\09mov eax, dword ptr $3\0A\09mov dword ptr $1, eax", "=*m,=*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t13() { @@ -121,8 +121,8 @@ void t13() { __asm movzx eax, i __asm movzx eax, j // CHECK: t13 -// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}) nounwind -// CHECK: call void asm sideeffect inteldialect "movzx eax, word ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i16* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "movzx eax, word ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i16* %{{.*}}) } void t14() { @@ -135,33 +135,38 @@ void t14() { .endif } // CHECK: t14 -// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, dword ptr $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect ".if 1\0A\09mov eax, dword ptr $0\0A\09.else\0A\09mov ebx, j\0A\09.endif", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } +int gvar = 10; void t15() { - int var = 10; - __asm mov eax, var ; eax = 10 - __asm mov eax, offset var ; eax = address of myvar + int lvar = 10; + __asm mov eax, lvar ; eax = 10 + __asm mov eax, offset lvar ; eax = address of lvar + __asm mov eax, offset gvar ; eax = address of gvar // CHECK: t15 -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind -// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @{{.*}}) } void t16() { int var = 10; __asm mov [eax], offset var // CHECK: t16 -// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) nounwind +// CHECK: call void asm sideeffect inteldialect "mov [eax], $0", "r,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) } void t17() { __asm _emit 0x4A __asm _emit 0x43 __asm _emit 0x4B + __asm _EMIT 0x4B // CHECK: t17 -// CHECK: call void asm sideeffect inteldialect ".byte 0x4A", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect ".byte 0x43", "~{dirflag},~{fpsr},~{flags}"() nounwind -// CHECK: call void asm sideeffect inteldialect ".byte 0x4B", "~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect ".byte 0x4A", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0x43", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0x4B", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0x4B", "~{dirflag},~{fpsr},~{flags}"() } struct t18_type { int a, b; }; @@ -177,7 +182,7 @@ int t18() { } return foo.b; // CHECK: t18 -// CHECK: call void asm sideeffect inteldialect "lea ebx, foo\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr foo\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "~{eax},~{dirflag},~{fpsr},~{flags}"() } int t19() { @@ -191,12 +196,197 @@ int t19() { } return foo.b; // CHECK: t19 -// CHECK: call void asm sideeffect inteldialect "lea ebx, foo\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "lea ebx, qword ptr foo\0A\09mov eax, [ebx].0\0A\09mov [ebx].4, ecx", "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t20() { + char bar; int foo; - __asm mov eax, TYPE foo + char _bar[2]; + int _foo[4]; + + __asm mov eax, LENGTH foo + __asm mov eax, LENGTH bar + __asm mov eax, LENGTH _foo + __asm mov eax, LENGTH _bar // CHECK: t20 -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() + + __asm mov eax, TYPE foo + __asm mov eax, TYPE bar + __asm mov eax, TYPE _foo + __asm mov eax, TYPE _bar +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() + + __asm mov eax, SIZE foo + __asm mov eax, SIZE bar + __asm mov eax, SIZE _foo + __asm mov eax, SIZE _bar +// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$16", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() +} + +void t21() { + __asm { + __asm push ebx + __asm mov ebx, 0x07 + __asm pop ebx + } +// CHECK: t21 +// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() +} + +extern void t22_helper(int x); +void t22() { + int x = 0; + __asm { + __asm push ebx + __asm mov ebx, esp + } + t22_helper(x); + __asm { + __asm mov esp, ebx + __asm pop ebx + } +// CHECK: t22 +// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, esp", "~{ebx},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void @t22_helper +// CHECK: call void asm sideeffect inteldialect "mov esp, ebx\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() +} + +void t23() { + __asm { + the_label: + } +// CHECK: t23 +// CHECK: call void asm sideeffect inteldialect "the_label:", "~{dirflag},~{fpsr},~{flags}"() +} + +void t24_helper(void) {} +void t24() { + __asm call t24_helper +// CHECK: t24 +// CHECK: call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(void ()* @t24_helper) +} + +void t25() { + __asm mov eax, 0ffffffffh + __asm mov eax, 0fh + __asm mov eax, 0a2h + __asm mov eax, 0xa2h + __asm mov eax, 0xa2 +// CHECK: t25 +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0ffffffffh", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0fh", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0a2h", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0xa2h", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0xa2", "~{eax},~{dirflag},~{fpsr},~{flags}"() +} + +void t26() { + __asm pushad + __asm mov eax, 0 + __asm __emit 0fh + __asm __emit 0a2h + __asm __EMIT 0a2h + __asm popad +// CHECK: t26 +// CHECK: call void asm sideeffect inteldialect "pushad", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$0", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0fh", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "popad", "~{dirflag},~{fpsr},~{flags}"() +} + +void t27() { + __asm mov eax, fs:[0h] +// CHECK: t27 +// CHECK: call void asm sideeffect inteldialect "mov eax, fs:[0h]", "~{eax},~{dirflag},~{fpsr},~{flags}"() +} + +void t28() { + __asm align 8 + __asm align 16; + __asm align 128; + __asm ALIGN 256; +// CHECK: t28 +// CHECK: call void asm sideeffect inteldialect ".align 3", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".align 4", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".align 7", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect ".align 8", "~{dirflag},~{fpsr},~{flags}"() +} + +void t29() { + int arr[2] = {0, 0}; + int olen = 0, osize = 0, otype = 0; + __asm mov olen, LENGTH arr + __asm mov osize, SIZE arr + __asm mov otype, TYPE arr +// CHECK: t29 +// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$2", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$8", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, $$4", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +} + +int results[2] = {13, 37}; +int *t30() +{ + int *res; + __asm lea edi, results + __asm mov res, edi + return res; +// CHECK: t30 +// CHECK: call void asm sideeffect inteldialect "lea edi, dword ptr $0", "*m,~{edi},~{dirflag},~{fpsr},~{flags}"([2 x i32]* @{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, edi", "=*m,~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}) +} + +void t31() { + __asm pushad + __asm popad +// CHECK: t31 +// CHECK: call void asm sideeffect inteldialect "pushad", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "popad", "~{dirflag},~{fpsr},~{flags}"() +} + +void t32() { + int i; + __asm mov eax, i + __asm mov eax, dword ptr i + __asm mov ax, word ptr i + __asm mov al, byte ptr i +// CHECK: t32 +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov ax, word ptr $0", "*m,~{ax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov al, byte ptr $0", "*m,~{al},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +} + +void t33() { + int i; + __asm mov eax, [i] + __asm mov eax, dword ptr [i] + __asm mov ax, word ptr [i] + __asm mov al, byte ptr [i] +// CHECK: t33 +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov ax, word ptr $0", "*m,~{ax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "mov al, byte ptr $0", "*m,~{al},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}) +} + +void t34() { + __asm prefetchnta 64[eax] + __asm mov eax, dword ptr 4[eax] +// CHECK: t34 +// CHECK: call void asm sideeffect inteldialect "prefetchnta $$64[eax]", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4[eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() } diff --git a/test/CodeGen/ms-inline-asm.cpp b/test/CodeGen/ms-inline-asm.cpp new file mode 100644 index 0000000..9c160be --- /dev/null +++ b/test/CodeGen/ms-inline-asm.cpp @@ -0,0 +1,26 @@ +// REQUIRES: x86-64-registered-target +// RUN: %clang_cc1 -x c++ %s -triple i386-apple-darwin10 -O0 -fasm-blocks -emit-llvm -o - | FileCheck %s + +struct Foo { + static int *ptr; + static int a, b; + struct Bar { + static int *ptr; + }; +}; + +void t1() { + Foo::ptr = (int *)0xDEADBEEF; + Foo::Bar::ptr = (int *)0xDEADBEEF; + __asm mov eax, Foo::ptr + __asm mov eax, Foo::Bar::ptr + __asm mov eax, [Foo::ptr] + __asm mov eax, dword ptr [Foo::ptr] + __asm mov eax, dword ptr [Foo::ptr] +// CHECK: @_Z2t1v +// CHECK: call void asm sideeffect inteldialect "mov eax, Foo::ptr", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, Foo::Bar::ptr", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, [Foo::ptr]", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr [Foo::ptr]", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr [Foo::ptr]", "~{eax},~{dirflag},~{fpsr},~{flags}"() +} diff --git a/test/CodeGen/mult-alt-generic.c b/test/CodeGen/mult-alt-generic.c index 1665f9c..6cf6f0a 100644 --- a/test/CodeGen/mult-alt-generic.c +++ b/test/CodeGen/mult-alt-generic.c @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -triple i686 %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64 %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple arm %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -triple cellspu %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple mblaze %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple mips %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple mipsel %s -emit-llvm -o - | FileCheck %s diff --git a/test/CodeGen/no-opt-volatile-memcpy.c b/test/CodeGen/no-opt-volatile-memcpy.c new file mode 100644 index 0000000..0fab363 --- /dev/null +++ b/test/CodeGen/no-opt-volatile-memcpy.c @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -O0 -triple=x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s +// rdar://11861085 + +struct s { + char filler [128]; + volatile int x; +}; + +struct s gs; + +void foo (void) { + struct s ls; + ls = ls; + gs = gs; + ls = gs; +} +// CHECK: define void @foo() +// CHECK: %[[LS:.*]] = alloca %struct.s, align 4 +// CHECK-NEXT: %[[ZERO:.*]] = bitcast %struct.s* %[[LS]] to i8* +// CHECK-NEXT: %[[ONE:.*]] = bitcast %struct.s* %[[LS]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[ZERO]], i8* %[[ONE]], i64 132, i32 4, i1 true) +// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true) +// CHECK-NEXT: %[[TWO:.*]] = bitcast %struct.s* %[[LS]] to i8* +// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* %[[TWO]], i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true) + + +struct s1 { + struct s y; +}; + +struct s1 s; + +void fee (void) { + s = s; + s.y = gs; +} +// CHECK: define void @fee() +// CHECK: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true) +// CHECK-NEXT: call void @llvm.memcpy.{{.*}}(i8* getelementptr inbounds (%struct.s1* @s, i32 0, i32 0, i32 0, i32 0), i8* getelementptr inbounds (%struct.s* @gs, i32 0, i32 0, i32 0), i64 132, i32 4, i1 true) + diff --git a/test/CodeGen/nvptx-cpus.c b/test/CodeGen/nvptx-cpus.c new file mode 100644 index 0000000..c9c7680 --- /dev/null +++ b/test/CodeGen/nvptx-cpus.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_20 -O3 -S -o %t %s -emit-llvm +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_21 -O3 -S -o %t %s -emit-llvm +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_30 -O3 -S -o %t %s -emit-llvm +// RUN: %clang_cc1 -triple nvptx-unknown-unknown -target-cpu sm_35 -O3 -S -o %t %s -emit-llvm + +// Make sure clang accepts all supported architectures. + +void foo(float* a, + float* b) { + a[0] = b[0]; +} diff --git a/test/CodeGen/packed-nest-unpacked.c b/test/CodeGen/packed-nest-unpacked.c index 6097e3f..7f486c9 100644 --- a/test/CodeGen/packed-nest-unpacked.c +++ b/test/CodeGen/packed-nest-unpacked.c @@ -60,6 +60,6 @@ struct YBitfield gbitfield; unsigned test7() { // CHECK: @test7 - // CHECK: load i32* bitcast (%struct.XBitfield* getelementptr inbounds (%struct.YBitfield* @gbitfield, i32 0, i32 1) to i32*), align 1 + // CHECK: load i32* bitcast (%struct.XBitfield* getelementptr inbounds (%struct.YBitfield* @gbitfield, i32 0, i32 1) to i32*), align 4 return gbitfield.y.b2; } diff --git a/test/CodeGen/packed-structure.c b/test/CodeGen/packed-structure.c index 3aeaa23..ffd98db 100644 --- a/test/CodeGen/packed-structure.c +++ b/test/CodeGen/packed-structure.c @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | opt -S -strip -o %t -// RUX: llvm-gcc -flto -S -O3 -o %t %s // RUN: FileCheck --check-prefix=CHECK-GLOBAL < %t %s // RUN: FileCheck --check-prefix=CHECK-FUNCTIONS < %t %s diff --git a/test/CodeGen/parameter-passing.c b/test/CodeGen/parameter-passing.c index e48815b..40610af 100644 --- a/test/CodeGen/parameter-passing.c +++ b/test/CodeGen/parameter-passing.c @@ -5,14 +5,10 @@ // We also check _Bool and empty structures, as these can have annoying // corner cases. -// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O3 -emit-llvm -o %t -// RUN: not grep '@g0' %t - -// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -O3 -emit-llvm -o %t -// RUN: not grep '@g0' %t - -// RUN: %clang_cc1 %s -triple powerpc-unknown-unknown -O3 -emit-llvm -o %t -// RUN: not grep '@g0' %t +// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O3 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-unknown -O3 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple powerpc-unknown-unknown -O3 -emit-llvm -o - | FileCheck %s +// CHECK-NOT: @g0 typedef _Bool BoolTy; typedef int ScalarTy; diff --git a/test/CodeGen/ppc-atomics.c b/test/CodeGen/ppc-atomics.c deleted file mode 100644 index 3fcb0fb..0000000 --- a/test/CodeGen/ppc-atomics.c +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=32 -// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=64 - -unsigned char c1, c2; -unsigned short s1, s2; -unsigned int i1, i2; -unsigned long long ll1, ll2; - -enum memory_order { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -}; - -void test1(void) { - (void)__atomic_load(&c1, &c2, memory_order_seq_cst); - (void)__atomic_load(&s1, &s2, memory_order_seq_cst); - (void)__atomic_load(&i1, &i2, memory_order_seq_cst); - (void)__atomic_load(&ll1, &ll2, memory_order_seq_cst); - -// 32: define void @test1 -// 32: load atomic i8* @c1 seq_cst -// 32: load atomic i16* @s1 seq_cst -// 32: load atomic i32* @i1 seq_cst -// 32: call void @__atomic_load(i32 8, i8* bitcast (i64* @ll1 to i8*) - -// 64: define void @test1 -// 64: load atomic i8* @c1 seq_cst -// 64: load atomic i16* @s1 seq_cst -// 64: load atomic i32* @i1 seq_cst -// 64: load atomic i64* @ll1 seq_cst -} diff --git a/test/CodeGen/ppc64-complex-parms.c b/test/CodeGen/ppc64-complex-parms.c new file mode 100644 index 0000000..92a6fa5 --- /dev/null +++ b/test/CodeGen/ppc64-complex-parms.c @@ -0,0 +1,184 @@ +// REQUIRES: ppc64-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s + +float crealf(_Complex float); +double creal(_Complex double); +long double creall(_Complex long double); + +float foo_float(_Complex float x) { + return crealf(x); +} + +// CHECK: define float @foo_float(float {{[%A-Za-z0-9.]+}}, float {{[%A-Za-z0-9.]+}}) [[NUW:#[0-9]+]] { + +double foo_double(_Complex double x) { + return creal(x); +} + +// CHECK: define double @foo_double(double {{[%A-Za-z0-9.]+}}, double {{[%A-Za-z0-9.]+}}) [[NUW]] { + +long double foo_long_double(_Complex long double x) { + return creall(x); +} + +// CHECK: define ppc_fp128 @foo_long_double(ppc_fp128 {{[%A-Za-z0-9.]+}}, ppc_fp128 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +int foo_int(_Complex int x) { + return __real__ x; +} + +// CHECK: define signext i32 @foo_int(i32 {{[%A-Za-z0-9.]+}}, i32 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +short foo_short(_Complex short x) { + return __real__ x; +} + +// CHECK: define signext i16 @foo_short(i16 {{[%A-Za-z0-9.]+}}, i16 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +signed char foo_char(_Complex signed char x) { + return __real__ x; +} + +// CHECK: define signext i8 @foo_char(i8 {{[%A-Za-z0-9.]+}}, i8 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +long foo_long(_Complex long x) { + return __real__ x; +} + +// CHECK: define i64 @foo_long(i64 {{[%A-Za-z0-9.]+}}, i64 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +long long foo_long_long(_Complex long long x) { + return __real__ x; +} + +// CHECK: define i64 @foo_long_long(i64 {{[%A-Za-z0-9.]+}}, i64 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +void bar_float(void) { + foo_float(2.0f - 2.5fi); +} + +// CHECK: define void @bar_float() [[NUW]] { +// CHECK: %[[VAR1:[A-Za-z0-9.]+]] = alloca { float, float }, align 4 +// CHECK: %[[VAR2:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }* %[[VAR1]], i32 0, i32 0 +// CHECK: %[[VAR3:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }* %[[VAR1]], i32 0, i32 1 +// CHECK: store float 2.000000e+00, float* %[[VAR2]] +// CHECK: store float -2.500000e+00, float* %[[VAR3]] +// CHECK: %[[VAR4:[A-Za-z0-9.]+]] = getelementptr { float, float }* %[[VAR1]], i32 0, i32 0 +// CHECK: %[[VAR5:[A-Za-z0-9.]+]] = load float* %[[VAR4]], align 1 +// CHECK: %[[VAR6:[A-Za-z0-9.]+]] = getelementptr { float, float }* %[[VAR1]], i32 0, i32 1 +// CHECK: %[[VAR7:[A-Za-z0-9.]+]] = load float* %[[VAR6]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call float @foo_float(float %[[VAR5]], float %[[VAR7]]) + +void bar_double(void) { + foo_double(2.0 - 2.5i); +} + +// CHECK: define void @bar_double() [[NUW]] { +// CHECK: %[[VAR11:[A-Za-z0-9.]+]] = alloca { double, double }, align 8 +// CHECK: %[[VAR12:[A-Za-z0-9.]+]] = getelementptr inbounds { double, double }* %[[VAR11]], i32 0, i32 0 +// CHECK: %[[VAR13:[A-Za-z0-9.]+]] = getelementptr inbounds { double, double }* %[[VAR11]], i32 0, i32 1 +// CHECK: store double 2.000000e+00, double* %[[VAR12]] +// CHECK: store double -2.500000e+00, double* %[[VAR13]] +// CHECK: %[[VAR14:[A-Za-z0-9.]+]] = getelementptr { double, double }* %[[VAR11]], i32 0, i32 0 +// CHECK: %[[VAR15:[A-Za-z0-9.]+]] = load double* %[[VAR14]], align 1 +// CHECK: %[[VAR16:[A-Za-z0-9.]+]] = getelementptr { double, double }* %[[VAR11]], i32 0, i32 1 +// CHECK: %[[VAR17:[A-Za-z0-9.]+]] = load double* %[[VAR16]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call double @foo_double(double %[[VAR15]], double %[[VAR17]]) + +void bar_long_double(void) { + foo_long_double(2.0L - 2.5Li); +} + +// CHECK: define void @bar_long_double() [[NUW]] { +// CHECK: %[[VAR21:[A-Za-z0-9.]+]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK: %[[VAR22:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 0 +// CHECK: %[[VAR23:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 1 +// CHECK: store ppc_fp128 0xM40000000000000000000000000000000, ppc_fp128* %[[VAR22]] +// CHECK: store ppc_fp128 0xMC0040000000000000000000000000000, ppc_fp128* %[[VAR23]] +// CHECK: %[[VAR24:[A-Za-z0-9.]+]] = getelementptr { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 0 +// CHECK: %[[VAR25:[A-Za-z0-9.]+]] = load ppc_fp128* %[[VAR24]], align 1 +// CHECK: %[[VAR26:[A-Za-z0-9.]+]] = getelementptr { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 1 +// CHECK: %[[VAR27:[A-Za-z0-9.]+]] = load ppc_fp128* %[[VAR26]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call ppc_fp128 @foo_long_double(ppc_fp128 %[[VAR25]], ppc_fp128 %[[VAR27]]) + +void bar_int(void) { + foo_int(2 - 3i); +} + +// CHECK: define void @bar_int() [[NUW]] { +// CHECK: %[[VAR31:[A-Za-z0-9.]+]] = alloca { i32, i32 }, align 4 +// CHECK: %[[VAR32:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }* %[[VAR31]], i32 0, i32 0 +// CHECK: %[[VAR33:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }* %[[VAR31]], i32 0, i32 1 +// CHECK: store i32 2, i32* %[[VAR32]] +// CHECK: store i32 -3, i32* %[[VAR33]] +// CHECK: %[[VAR34:[A-Za-z0-9.]+]] = getelementptr { i32, i32 }* %[[VAR31]], i32 0, i32 0 +// CHECK: %[[VAR35:[A-Za-z0-9.]+]] = load i32* %[[VAR34]], align 1 +// CHECK: %[[VAR36:[A-Za-z0-9.]+]] = getelementptr { i32, i32 }* %[[VAR31]], i32 0, i32 1 +// CHECK: %[[VAR37:[A-Za-z0-9.]+]] = load i32* %[[VAR36]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call signext i32 @foo_int(i32 %[[VAR35]], i32 %[[VAR37]]) + +void bar_short(void) { + foo_short(2 - 3i); +} + +// CHECK: define void @bar_short() [[NUW]] { +// CHECK: %[[VAR41:[A-Za-z0-9.]+]] = alloca { i16, i16 }, align 2 +// CHECK: %[[VAR42:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }* %[[VAR41]], i32 0, i32 0 +// CHECK: %[[VAR43:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }* %[[VAR41]], i32 0, i32 1 +// CHECK: store i16 2, i16* %[[VAR42]] +// CHECK: store i16 -3, i16* %[[VAR43]] +// CHECK: %[[VAR44:[A-Za-z0-9.]+]] = getelementptr { i16, i16 }* %[[VAR41]], i32 0, i32 0 +// CHECK: %[[VAR45:[A-Za-z0-9.]+]] = load i16* %[[VAR44]], align 1 +// CHECK: %[[VAR46:[A-Za-z0-9.]+]] = getelementptr { i16, i16 }* %[[VAR41]], i32 0, i32 1 +// CHECK: %[[VAR47:[A-Za-z0-9.]+]] = load i16* %[[VAR46]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call signext i16 @foo_short(i16 %[[VAR45]], i16 %[[VAR47]]) + +void bar_char(void) { + foo_char(2 - 3i); +} + +// CHECK: define void @bar_char() [[NUW]] { +// CHECK: %[[VAR51:[A-Za-z0-9.]+]] = alloca { i8, i8 }, align 1 +// CHECK: %[[VAR52:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }* %[[VAR51]], i32 0, i32 0 +// CHECK: %[[VAR53:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }* %[[VAR51]], i32 0, i32 1 +// CHECK: store i8 2, i8* %[[VAR52]] +// CHECK: store i8 -3, i8* %[[VAR53]] +// CHECK: %[[VAR54:[A-Za-z0-9.]+]] = getelementptr { i8, i8 }* %[[VAR51]], i32 0, i32 0 +// CHECK: %[[VAR55:[A-Za-z0-9.]+]] = load i8* %[[VAR54]], align 1 +// CHECK: %[[VAR56:[A-Za-z0-9.]+]] = getelementptr { i8, i8 }* %[[VAR51]], i32 0, i32 1 +// CHECK: %[[VAR57:[A-Za-z0-9.]+]] = load i8* %[[VAR56]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call signext i8 @foo_char(i8 %[[VAR55]], i8 %[[VAR57]]) + +void bar_long(void) { + foo_long(2L - 3Li); +} + +// CHECK: define void @bar_long() [[NUW]] { +// CHECK: %[[VAR61:[A-Za-z0-9.]+]] = alloca { i64, i64 }, align 8 +// CHECK: %[[VAR62:[A-Za-z0-9.]+]] = getelementptr inbounds { i64, i64 }* %[[VAR61]], i32 0, i32 0 +// CHECK: %[[VAR63:[A-Za-z0-9.]+]] = getelementptr inbounds { i64, i64 }* %[[VAR61]], i32 0, i32 1 +// CHECK: store i64 2, i64* %[[VAR62]] +// CHECK: store i64 -3, i64* %[[VAR63]] +// CHECK: %[[VAR64:[A-Za-z0-9.]+]] = getelementptr { i64, i64 }* %[[VAR61]], i32 0, i32 0 +// CHECK: %[[VAR65:[A-Za-z0-9.]+]] = load i64* %[[VAR64]], align 1 +// CHECK: %[[VAR66:[A-Za-z0-9.]+]] = getelementptr { i64, i64 }* %[[VAR61]], i32 0, i32 1 +// CHECK: %[[VAR67:[A-Za-z0-9.]+]] = load i64* %[[VAR66]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call i64 @foo_long(i64 %[[VAR65]], i64 %[[VAR67]]) + +void bar_long_long(void) { + foo_long_long(2LL - 3LLi); +} + +// CHECK: define void @bar_long_long() [[NUW]] { +// CHECK: %[[VAR71:[A-Za-z0-9.]+]] = alloca { i64, i64 }, align 8 +// CHECK: %[[VAR72:[A-Za-z0-9.]+]] = getelementptr inbounds { i64, i64 }* %[[VAR71]], i32 0, i32 0 +// CHECK: %[[VAR73:[A-Za-z0-9.]+]] = getelementptr inbounds { i64, i64 }* %[[VAR71]], i32 0, i32 1 +// CHECK: store i64 2, i64* %[[VAR72]] +// CHECK: store i64 -3, i64* %[[VAR73]] +// CHECK: %[[VAR74:[A-Za-z0-9.]+]] = getelementptr { i64, i64 }* %[[VAR71]], i32 0, i32 0 +// CHECK: %[[VAR75:[A-Za-z0-9.]+]] = load i64* %[[VAR74]], align 1 +// CHECK: %[[VAR76:[A-Za-z0-9.]+]] = getelementptr { i64, i64 }* %[[VAR71]], i32 0, i32 1 +// CHECK: %[[VAR77:[A-Za-z0-9.]+]] = load i64* %[[VAR76]], align 1 +// CHECK: %{{[A-Za-z0-9.]+}} = call i64 @foo_long_long(i64 %[[VAR75]], i64 %[[VAR77]]) + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/ppc64-complex-return.c b/test/CodeGen/ppc64-complex-return.c new file mode 100644 index 0000000..b3fd549 --- /dev/null +++ b/test/CodeGen/ppc64-complex-return.c @@ -0,0 +1,129 @@ +// REQUIRES: ppc64-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s + +float crealf(_Complex float); +double creal(_Complex double); +long double creall(_Complex long double); + +_Complex float foo_float(_Complex float x) { + return x; +} + +// CHECK: define { float, float } @foo_float(float {{[%A-Za-z0-9.]+}}, float {{[%A-Za-z0-9.]+}}) [[NUW:#[0-9]+]] { + +_Complex double foo_double(_Complex double x) { + return x; +} + +// CHECK: define { double, double } @foo_double(double {{[%A-Za-z0-9.]+}}, double {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex long double foo_long_double(_Complex long double x) { + return x; +} + +// CHECK: define { ppc_fp128, ppc_fp128 } @foo_long_double(ppc_fp128 {{[%A-Za-z0-9.]+}}, ppc_fp128 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex int foo_int(_Complex int x) { + return x; +} + +// CHECK: define { i32, i32 } @foo_int(i32 {{[%A-Za-z0-9.]+}}, i32 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex short foo_short(_Complex short x) { + return x; +} + +// CHECK: define { i16, i16 } @foo_short(i16 {{[%A-Za-z0-9.]+}}, i16 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex signed char foo_char(_Complex signed char x) { + return x; +} + +// CHECK: define { i8, i8 } @foo_char(i8 {{[%A-Za-z0-9.]+}}, i8 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex long foo_long(_Complex long x) { + return x; +} + +// CHECK: define { i64, i64 } @foo_long(i64 {{[%A-Za-z0-9.]+}}, i64 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +_Complex long long foo_long_long(_Complex long long x) { + return x; +} + +// CHECK: define { i64, i64 } @foo_long_long(i64 {{[%A-Za-z0-9.]+}}, i64 {{[%A-Za-z0-9.]+}}) [[NUW]] { + +float bar_float(void) { + return crealf(foo_float(2.0f - 2.5fi)); +} + +// CHECK: define float @bar_float() [[NUW]] { +// CHECK: [[VAR1:[%A-Za-z0-9.]+]] = call { float, float } @foo_float +// CHECK: extractvalue { float, float } [[VAR1]], 0 +// CHECK: extractvalue { float, float } [[VAR1]], 1 + +double bar_double(void) { + return creal(foo_double(2.0 - 2.5i)); +} + +// CHECK: define double @bar_double() [[NUW]] { +// CHECK: [[VAR2:[%A-Za-z0-9.]+]] = call { double, double } @foo_double +// CHECK: extractvalue { double, double } [[VAR2]], 0 +// CHECK: extractvalue { double, double } [[VAR2]], 1 + +long double bar_long_double(void) { + return creall(foo_long_double(2.0L - 2.5Li)); +} + +// CHECK: define ppc_fp128 @bar_long_double() [[NUW]] { +// CHECK: [[VAR3:[%A-Za-z0-9.]+]] = call { ppc_fp128, ppc_fp128 } @foo_long_double +// CHECK: extractvalue { ppc_fp128, ppc_fp128 } [[VAR3]], 0 +// CHECK: extractvalue { ppc_fp128, ppc_fp128 } [[VAR3]], 1 + +int bar_int(void) { + return __real__(foo_int(2 - 3i)); +} + +// CHECK: define signext i32 @bar_int() [[NUW]] { +// CHECK: [[VAR4:[%A-Za-z0-9.]+]] = call { i32, i32 } @foo_int +// CHECK: extractvalue { i32, i32 } [[VAR4]], 0 +// CHECK: extractvalue { i32, i32 } [[VAR4]], 1 + +short bar_short(void) { + return __real__(foo_short(2 - 3i)); +} + +// CHECK: define signext i16 @bar_short() [[NUW]] { +// CHECK: [[VAR5:[%A-Za-z0-9.]+]] = call { i16, i16 } @foo_short +// CHECK: extractvalue { i16, i16 } [[VAR5]], 0 +// CHECK: extractvalue { i16, i16 } [[VAR5]], 1 + +signed char bar_char(void) { + return __real__(foo_char(2 - 3i)); +} + +// CHECK: define signext i8 @bar_char() [[NUW]] { +// CHECK: [[VAR6:[%A-Za-z0-9.]+]] = call { i8, i8 } @foo_char +// CHECK: extractvalue { i8, i8 } [[VAR6]], 0 +// CHECK: extractvalue { i8, i8 } [[VAR6]], 1 + +long bar_long(void) { + return __real__(foo_long(2L - 3Li)); +} + +// CHECK: define i64 @bar_long() [[NUW]] { +// CHECK: [[VAR7:[%A-Za-z0-9.]+]] = call { i64, i64 } @foo_long +// CHECK: extractvalue { i64, i64 } [[VAR7]], 0 +// CHECK: extractvalue { i64, i64 } [[VAR7]], 1 + +long long bar_long_long(void) { + return __real__(foo_long_long(2LL - 3LLi)); +} + +// CHECK: define i64 @bar_long_long() [[NUW]] { +// CHECK: [[VAR8:[%A-Za-z0-9.]+]] = call { i64, i64 } @foo_long_long +// CHECK: extractvalue { i64, i64 } [[VAR8]], 0 +// CHECK: extractvalue { i64, i64 } [[VAR8]], 1 + + +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/ppc64-extend.c b/test/CodeGen/ppc64-extend.c index f4d6bf9..68d28c7 100644 --- a/test/CodeGen/ppc64-extend.c +++ b/test/CodeGen/ppc64-extend.c @@ -2,14 +2,15 @@ // RUN: %clang_cc1 -O0 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s void f1(int x) { return; } -// CHECK: define void @f1(i32 signext %x) nounwind +// CHECK: define void @f1(i32 signext %x) [[NUW:#[0-9]+]] void f2(unsigned int x) { return; } -// CHECK: define void @f2(i32 zeroext %x) nounwind +// CHECK: define void @f2(i32 zeroext %x) [[NUW]] int f3(void) { return 0; } -// CHECK: define signext i32 @f3() nounwind +// CHECK: define signext i32 @f3() [[NUW]] unsigned int f4(void) { return 0; } -// CHECK: define zeroext i32 @f4() nounwind +// CHECK: define zeroext i32 @f4() [[NUW]] +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/ppc64-varargs-complex.c b/test/CodeGen/ppc64-varargs-complex.c new file mode 100644 index 0000000..b65a773 --- /dev/null +++ b/test/CodeGen/ppc64-varargs-complex.c @@ -0,0 +1,73 @@ +// REQUIRES: ppc64-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s + +#include <stdarg.h> + +void testva (int n, ...) +{ + va_list ap; + + _Complex int i = va_arg(ap, _Complex int); + // CHECK: %[[VAR40:[A-Za-z0-9.]+]] = load i8** %[[VAR100:[A-Za-z0-9.]+]] + // CHECK-NEXT: %[[VAR41:[A-Za-z0-9.]+]] = getelementptr i8* %[[VAR40]], i64 16 + // CHECK-NEXT: store i8* %[[VAR41]], i8** %[[VAR100]] + // CHECK-NEXT: %[[VAR1:[A-Za-z0-9.]+]] = ptrtoint i8* %[[VAR40]] to i64 + // CHECK-NEXT: %[[VAR2:[A-Za-z0-9.]+]] = add i64 %[[VAR1]], 4 + // CHECK-NEXT: %[[VAR3:[A-Za-z0-9.]+]] = add i64 %[[VAR1]], 12 + // CHECK-NEXT: %[[VAR4:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR2]] to i32* + // CHECK-NEXT: %[[VAR5:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR3]] to i32* + // CHECK-NEXT: %[[VAR6:[A-Za-z0-9.]+]] = load i32* %[[VAR4]] + // CHECK-NEXT: %[[VAR7:[A-Za-z0-9.]+]] = load i32* %[[VAR5]] + // CHECK-NEXT: %[[VAR8:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }* %[[VAR0:[A-Za-z0-9.]+]], i32 0, i32 0 + // CHECK-NEXT: %[[VAR9:[A-Za-z0-9.]+]] = getelementptr inbounds { i32, i32 }* %[[VAR0]], i32 0, i32 1 + // CHECK-NEXT: store i32 %[[VAR6]], i32* %[[VAR8]] + // CHECK-NEXT: store i32 %[[VAR7]], i32* %[[VAR9]] + + _Complex short s = va_arg(ap, _Complex short); + // CHECK: %[[VAR50:[A-Za-z0-9.]+]] = load i8** %[[VAR100:[A-Za-z0-9.]+]] + // CHECK-NEXT: %[[VAR51:[A-Za-z0-9.]+]] = getelementptr i8* %[[VAR50]], i64 16 + // CHECK-NEXT: store i8* %[[VAR51]], i8** %[[VAR100]] + // CHECK: %[[VAR11:[A-Za-z0-9.]+]] = ptrtoint i8* %{{[A-Za-z0-9.]+}} to i64 + // CHECK-NEXT: %[[VAR12:[A-Za-z0-9.]+]] = add i64 %[[VAR11]], 6 + // CHECK-NEXT: %[[VAR13:[A-Za-z0-9.]+]] = add i64 %[[VAR11]], 14 + // CHECK-NEXT: %[[VAR14:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR12]] to i16* + // CHECK-NEXT: %[[VAR15:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR13]] to i16* + // CHECK-NEXT: %[[VAR16:[A-Za-z0-9.]+]] = load i16* %[[VAR14]] + // CHECK-NEXT: %[[VAR17:[A-Za-z0-9.]+]] = load i16* %[[VAR15]] + // CHECK-NEXT: %[[VAR18:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }* %[[VAR10:[A-Za-z0-9.]+]], i32 0, i32 0 + // CHECK-NEXT: %[[VAR19:[A-Za-z0-9.]+]] = getelementptr inbounds { i16, i16 }* %[[VAR10]], i32 0, i32 1 + // CHECK-NEXT: store i16 %[[VAR16]], i16* %[[VAR18]] + // CHECK-NEXT: store i16 %[[VAR17]], i16* %[[VAR19]] + + _Complex char c = va_arg(ap, _Complex char); + // CHECK: %[[VAR60:[A-Za-z0-9.]+]] = load i8** %[[VAR100:[A-Za-z0-9.]+]] + // CHECK-NEXT: %[[VAR61:[A-Za-z0-9.]+]] = getelementptr i8* %[[VAR60]], i64 16 + // CHECK-NEXT: store i8* %[[VAR61]], i8** %[[VAR100]] + // CHECK: %[[VAR21:[A-Za-z0-9.]+]] = ptrtoint i8* %{{[A-Za-z0-9.]+}} to i64 + // CHECK-NEXT: %[[VAR22:[A-Za-z0-9.]+]] = add i64 %[[VAR21]], 7 + // CHECK-NEXT: %[[VAR23:[A-Za-z0-9.]+]] = add i64 %[[VAR21]], 15 + // CHECK-NEXT: %[[VAR24:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR22]] to i8* + // CHECK-NEXT: %[[VAR25:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR23]] to i8* + // CHECK-NEXT: %[[VAR26:[A-Za-z0-9.]+]] = load i8* %[[VAR24]] + // CHECK-NEXT: %[[VAR27:[A-Za-z0-9.]+]] = load i8* %[[VAR25]] + // CHECK-NEXT: %[[VAR28:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }* %[[VAR20:[A-Za-z0-9.]+]], i32 0, i32 0 + // CHECK-NEXT: %[[VAR29:[A-Za-z0-9.]+]] = getelementptr inbounds { i8, i8 }* %[[VAR20]], i32 0, i32 1 + // CHECK-NEXT: store i8 %[[VAR26]], i8* %[[VAR28]] + // CHECK-NEXT: store i8 %[[VAR27]], i8* %[[VAR29]] + + _Complex float f = va_arg(ap, _Complex float); + // CHECK: %[[VAR70:[A-Za-z0-9.]+]] = load i8** %[[VAR100:[A-Za-z0-9.]+]] + // CHECK-NEXT: %[[VAR71:[A-Za-z0-9.]+]] = getelementptr i8* %[[VAR70]], i64 16 + // CHECK-NEXT: store i8* %[[VAR71]], i8** %[[VAR100]] + // CHECK: %[[VAR31:[A-Za-z0-9.]+]] = ptrtoint i8* %{{[A-Za-z0-9.]+}} to i64 + // CHECK-NEXT: %[[VAR32:[A-Za-z0-9.]+]] = add i64 %[[VAR31]], 4 + // CHECK-NEXT: %[[VAR33:[A-Za-z0-9.]+]] = add i64 %[[VAR31]], 12 + // CHECK-NEXT: %[[VAR34:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR32]] to float* + // CHECK-NEXT: %[[VAR35:[A-Za-z0-9.]+]] = inttoptr i64 %[[VAR33]] to float* + // CHECK-NEXT: %[[VAR36:[A-Za-z0-9.]+]] = load float* %[[VAR34]] + // CHECK-NEXT: %[[VAR37:[A-Za-z0-9.]+]] = load float* %[[VAR35]] + // CHECK-NEXT: %[[VAR38:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }* %[[VAR30:[A-Za-z0-9.]+]], i32 0, i32 0 + // CHECK-NEXT: %[[VAR39:[A-Za-z0-9.]+]] = getelementptr inbounds { float, float }* %[[VAR30]], i32 0, i32 1 + // CHECK-NEXT: store float %[[VAR36]], float* %[[VAR38]] + // CHECK-NEXT: store float %[[VAR37]], float* %[[VAR39]] +} diff --git a/test/CodeGen/pr2394.c b/test/CodeGen/pr2394.c index e43281a..f1091ec 100644 --- a/test/CodeGen/pr2394.c +++ b/test/CodeGen/pr2394.c @@ -1,7 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s struct __attribute((packed)) x {int a : 24;}; int a(struct x* g) { - // CHECK: load i16 - // CHECK: load i8 + // CHECK: load i24 return g->a; } diff --git a/test/CodeGen/pragma-weak.c b/test/CodeGen/pragma-weak.c index 2efc2eb..d4b1b9f 100644 --- a/test/CodeGen/pragma-weak.c +++ b/test/CodeGen/pragma-weak.c @@ -136,7 +136,7 @@ void __both3(void) {} void __a1(void) __attribute((noinline)); #pragma weak a1 = __a1 void __a1(void) {} -// CHECK: define void @__a1() {{.*}} noinline +// CHECK: define void @__a1() [[NI:#[0-9]+]] // attributes introduced BEFORE a combination of #pragma weak and alias() // hold... @@ -144,11 +144,11 @@ void __a3(void) __attribute((noinline)); #pragma weak a3 = __a3 void a3(void) __attribute((alias("__a3"))); void __a3(void) {} -// CHECK: define void @__a3() {{.*}} noinline +// CHECK: define void @__a3() [[NI]] #pragma weak xxx = __xxx __attribute((pure,noinline,const,fastcall)) void __xxx(void) { } -// CHECK: void @__xxx() {{.*}} noinline +// CHECK: void @__xxx() [[RN:#[0-9]+]] ///////////// PR10878: Make sure we can call a weak alias void SHA512Pad(void *context) {} @@ -179,3 +179,6 @@ void zzz(void){} // CHECK: define void @yyy() int correct_linkage; + +// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[RN]] = { noinline nounwind readnone{{.*}} } diff --git a/test/CodeGen/prefetchw-builtins.c b/test/CodeGen/prefetchw-builtins.c new file mode 100644 index 0000000..9c5fdc7 --- /dev/null +++ b/test/CodeGen/prefetchw-builtins.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +prfchw -emit-llvm -o - %s | FileCheck %s + +// Don't include mm_malloc.h, it's system specific. +#define __MM_MALLOC_H + +#include <x86intrin.h> + +void prefetch_w(void *p) { + return _m_prefetchw(p); +// CHECK: @prefetch_w +// CHECK: call void @llvm.prefetch({{.*}}, i32 1, i32 3, i32 1) +} diff --git a/test/CodeGen/r5.c b/test/CodeGen/r5.c new file mode 100644 index 0000000..30a0c0d --- /dev/null +++ b/test/CodeGen/r5.c @@ -0,0 +1,5 @@ +// RUN: %clang -target armv7-none-linux-gnueabi -mcpu=cortex-r5 -emit-llvm -S %s -o /dev/null + +int main() { + return 0; +} diff --git a/test/CodeGen/rdrand-builtins.c b/test/CodeGen/rdrand-builtins.c index b7970f4..15414a3 100644 --- a/test/CodeGen/rdrand-builtins.c +++ b/test/CodeGen/rdrand-builtins.c @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +rdrnd -emit-llvm -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - %s | FileCheck %s // Don't include mm_malloc.h, it's system specific. #define __MM_MALLOC_H -#include <immintrin.h> +#include <x86intrin.h> int rdrand16(unsigned short *p) { return _rdrand16_step(p); @@ -25,3 +25,24 @@ int rdrand64(unsigned long long *p) { // CHECK: call { i64, i32 } @llvm.x86.rdrand.64 // CHECK: store i64 } + +int rdseed16(unsigned short *p) { + return _rdseed16_step(p); +// CHECK: @rdseed16 +// CHECK: call { i16, i32 } @llvm.x86.rdseed.16 +// CHECK: store i16 +} + +int rdseed32(unsigned *p) { + return _rdseed32_step(p); +// CHECK: @rdseed32 +// CHECK: call { i32, i32 } @llvm.x86.rdseed.32 +// CHECK: store i32 +} + +int rdseed64(unsigned long long *p) { + return _rdseed64_step(p); +// CHECK: @rdseed64 +// CHECK: call { i64, i32 } @llvm.x86.rdseed.64 +// CHECK: store i64 +} diff --git a/test/CodeGen/regparm.c b/test/CodeGen/regparm.c index d628b68..4c3752c 100644 --- a/test/CodeGen/regparm.c +++ b/test/CodeGen/regparm.c @@ -20,7 +20,7 @@ void f1(int i, int j, int k) { } int main(void) { - // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.foo* inreg null + // CHECK: call void @reduced(i8 inreg signext 0, {{.*}} %struct.foo* inreg null reduced(0, 0.0, 0, 0.0, 0); // CHECK: call x86_stdcallcc void {{.*}}(i32 inreg 1, i32 inreg 2) bar(1,2); diff --git a/test/CodeGen/rtm-builtins.c b/test/CodeGen/rtm-builtins.c index c4939a9..5660d8e 100644 --- a/test/CodeGen/rtm-builtins.c +++ b/test/CodeGen/rtm-builtins.c @@ -21,3 +21,8 @@ test_xabort(void) { // CHECK: void @llvm.x86.xabort(i8 2) _xabort(2); } + +unsigned int test_xtest(void) { + // CHECK: i32 @llvm.x86.xtest() + return _xtest(); +} diff --git a/test/CodeGen/sanitize-init-order.cpp b/test/CodeGen/sanitize-init-order.cpp new file mode 100644 index 0000000..3e94620 --- /dev/null +++ b/test/CodeGen/sanitize-init-order.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsanitize=address,init-order -emit-llvm -o - %s | FileCheck %s + +struct PODStruct { + int x; +}; +PODStruct s1; + +struct PODWithDtor { + ~PODWithDtor() { } + int x; +}; +PODWithDtor s2; + +struct PODWithCtorAndDtor { + PODWithCtorAndDtor() { } + ~PODWithCtorAndDtor() { } + int x; +}; +PODWithCtorAndDtor s3; + +// Check that ASan init-order checking ignores structs with trivial default +// constructor. +// CHECK: !llvm.asan.dynamically_initialized_globals = !{[[GLOB:![0-9]+]]} +// CHECK: [[GLOB]] = metadata !{%struct.PODWithCtorAndDtor diff --git a/test/CodeGen/sanitize-recover.c b/test/CodeGen/sanitize-recover.c new file mode 100644 index 0000000..3c9c895 --- /dev/null +++ b/test/CodeGen/sanitize-recover.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=RECOVER +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow -fno-sanitize-recover %s -emit-llvm -o - | FileCheck %s --check-prefix=ABORT + + +// RECOVER: @test +// ABORT: @test +void test() { + extern volatile unsigned x, y, z; + + // RECOVER: uadd.with.overflow.i32 + // RECOVER: ubsan_handle_add_overflow( + // RECOVER-NOT: unreachable + // ABORT: uadd.with.overflow.i32 + // ABORT: ubsan_handle_add_overflow_abort( + // ABORT: unreachable + x = y + z; +} diff --git a/test/CodeGen/sanitize-thread-attr.cpp b/test/CodeGen/sanitize-thread-attr.cpp new file mode 100644 index 0000000..fe5d810 --- /dev/null +++ b/test/CodeGen/sanitize-thread-attr.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s +// RUN: echo "src:%s" > %t +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s + +// REQUIRES: shell + +// The sanitize_thread attribute should be attached to functions +// when ThreadSanitizer is enabled, unless no_sanitize_thread attribute +// is present. + +// WITHOUT: NoTSAN1{{.*}}) [[NOATTR:#[0-9]+]] +// BL: NoTSAN1{{.*}}) [[NOATTR:#[0-9]+]] +// TSAN: NoTSAN1{{.*}}) [[NOATTR:#[0-9]+]] +__attribute__((no_sanitize_thread)) +int NoTSAN1(int *a) { return *a; } + +// WITHOUT: NoTSAN2{{.*}}) [[NOATTR]] +// BL: NoTSAN2{{.*}}) [[NOATTR]] +// TSAN: NoTSAN2{{.*}}) [[NOATTR]] +__attribute__((no_sanitize_thread)) +int NoTSAN2(int *a); +int NoTSAN2(int *a) { return *a; } + +// WITHOUT: TSANOk{{.*}}) [[NOATTR]] +// BL: TSANOk{{.*}}) [[NOATTR]] +// TSAN: TSANOk{{.*}}) [[WITH:#[0-9]+]] +int TSANOk(int *a) { return *a; } + +// WITHOUT: TemplateTSANOk{{.*}}) [[NOATTR]] +// BL: TemplateTSANOk{{.*}}) [[NOATTR]] +// TSAN: TemplateTSANOk{{.*}}) [[WITH]] +template<int i> +int TemplateTSANOk() { return i; } + +// WITHOUT: TemplateNoTSAN{{.*}}) [[NOATTR]] +// BL: TemplateNoTSAN{{.*}}) [[NOATTR]] +// TSAN: TemplateNoTSAN{{.*}}) [[NOATTR]] +template<int i> +__attribute__((no_sanitize_thread)) +int TemplateNoTSAN() { return i; } + +int force_instance = TemplateTSANOk<42>() + + TemplateNoTSAN<42>(); + +// Check that __cxx_global_var_init* get the sanitize_thread attribute. +int global1 = 0; +int global2 = *(int*)((char*)&global1+1); +// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// BL: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// TSAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] + +// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} } +// WITHOUT: attributes [[NOATTR_NO_TF]] = { nounwind } + +// BL: attributes [[NOATTR]] = { nounwind{{.*}} } +// BL: attributes [[NOATTR_NO_TF]] = { nounwind{{.*}} } + +// TSAN: attributes [[NOATTR]] = { nounwind{{.*}} } +// TSAN: attributes [[WITH]] = { nounwind sanitize_thread{{.*}} } +// TSAN: attributes [[WITH_NO_TF]] = { nounwind sanitize_thread } diff --git a/test/CodeGen/sanitize-use-after-scope.c b/test/CodeGen/sanitize-use-after-scope.c new file mode 100644 index 0000000..8f92038 --- /dev/null +++ b/test/CodeGen/sanitize-use-after-scope.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -S -emit-llvm -o - -fsanitize=address,use-after-scope %s \ +// RUN: | FileCheck %s -check-prefix=USE-AFTER-SCOPE +// RUN: %clang_cc1 -S -emit-llvm -o - -fsanitize=address %s \ +// RUN: | FileCheck %s -check-prefix=ADDRESS-ONLY + +extern int bar(char *A, int n); + +// ADDRESS-ONLY-NOT: @llvm.lifetime.start +int foo (int n) { + if (n) { + // USE-AFTER-SCOPE: @llvm.lifetime.start(i64 10, i8* {{.*}}) + char A[10]; + return bar(A, 1); + // USE-AFTER-SCOPE: @llvm.lifetime.end(i64 10, i8* {{.*}}) + } else { + // USE-AFTER-SCOPE: @llvm.lifetime.start(i64 20, i8* {{.*}}) + char A[20]; + return bar(A, 2); + // USE-AFTER-SCOPE: @llvm.lifetime.end(i64 20, i8* {{.*}}) + } +} + diff --git a/test/CodeGen/split-debug-filename.c b/test/CodeGen/split-debug-filename.c new file mode 100644 index 0000000..63970a8 --- /dev/null +++ b/test/CodeGen/split-debug-filename.c @@ -0,0 +1,7 @@ +// RUN: %clang -target x86_64-linux-gnu -gsplit-dwarf -S -emit-llvm -o - %s | FileCheck %s +int main (void) { + return 0; +} + +// Testing to ensure that the dwo name gets output into the compile unit. +// CHECK: split-debug-filename.dwo diff --git a/test/CodeGen/stack-protector.c b/test/CodeGen/stack-protector.c index eb4cea2..e47e5b3 100644 --- a/test/CodeGen/stack-protector.c +++ b/test/CodeGen/stack-protector.c @@ -1,14 +1,24 @@ // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 0 | FileCheck -check-prefix=NOSSP %s -// NOSSP: define void @test1(i8* %msg) nounwind { +// NOSSP: define void @test1(i8* %msg) #0 { // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 1 | FileCheck -check-prefix=WITHSSP %s -// WITHSSP: define void @test1(i8* %msg) nounwind ssp { +// WITHSSP: define void @test1(i8* %msg) #0 { // RUN: %clang_cc1 -emit-llvm -o - %s -stack-protector 2 | FileCheck -check-prefix=SSPREQ %s -// SSPREQ: define void @test1(i8* %msg) nounwind sspreq { +// SSPREQ: define void @test1(i8* %msg) #0 { + +typedef __SIZE_TYPE__ size_t; int printf(const char * _Format, ...); +size_t strlen(const char *s); +char *strcpy(char *s1, const char *s2); void test1(const char *msg) { char a[strlen(msg) + 1]; strcpy(a, msg); printf("%s\n", a); } + +// NOSSP: attributes #{{.*}} = { nounwind{{.*}} } + +// WITHSSP: attributes #{{.*}} = { nounwind ssp{{.*}} } + +// SSPREQ: attributes #{{.*}} = { nounwind sspreq{{.*}} } diff --git a/test/CodeGen/string-literal.c b/test/CodeGen/string-literal.c index 12d431a..8bc97f1 100644 --- a/test/CodeGen/string-literal.c +++ b/test/CodeGen/string-literal.c @@ -1,80 +1,107 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=C %s -// RUN: %clang_cc1 -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=C %s -// RUN: %clang_cc1 -x c++ -std=c++11 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CPP0X %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C %s +// RUN: %clang_cc1 -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C %s +// RUN: %clang_cc1 -x c++ -std=c++11 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-CXX11 %s +// RUN: %clang_cc1 -x c -std=c11 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-C11 %s #include <stddef.h> +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +typedef __CHAR16_TYPE__ char16_t; +typedef __CHAR32_TYPE__ char32_t; +#endif + int main() { // CHECK-C: private unnamed_addr constant [10 x i8] c"abc\00\00\00\00\00\00\00", align 1 - // CHECK-CPP0X: private unnamed_addr constant [10 x i8] c"abc\00\00\00\00\00\00\00", align 1 + // CHECK-C11: private unnamed_addr constant [10 x i8] c"abc\00\00\00\00\00\00\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [10 x i8] c"abc\00\00\00\00\00\00\00", align 1 char a[10] = "abc"; // This should convert to utf8. // CHECK-C: private unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1 - // CHECK-CPP0X: private unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1 + // CHECK-C11: private unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1 char b[10] = "\u1120\u0220\U00102030"; // CHECK-C: private unnamed_addr constant [3 x i32] [i32 65, i32 66, i32 0], align 4 - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 65, i32 66, i32 0], align 4 + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 65, i32 66, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 65, i32 66, i32 0], align 4 const wchar_t *foo = L"AB"; // CHECK-C: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110027, i32 0], align 4 - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110027, i32 0], align 4 + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110027, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110027, i32 0], align 4 const wchar_t *bar = L"\u1234\U0010F00B"; // CHECK-C: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110028, i32 0], align 4 - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110028, i32 0], align 4 + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110028, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 4660, i32 1110028, i32 0], align 4 const wchar_t *baz = L"\u1234" "\U0010F00C"; -#if __cplusplus >= 201103L - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 67, i32 68, i32 0], align 4 +#if __cplusplus >= 201103L || __STDC_VERSION__ >= 201112L + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 67, i32 68, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 67, i32 68, i32 0], align 4 const char32_t *c = U"CD"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110028, i32 0], align 4 + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110028, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110028, i32 0], align 4 const char32_t *d = U"\u1235\U0010F00C"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110027, i32 0], align 4 + // CHECK-C11: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110027, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 4661, i32 1110027, i32 0], align 4 const char32_t *o = "\u1235" U"\U0010F00B"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i16] [i16 69, i16 70, i16 0], align 2 + // CHECK-C11: private unnamed_addr constant [3 x i16] [i16 69, i16 70, i16 0], align 2 + // CHECK-CXX11: private unnamed_addr constant [3 x i16] [i16 69, i16 70, i16 0], align 2 const char16_t *e = u"EF"; // This should convert to utf16. - // CHECK-CPP0X: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0], align 2 + // CHECK-C11: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0], align 2 + // CHECK-CXX11: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0], align 2 const char16_t *f = u"\u1120\u0220\U00102030"; // This should convert to utf16. - // CHECK-CPP0X: private unnamed_addr constant [5 x i16] [i16 4384, i16 800, i16 -9272, i16 -9168, i16 0], align 2 + // CHECK-C11: private unnamed_addr constant [5 x i16] [i16 4384, i16 800, i16 -9272, i16 -9168, i16 0], align 2 + // CHECK-CXX11: private unnamed_addr constant [5 x i16] [i16 4384, i16 800, i16 -9272, i16 -9168, i16 0], align 2 const char16_t *p = u"\u1120\u0320" "\U00102030"; - // CHECK-CPP0X: private unnamed_addr constant [4 x i8] c"def\00", align 1 + // CHECK-C11: private unnamed_addr constant [4 x i8] c"def\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [4 x i8] c"def\00", align 1 const char *g = u8"def"; - // CHECK-CPP0X: private unnamed_addr constant [4 x i8] c"ghi\00", align 1 +#ifdef __cplusplus + // CHECK-CXX11: private unnamed_addr constant [4 x i8] c"ghi\00", align 1 const char *h = R"foo(ghi)foo"; - // CHECK-CPP0X: private unnamed_addr constant [4 x i8] c"jkl\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [4 x i8] c"jkl\00", align 1 const char *i = u8R"bar(jkl)bar"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i16] [i16 71, i16 72, i16 0], align 2 + // CHECK-CXX11: private unnamed_addr constant [3 x i16] [i16 71, i16 72, i16 0], align 2 const char16_t *j = uR"foo(GH)foo"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 73, i32 74, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 73, i32 74, i32 0], align 4 const char32_t *k = UR"bar(IJ)bar"; - // CHECK-CPP0X: private unnamed_addr constant [3 x i32] [i32 75, i32 76, i32 0], align 4 + // CHECK-CXX11: private unnamed_addr constant [3 x i32] [i32 75, i32 76, i32 0], align 4 const wchar_t *l = LR"bar(KL)bar"; - // CHECK-CPP0X: private unnamed_addr constant [9 x i8] c"abc\5Cndef\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [9 x i8] c"abc\5Cndef\00", align 1 const char *m = R"(abc\ndef)"; - // CHECK-CPP0X: private unnamed_addr constant [8 x i8] c"abc\0Adef\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [8 x i8] c"abc\0Adef\00", align 1 const char *n = R"(abc def)"; - // CHECK-CPP0X: private unnamed_addr constant [11 x i8] c"abc\0Adefghi\00", align 1 + // CHECK-CXX11: private unnamed_addr constant [11 x i8] c"abc\0Adefghi\00", align 1 const char *q = R"(abc def)" "ghi"; + // CHECK-CXX11: private unnamed_addr constant [13 x i8] c"abc\5C\0A??=\0Adef\00", align 1 + const char *r = R\ +"(abc\ +??= +def)"; + +#endif #endif } diff --git a/test/CodeGen/struct-passing.c b/test/CodeGen/struct-passing.c index efb00ef..d28fee2 100644 --- a/test/CodeGen/struct-passing.c +++ b/test/CodeGen/struct-passing.c @@ -16,9 +16,12 @@ void __attribute__((pure)) f5(T1 a); void *ps[] = { f0, f1, f2, f3, f4, f5 }; -// CHECK: declare i32 @f0() nounwind readnone -// CHECK: declare i32 @f1() nounwind readonly +// CHECK: declare i32 @f0() [[RN:#[0-9]+]] +// CHECK: declare i32 @f1() [[RO:#[0-9]+]] // CHECK: declare void @f2({{.*}} sret) // CHECK: declare void @f3({{.*}} sret) // CHECK: declare void @f4({{.*}} byval align 4) // CHECK: declare void @f5({{.*}} byval align 4) + +// CHECK: attributes [[RN]] = { nounwind readnone{{.*}} } +// CHECK: attributes [[RO]] = { nounwind readonly{{.*}} } diff --git a/test/CodeGen/tbaa-struct.cpp b/test/CodeGen/tbaa-struct.cpp index 8b30aa0..12a6f4d 100644 --- a/test/CodeGen/tbaa-struct.cpp +++ b/test/CodeGen/tbaa-struct.cpp @@ -14,4 +14,33 @@ void copy(struct A *a, struct A *b) { // CHECK: target datalayout = "{{.*}}p:[[P:64|32]] // CHECK: call void @llvm.memcpy.p0i8.p0i8.i[[P]](i8* %{{.*}}, i8* %{{.*}}, i[[P]] 16, i32 4, i1 false), !tbaa.struct [[TS:!.*]] + +struct B { + char c1; + struct A a; + int ii; +}; + +void copy2(struct B *a, struct B *b) { + *a = *b; +} + +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i[[P]](i8* %{{.*}}, i8* %{{.*}}, i[[P]] 24, i32 4, i1 false), !tbaa.struct [[TS2:!.*]] + +typedef _Complex int T2; +typedef _Complex char T5; +typedef _Complex int T7; +typedef struct T4 { T5 field0; T7 field1; } T4; +typedef union T1 { T2 field0; T4 field1; } T1; + +void copy3 (T1 *a, T1 *b) { + *a = *b; +} + +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i[[P]](i8* %{{.*}}, i8* %{{.*}}, i[[P]] 12, i32 4, i1 false), !tbaa.struct [[TS3:!.*]] + // CHECK: [[TS]] = metadata !{i64 0, i64 2, metadata !{{.*}}, i64 4, i64 4, metadata !{{.*}}, i64 8, i64 1, metadata !{{.*}}, i64 12, i64 4, metadata !{{.*}}} +// (offset, size) = (0,1) char; (4,2) short; (8,4) int; (12,1) char; (16,4) int; (20,4) int +// CHECK: [[TS2]] = metadata !{i64 0, i64 1, metadata !{{.*}}, i64 4, i64 2, metadata !{{.*}}, i64 8, i64 4, metadata !{{.*}}, i64 12, i64 1, metadata !{{.*}}, i64 16, i64 4, metadata {{.*}}, i64 20, i64 4, metadata {{.*}}} +// (offset, size) = (0,8) char; (0,2) char; (4,8) char +// CHECK: [[TS3]] = metadata !{i64 0, i64 8, metadata !{{.*}}, i64 0, i64 2, metadata !{{.*}}, i64 4, i64 8, metadata !{{.*}}} diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp new file mode 100644 index 0000000..c30e4a3 --- /dev/null +++ b/test/CodeGen/tbaa.cpp @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH +// Test TBAA metadata generated by front-end. + +#include <stdint.h> +typedef struct +{ + uint16_t f16; + uint32_t f32; + uint16_t f16_2; + uint32_t f32_2; +} StructA; +typedef struct +{ + uint16_t f16; + StructA a; + uint32_t f32; +} StructB; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; +} StructC; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; + uint8_t f8; +} StructD; + +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS; +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS2; + +uint32_t g(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 + *s = 1; + A->f32 = 4; + return *s; +} + +uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 + *s = 1; + A->f16 = 4; + return *s; +} + +uint32_t g3(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + A->f32 = 1; + B->a.f32 = 4; + return A->f32; +} + +uint32_t g4(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 + A->f32 = 1; + B->a.f16 = 4; + return A->f32; +} + +uint32_t g5(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 + A->f32 = 1; + B->f32 = 4; + return A->f32; +} + +uint32_t g6(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 + A->f32 = 1; + B->a.f32_2 = 4; + return A->f32; +} + +uint32_t g7(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 + A->f32 = 1; + S->f32 = 4; + return A->f32; +} + +uint32_t g8(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 + A->f32 = 1; + S->f16 = 4; + return A->f32; +} + +uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 + S->f32 = 1; + S2->f32 = 4; + return S->f32; +} + +uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 + S->f32 = 1; + S2->f16 = 4; + return S->f32; +} + +uint32_t g11(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 + C->b.a.f32 = 1; + D->b.a.f32 = 4; + return C->b.a.f32; +} + +uint32_t g12(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// TODO: differentiate the two accesses. +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + StructB *b1 = &(C->b); + StructB *b2 = &(D->b); + // b1, b2 have different context. + b1->a.f32 = 1; + b2->a.f32 = 4; + return b1->a.f32; +} + +// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"} +// CHECK: !4 = metadata !{metadata !"int", metadata !1} +// CHECK: !5 = metadata !{metadata !"short", metadata !1} + +// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// PATH: !4 = metadata !{metadata !"int", metadata !1} +// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} +// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !7 = metadata !{metadata !"short", metadata !1} +// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} +// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} +// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} +// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} +// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} +// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} +// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} +// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} +// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} +// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} +// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} +// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} +// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} +// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} diff --git a/test/CodeGen/ubsan-blacklist.c b/test/CodeGen/ubsan-blacklist.c new file mode 100644 index 0000000..6c67f02 --- /dev/null +++ b/test/CodeGen/ubsan-blacklist.c @@ -0,0 +1,31 @@ +// Verify ubsan doesn't emit checks for blacklisted functions and files +// RUN: echo "fun:hash" > %t-func.blacklist +// RUN: echo "src:%s" > %t-file.blacklist +// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT +// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-func.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FUNC +// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-file.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FILE + +// FIXME: %t-file.blacklist contains DOSish paths. +// REQUIRES: shell + +unsigned i; + +// DEFAULT: @hash +// FUNC: @hash +// FILE: @hash +unsigned hash() { +// DEFAULT: call void @__ubsan +// FUNC-NOT: call void @__ubsan +// FILE-NOT: call void @__ubsan + return i * 37; +} + +// DEFAULT: @add +// FUNC: @add +// FILE: @add +unsigned add() { +// DEFAULT: call void @__ubsan +// FUNC: call void @__ubsan +// FILE-NOT: call void @__ubsan + return i + 1; +} diff --git a/test/CodeGen/ucn-identifiers.c b/test/CodeGen/ucn-identifiers.c new file mode 100644 index 0000000..56e3aa5 --- /dev/null +++ b/test/CodeGen/ucn-identifiers.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -emit-llvm -o /dev/null +// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -x c++ +// This file contains UTF-8; please do not fix! + + +extern void \u00FCber(int); +extern void \U000000FCber(int); // redeclaration, no warning + +void goodCalls() { + \u00FCber(0); + \u00fcber(1); + über(2); + \U000000FCber(3); +} diff --git a/test/CodeGen/unreachable.c b/test/CodeGen/unreachable.c index 5e9fa6a..898f64e 100644 --- a/test/CodeGen/unreachable.c +++ b/test/CodeGen/unreachable.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s -// RUN: grep '@unreachable' %t | count 0 +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// CHECK-NOT: @unreachable extern void abort() __attribute__((noreturn)); extern int unreachable(); diff --git a/test/CodeGen/unsigned-overflow.c b/test/CodeGen/unsigned-overflow.c new file mode 100644 index 0000000..341ea35 --- /dev/null +++ b/test/CodeGen/unsigned-overflow.c @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s +// Verify checked operations are emitted for integers and longs. +// unsigned short/char's tested in unsigned-promotion.c + +unsigned long li, lj, lk; +unsigned int ii, ij, ik; + +extern void opaquelong(unsigned long); +extern void opaqueint(unsigned int); + +// CHECK: define void @testlongadd() +void testlongadd() { + + // CHECK: [[T1:%.*]] = load i64* @lj + // CHECK-NEXT: [[T2:%.*]] = load i64* @lk + // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_add_overflow + li = lj + lk; +} + +// CHECK: define void @testlongsub() +void testlongsub() { + + // CHECK: [[T1:%.*]] = load i64* @lj + // CHECK-NEXT: [[T2:%.*]] = load i64* @lk + // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[T1]], i64 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_sub_overflow + li = lj - lk; +} + +// CHECK: define void @testlongmul() +void testlongmul() { + + // CHECK: [[T1:%.*]] = load i64* @lj + // CHECK-NEXT: [[T2:%.*]] = load i64* @lk + // CHECK-NEXT: [[T3:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[T1]], i64 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_mul_overflow + li = lj * lk; +} + +// CHECK: define void @testlongpostinc() +void testlongpostinc() { + opaquelong(li++); + + // CHECK: [[T1:%.*]] = load i64* @li + // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1) + // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0 + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1 + // CHECK: call void @__ubsan_handle_add_overflow +} + +// CHECK: define void @testlongpreinc() +void testlongpreinc() { + opaquelong(++li); + + // CHECK: [[T1:%.*]] = load i64* @li + // CHECK-NEXT: [[T2:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[T1]], i64 1) + // CHECK-NEXT: [[T3:%.*]] = extractvalue { i64, i1 } [[T2]], 0 + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i64, i1 } [[T2]], 1 + // CHECK: call void @__ubsan_handle_add_overflow +} + +// CHECK: define void @testintadd() +void testintadd() { + + // CHECK: [[T1:%.*]] = load i32* @ij + // CHECK-NEXT: [[T2:%.*]] = load i32* @ik + // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_add_overflow + ii = ij + ik; +} + +// CHECK: define void @testintsub() +void testintsub() { + + // CHECK: [[T1:%.*]] = load i32* @ij + // CHECK-NEXT: [[T2:%.*]] = load i32* @ik + // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[T1]], i32 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_sub_overflow + ii = ij - ik; +} + +// CHECK: define void @testintmul() +void testintmul() { + + // CHECK: [[T1:%.*]] = load i32* @ij + // CHECK-NEXT: [[T2:%.*]] = load i32* @ik + // CHECK-NEXT: [[T3:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[T1]], i32 [[T2]]) + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T3]], 0 + // CHECK-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T3]], 1 + // CHECK: call void @__ubsan_handle_mul_overflow + ii = ij * ik; +} + +// CHECK: define void @testintpostinc() +void testintpostinc() { + opaqueint(ii++); + + // CHECK: [[T1:%.*]] = load i32* @ii + // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1) + // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0 + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1 + // CHECK: call void @__ubsan_handle_add_overflow +} + +// CHECK: define void @testintpreinc() +void testintpreinc() { + opaqueint(++ii); + + // CHECK: [[T1:%.*]] = load i32* @ii + // CHECK-NEXT: [[T2:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[T1]], i32 1) + // CHECK-NEXT: [[T3:%.*]] = extractvalue { i32, i1 } [[T2]], 0 + // CHECK-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T2]], 1 + // CHECK: call void @__ubsan_handle_add_overflow +} diff --git a/test/CodeGen/unsigned-promotion.c b/test/CodeGen/unsigned-promotion.c new file mode 100644 index 0000000..c263c0c --- /dev/null +++ b/test/CodeGen/unsigned-promotion.c @@ -0,0 +1,143 @@ +// Check -fsanitize=signed-integer-overflow and +// -fsanitize=unsigned-integer-overflow with promoted unsigned types +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \ +// RUN: -fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKS +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s \ +// RUN: -fsanitize=unsigned-integer-overflow | FileCheck %s --check-prefix=CHECKU + +unsigned short si, sj, sk; +unsigned char ci, cj, ck; + +extern void opaqueshort(unsigned short); +extern void opaquechar(unsigned char); + +// CHECKS: define void @testshortadd() +// CHECKU: define void @testshortadd() +void testshortadd() { + // CHECKS: load i16* @sj + // CHECKS: load i16* @sk + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_add_overflow + // + // CHECKU: [[T1:%.*]] = load i16* @sj + // CHECKU: [[T2:%.*]] = zext i16 [[T1]] + // CHECKU: [[T3:%.*]] = load i16* @sk + // CHECKU: [[T4:%.*]] = zext i16 [[T3]] + // CHECKU-NOT: llvm.sadd + // CHECKU-NOT: llvm.uadd + // CHECKU: [[T5:%.*]] = add nsw i32 [[T2]], [[T4]] + + si = sj + sk; +} + +// CHECKS: define void @testshortsub() +// CHECKU: define void @testshortsub() +void testshortsub() { + + // CHECKS: load i16* @sj + // CHECKS: load i16* @sk + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_sub_overflow + // + // CHECKU: [[T1:%.*]] = load i16* @sj + // CHECKU: [[T2:%.*]] = zext i16 [[T1]] + // CHECKU: [[T3:%.*]] = load i16* @sk + // CHECKU: [[T4:%.*]] = zext i16 [[T3]] + // CHECKU-NOT: llvm.ssub + // CHECKU-NOT: llvm.usub + // CHECKU: [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]] + + si = sj - sk; +} + +// CHECKS: define void @testshortmul() +// CHECKU: define void @testshortmul() +void testshortmul() { + + // CHECKS: load i16* @sj + // CHECKS: load i16* @sk + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_mul_overflow + // + // CHECKU: [[T1:%.*]] = load i16* @sj + // CHECKU: [[T2:%.*]] = zext i16 [[T1]] + // CHECKU: [[T3:%.*]] = load i16* @sk + // CHECKU: [[T4:%.*]] = zext i16 [[T3]] + // CHECKU-NOT: llvm.smul + // CHECKU-NOT: llvm.umul + // CHECKU: [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]] + si = sj * sk; +} + +// CHECKS: define void @testcharadd() +// CHECKU: define void @testcharadd() +void testcharadd() { + + // CHECKS: load i8* @cj + // CHECKS: load i8* @ck + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_add_overflow + // + // CHECKU: [[T1:%.*]] = load i8* @cj + // CHECKU: [[T2:%.*]] = zext i8 [[T1]] + // CHECKU: [[T3:%.*]] = load i8* @ck + // CHECKU: [[T4:%.*]] = zext i8 [[T3]] + // CHECKU-NOT: llvm.sadd + // CHECKU-NOT: llvm.uadd + // CHECKU: [[T5:%.*]] = add nsw i32 [[T2]], [[T4]] + + ci = cj + ck; +} + +// CHECKS: define void @testcharsub() +// CHECKU: define void @testcharsub() +void testcharsub() { + + // CHECKS: load i8* @cj + // CHECKS: load i8* @ck + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_sub_overflow + // + // CHECKU: [[T1:%.*]] = load i8* @cj + // CHECKU: [[T2:%.*]] = zext i8 [[T1]] + // CHECKU: [[T3:%.*]] = load i8* @ck + // CHECKU: [[T4:%.*]] = zext i8 [[T3]] + // CHECKU-NOT: llvm.ssub + // CHECKU-NOT: llvm.usub + // CHECKU: [[T5:%.*]] = sub nsw i32 [[T2]], [[T4]] + + ci = cj - ck; +} + +// CHECKS: define void @testcharmul() +// CHECKU: define void @testcharmul() +void testcharmul() { + + // CHECKS: load i8* @cj + // CHECKS: load i8* @ck + // CHECKS: [[T1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[T2:%.*]], i32 [[T3:%.*]]) + // CHECKS-NEXT: [[T4:%.*]] = extractvalue { i32, i1 } [[T1]], 0 + // CHECKS-NEXT: [[T5:%.*]] = extractvalue { i32, i1 } [[T1]], 1 + // CHECKS: call void @__ubsan_handle_mul_overflow + // + // CHECKU: [[T1:%.*]] = load i8* @cj + // CHECKU: [[T2:%.*]] = zext i8 [[T1]] + // CHECKU: [[T3:%.*]] = load i8* @ck + // CHECKU: [[T4:%.*]] = zext i8 [[T3]] + // CHECKU-NOT: llvm.smul + // CHECKU-NOT: llvm.umul + // CHECKU: [[T5:%.*]] = mul nsw i32 [[T2]], [[T4]] + + ci = cj * ck; +} diff --git a/test/CodeGen/unsigned-trapv.c b/test/CodeGen/unsigned-trapv.c new file mode 100644 index 0000000..b7aed03 --- /dev/null +++ b/test/CodeGen/unsigned-trapv.c @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=unsigned-integer-overflow | FileCheck %s --check-prefix=UNSIGNED +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=TRAPV +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=unsigned-integer-overflow -ftrapv | FileCheck %s --check-prefix=BOTH +// Verify that -ftrapv and -fsanitize=unsigned-integer-overflow +// work together as expected + + +// UNSIGNED: @test_signed +// TRAPV: @test_signed +// BOTH: @test_signed +void test_signed() { + extern volatile int a, b, c; + // UNSIGNED: add nsw i32 + // UNSIGNED-NOT: overflow + // TRAPV: sadd.with.overflow.i32 + // TRAPV-NOT: ubsan + // TRAPV: llvm.trap + // BOTH: sadd.with.overflow.i32 + // BOTH-NOT: ubsan + // BOTH: llvm.trap + a = b + c; +} + +// UNSIGNED: @test_unsigned +// TRAPV: @test_unsigned +// BOTH: @test_unsigned +void test_unsigned() { + extern volatile unsigned x, y, z; + // UNSIGNED: uadd.with.overflow.i32 + // UNSIGNED-NOT: llvm.trap + // UNSIGNED: ubsan + // TRAPV-NOT: overflow + // TRAPV-NOT: llvm.trap + // BOTH: uadd.with.overflow.i32 + // BOTH: ubsan + // BOTH-NOT: llvm.trap + x = y + z; +} diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c index 7a79cb6..e505a6e 100644 --- a/test/CodeGen/unwind-attr.c +++ b/test/CodeGen/unwind-attr.c @@ -3,22 +3,27 @@ int opaque(); -// CHECK: define [[INT:i.*]] @test0() { -// CHECK-NOEXC: define [[INT:i.*]] @test0() nounwind { +// CHECK: define [[INT:i.*]] @test0() [[TF:#[0-9]+]] { +// CHECK-NOEXC: define [[INT:i.*]] @test0() [[NUW:#[0-9]+]] { int test0(void) { return opaque(); } // <rdar://problem/8087431>: locally infer nounwind at -O0 -// CHECK: define [[INT:i.*]] @test1() nounwind { -// CHECK-NOEXC: define [[INT:i.*]] @test1() nounwind { +// CHECK: define [[INT:i.*]] @test1() [[NUW:#[0-9]+]] { +// CHECK-NOEXC: define [[INT:i.*]] @test1() [[NUW]] { int test1(void) { return 0; } // <rdar://problem/8283071>: not for weak functions -// CHECK: define weak [[INT:i.*]] @test2() { -// CHECK-NOEXC: define weak [[INT:i.*]] @test2() nounwind { +// CHECK: define weak [[INT:i.*]] @test2() [[TF]] { +// CHECK-NOEXC: define weak [[INT:i.*]] @test2() [[NUW]] { __attribute__((weak)) int test2(void) { return 0; } + +// CHECK: attributes [[TF]] = { "{{.*}} } +// CHECK: attributes [[NUW]] = { nounwind{{.*}} } + +// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} } diff --git a/test/CodeGen/visibility.c b/test/CodeGen/visibility.c index fa4b599..3082b7b 100644 --- a/test/CodeGen/visibility.c +++ b/test/CodeGen/visibility.c @@ -67,3 +67,10 @@ __private_extern__ void test3(void) {} // Top of file. extern int test4; __private_extern__ int test4 = 10; + +// rdar://12399248 +// CHECK-DEFAULT: define hidden void @test5() +// CHECK-PROTECTED: define hidden void @test5() +// CHECK-HIDDEN: define hidden void @test5() +__attribute__((availability(macosx,introduced=10.5,deprecated=10.6))) +__private_extern__ void test5(void) {} diff --git a/test/CodeGen/vla.c b/test/CodeGen/vla.c index e151827..f63796b 100644 --- a/test/CodeGen/vla.c +++ b/test/CodeGen/vla.c @@ -190,4 +190,8 @@ void test6(void) // CHECK-NEXT: store i32 0, i32* [[IX2]], align 4 } - +// Follow gcc's behavior for VLAs in parameter lists. PR9559. +void test7(int a[b(0)]) { + // CHECK: define void @test7( + // CHECK: call i32 @b(i8* null) +} diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c index 1a996de..0dcdc15 100644 --- a/test/CodeGen/volatile.c +++ b/test/CodeGen/volatile.c @@ -1,10 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm < %s -o %t -// RUN: grep volatile %t | count 28 -// RUN: grep memcpy %t | count 7 - -// The number 28 comes from the current codegen for volatile loads; -// if this number changes, it's not necessarily something wrong, but -// something has changed to affect volatile load/store codegen +// RUN: %clang_cc1 -emit-llvm < %s | FileCheck %s int S; volatile int vS; @@ -43,58 +37,171 @@ volatile_int vtS; int main() { int i; - +// CHECK: [[I:%[a-zA-Z0-9_.]+]] = alloca i32 // load i=S; +// CHECK: load i32* @S +// CHECK: store i32 {{.*}}, i32* [[I]] i=vS; +// CHECK: load volatile i32* @vS +// CHECK: store i32 {{.*}}, i32* [[I]] i=*pS; +// CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32** @pS +// CHECK: load i32* [[PS_VAL]] +// CHECK: store i32 {{.*}}, i32* [[I]] i=*pvS; +// CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32** @pvS +// CHECK: load volatile i32* [[PVS_VAL]] +// CHECK: store i32 {{.*}}, i32* [[I]] i=A[2]; +// CHECK: load i32* getelementptr {{.*}} @A +// CHECK: store i32 {{.*}}, i32* [[I]] i=vA[2]; +// CHECK: load volatile i32* getelementptr {{.*}} @vA +// CHECK: store i32 {{.*}}, i32* [[I]] i=F.x; +// CHECK: load i32* getelementptr {{.*}} @F +// CHECK: store i32 {{.*}}, i32* [[I]] i=vF.x; +// CHECK: load volatile i32* getelementptr {{.*}} @vF +// CHECK: store i32 {{.*}}, i32* [[I]] i=F2.x; +// CHECK: load i32* getelementptr {{.*}} @F2 +// CHECK: store i32 {{.*}}, i32* [[I]] i=vF2.x; +// CHECK: load volatile i32* getelementptr {{.*}} @vF2 +// CHECK: store i32 {{.*}}, i32* [[I]] i=vpF2->x; +// CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9_.]+}}** @vpF2 +// CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] +// CHECK: load volatile i32* [[ELT]] +// CHECK: store i32 {{.*}}, i32* [[I]] i=F3.x.y; +// CHECK: load i32* getelementptr {{.*}} @F3 +// CHECK: store i32 {{.*}}, i32* [[I]] i=vF3.x.y; +// CHECK: load volatile i32* getelementptr {{.*}} @vF3 +// CHECK: store i32 {{.*}}, i32* [[I]] i=BF.x; +// CHECK: load i8* getelementptr {{.*}} @BF +// CHECK: store i32 {{.*}}, i32* [[I]] i=vBF.x; +// CHECK: load volatile i8* getelementptr {{.*}} @vBF +// CHECK: store i32 {{.*}}, i32* [[I]] i=V[3]; +// CHECK: load <4 x i32>* @V +// CHECK: store i32 {{.*}}, i32* [[I]] i=vV[3]; +// CHECK: load volatile <4 x i32>* @vV +// CHECK: store i32 {{.*}}, i32* [[I]] i=VE.yx[1]; +// CHECK: load <4 x i32>* @VE +// CHECK: store i32 {{.*}}, i32* [[I]] i=vVE.zy[1]; +// CHECK: load volatile <4 x i32>* @vVE +// CHECK: store i32 {{.*}}, i32* [[I]] i = aggFct().x; // Note: not volatile + // N.b. Aggregate return is extremely target specific, all we can + // really say here is that there probably shouldn't be a volatile + // load. +// CHECK-NOT: load volatile +// CHECK: store i32 {{.*}}, i32* [[I]] i=vtS; +// CHECK: load volatile i32* @vtS +// CHECK: store i32 {{.*}}, i32* [[I]] // store S=i; +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* @S vS=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* @vS *pS=i; +// CHECK: load i32* [[I]] +// CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32** @pS +// CHECK: store i32 {{.*}}, i32* [[PS_VAL]] *pvS=i; +// CHECK: load i32* [[I]] +// CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32** @pvS +// CHECK: store volatile i32 {{.*}}, i32* [[PVS_VAL]] A[2]=i; +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @A vA[2]=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vA F.x=i; +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F vF.x=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF F2.x=i; +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F2 vF2.x=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF2 vpF2->x=i; +// CHECK: load i32* [[I]] +// CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9._]+}}** @vpF2 +// CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] +// CHECK: store volatile i32 {{.*}}, i32* [[ELT]] vF3.x.y=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF3 BF.x=i; +// CHECK: load i32* [[I]] +// CHECK: load i8* getelementptr {{.*}} @BF +// CHECK: store i8 {{.*}}, i8* getelementptr {{.*}} @BF vBF.x=i; +// CHECK: load i32* [[I]] +// CHECK: load volatile i8* getelementptr {{.*}} @vBF +// CHECK: store volatile i8 {{.*}}, i8* getelementptr {{.*}} @vBF V[3]=i; +// CHECK: load i32* [[I]] +// CHECK: load <4 x i32>* @V +// CHECK: store <4 x i32> {{.*}}, <4 x i32>* @V vV[3]=i; +// CHECK: load i32* [[I]] +// CHECK: load volatile <4 x i32>* @vV +// CHECK: store volatile <4 x i32> {{.*}}, <4 x i32>* @vV vtS=i; +// CHECK: load i32* [[I]] +// CHECK: store volatile i32 {{.*}}, i32* @vtS // other ops: ++S; +// CHECK: load i32* @S +// CHECK: store i32 {{.*}}, i32* @S ++vS; +// CHECK: load volatile i32* @vS +// CHECK: store volatile i32 {{.*}}, i32* @vS i+=S; +// CHECK: load i32* @S +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* [[I]] i+=vS; +// CHECK: load volatile i32* @vS +// CHECK: load i32* [[I]] +// CHECK: store i32 {{.*}}, i32* [[I]] ++vtS; +// CHECK: load volatile i32* @vtS +// CHECK: store volatile i32 {{.*}}, i32* @vtS (void)vF2; + // From vF2 to a temporary +// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* {{.*}} @vF2 {{.*}}, i1 true) vF2 = vF2; + // vF2 to itself +// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) vF2 = vF2 = vF2; + // vF2 to itself twice +// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) vF2 = (vF2, vF2); + // vF2 to a temporary, then vF2 to itself +// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* {{.*@vF2.*}}, i1 true) +// CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) } diff --git a/test/CodeGen/x86_32-arguments-darwin.c b/test/CodeGen/x86_32-arguments-darwin.c index 5bbc80b..4aa4295 100644 --- a/test/CodeGen/x86_32-arguments-darwin.c +++ b/test/CodeGen/x86_32-arguments-darwin.c @@ -229,7 +229,7 @@ v4i32 f55(v4i32 arg) { return arg+arg; } // CHECK: define void @f56( // CHECK: i8 signext %a0, %struct.s56_0* byval align 4 %a1, -// CHECK: x86_mmx %a2.coerce, %struct.s56_1* byval align 4, +// CHECK: i64 %a2.coerce, %struct.s56_1* byval align 4, // CHECK: i64 %a4.coerce, %struct.s56_2* byval align 4, // CHECK: <4 x i32> %a6, %struct.s56_3* byval align 16 %a7, // CHECK: <2 x double> %a8, %struct.s56_4* byval align 16 %a9, @@ -238,7 +238,7 @@ v4i32 f55(v4i32 arg) { return arg+arg; } // CHECK: call void (i32, ...)* @f56_0(i32 1, // CHECK: i32 %{{[^ ]*}}, %struct.s56_0* byval align 4 %{{[^ ]*}}, -// CHECK: x86_mmx %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, +// CHECK: i64 %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, // CHECK: i64 %{{[^ ]*}}, %struct.s56_2* byval align 4 %{{[^ ]*}}, // CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval align 16 %{{[^ ]*}}, // CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval align 16 %{{[^ ]*}}, @@ -337,3 +337,8 @@ T66 f66(int i, ...) { __builtin_va_end(ap); return v; } + +// PR14453 +struct s67 { _Complex unsigned short int a; }; +void f67(struct s67 x) {} +// CHECK: define void @f67(%struct.s67* byval align 4 %x) diff --git a/test/CodeGen/x86_32-arguments-linux.c b/test/CodeGen/x86_32-arguments-linux.c index 81dcaf6..e93f9dc 100644 --- a/test/CodeGen/x86_32-arguments-linux.c +++ b/test/CodeGen/x86_32-arguments-linux.c @@ -3,7 +3,7 @@ // CHECK: define void @f56( // CHECK: i8 signext %a0, %struct.s56_0* byval align 4 %a1, -// CHECK: x86_mmx %a2.coerce, %struct.s56_1* byval align 4, +// CHECK: i64 %a2.coerce, %struct.s56_1* byval align 4, // CHECK: <1 x double> %a4, %struct.s56_2* byval align 4, // CHECK: <4 x i32> %a6, %struct.s56_3* byval align 4, // CHECK: <2 x double> %a8, %struct.s56_4* byval align 4, @@ -12,7 +12,7 @@ // CHECK: call void (i32, ...)* @f56_0(i32 1, // CHECK: i32 %{{.*}}, %struct.s56_0* byval align 4 %{{[^ ]*}}, -// CHECK: x86_mmx %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, +// CHECK: i64 %{{[^ ]*}}, %struct.s56_1* byval align 4 %{{[^ ]*}}, // CHECK: <1 x double> %{{[^ ]*}}, %struct.s56_2* byval align 4 %{{[^ ]*}}, // CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval align 4 %{{[^ ]*}}, // CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval align 4 %{{[^ ]*}}, diff --git a/test/CodeGen/x86_32-inline-asm.c b/test/CodeGen/x86_32-inline-asm.c new file mode 100644 index 0000000..473f78e --- /dev/null +++ b/test/CodeGen/x86_32-inline-asm.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -verify %s +// <rdar://problem/12415959> + +typedef unsigned int u_int32_t; +typedef u_int32_t uint32_t; + +typedef unsigned long long u_int64_t; +typedef u_int64_t uint64_t; + +int func1() { + // Error out if size is > 32-bits. + uint32_t msr = 0x8b; + uint64_t val = 0; + __asm__ volatile("wrmsr" + : + : "c" (msr), + "a" ((val & 0xFFFFFFFFUL)), // expected-error {{invalid input size for constraint 'a'}} + "d" (((val >> 32) & 0xFFFFFFFFUL))); + + // Don't error out if the size of the destination is <= 32 bits. + unsigned char data; + unsigned int port; + __asm__ volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); // No error expected. +} diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index f73e1f0..518ee84 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -354,3 +354,41 @@ void test46() { v46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); } struct s47 { unsigned a; }; void f47(int,int,int,int,int,int,struct s47); void test47(int a, struct s47 b) { f47(a, a, a, a, a, a, b); } + +// rdar://12723368 +// In the following example, there are holes in T4 at the 3rd byte and the 4th +// byte, however, T2 does not have those holes. T4 is chosen to be the +// representing type for union T1, but we can't use load or store of T4 since +// it will skip the 3rd byte and the 4th byte. +// In general, Since we don't accurately represent the data fields of a union, +// do not use load or store of the representing llvm type for the union. +typedef _Complex int T2; +typedef _Complex char T5; +typedef _Complex int T7; +typedef struct T4 { T5 field0; T7 field1; } T4; +typedef union T1 { T2 field0; T4 field1; } T1; +extern T1 T1_retval; +T1 test48(void) { +// CHECK: @test48 +// CHECK: memcpy +// CHECK: memcpy + return T1_retval; +} + +void test49_helper(double, ...); +void test49(double d, double e) { + test49_helper(d, e); +} +// CHECK: define void @test49( +// CHECK: [[T0:%.*]] = load double* +// CHECK-NEXT: [[T1:%.*]] = load double* +// CHECK-NEXT: call void (double, ...)* @test49_helper(double [[T0]], double [[T1]]) + +void test50_helper(); +void test50(double d, double e) { + test50_helper(d, e); +} +// CHECK: define void @test50( +// CHECK: [[T0:%.*]] = load double* +// CHECK-NEXT: [[T1:%.*]] = load double* +// CHECK-NEXT: call void (double, double, ...)* bitcast (void (...)* @test50_helper to void (double, double, ...)*)(double [[T0]], double [[T1]]) |