diff options
Diffstat (limited to 'test/CodeGen')
154 files changed, 5036 insertions, 1111 deletions
diff --git a/test/CodeGen/2003-08-21-WideString.c b/test/CodeGen/2003-08-21-WideString.c index 4071d17c79708..1a6e5b7c88297 100644 --- a/test/CodeGen/2003-08-21-WideString.c +++ b/test/CodeGen/2003-08-21-WideString.c @@ -5,9 +5,9 @@ typedef __WCHAR_TYPE__ wchar_t; #if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \ || defined(_M_X64) || defined(SHORT_WCHAR) #define WCHAR_T_TYPE unsigned short -#elif defined(__sun) || defined(__AuroraUX__) +#elif defined(__sun) #define WCHAR_T_TYPE long -#else /* Solaris or AuroraUX. */ +#else /* Solaris. */ #define WCHAR_T_TYPE int #endif diff --git a/test/CodeGen/2005-06-15-ExpandGotoInternalProblem.c b/test/CodeGen/2005-06-15-ExpandGotoInternalProblem.c index dd1acc54bc1dc..0698601ad1335 100644 --- a/test/CodeGen/2005-06-15-ExpandGotoInternalProblem.c +++ b/test/CodeGen/2005-06-15-ExpandGotoInternalProblem.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c99 %s -emit-llvm -o - | \ -// RUN: opt -std-compile-opts -disable-output +// RUN: opt -O3 -disable-output // PR580 int X, Y; diff --git a/test/CodeGen/2005-09-24-AsmUserPrefix.c b/test/CodeGen/2005-09-24-AsmUserPrefix.c index 16283130beb09..d0e5bd1c3a444 100644 --- a/test/CodeGen/2005-09-24-AsmUserPrefix.c +++ b/test/CodeGen/2005-09-24-AsmUserPrefix.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | opt -std-compile-opts | llc | \ +// RUN: %clang_cc1 %s -emit-llvm -o - | opt -O3 | llc | \ // RUN: not grep _foo2 void foo() __asm__("foo2"); diff --git a/test/CodeGen/2007-06-18-SextAttrAggregate.c b/test/CodeGen/2007-06-18-SextAttrAggregate.c index 92171e2bd9b78..23c211d3ba042 100644 --- a/test/CodeGen/2007-06-18-SextAttrAggregate.c +++ b/test/CodeGen/2007-06-18-SextAttrAggregate.c @@ -1,11 +1,13 @@ // RUN: %clang_cc1 %s -o - -emit-llvm | FileCheck %s -// XFAIL: aarch64, arm64 +// XFAIL: aarch64, arm64, x86_64-pc-win32, x86_64-w64-mingw32 // PR1513 // AArch64 ABI actually requires the reverse of what this is testing: the callee // does any extensions and remaining bits are unspecified. +// Win64 ABI does expect extensions for type smaller than 64bits. + // Technically this test wasn't written to test that feature, but it's a // valuable check nevertheless. diff --git a/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c index 33bd800456f99..7401e114ddd0f 100644 --- a/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c +++ b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c @@ -8,5 +8,4 @@ struct et7 { 52, }; -// CHECK: @yv7 = global -// CHECK: i8 52, +// CHECK: @yv7 = global %struct.et7 { [0 x float] zeroinitializer, i8 52 } diff --git a/test/CodeGen/2009-07-15-pad-wchar_t-array.c b/test/CodeGen/2009-07-15-pad-wchar_t-array.c index df12cae90ea0f..4ae35158fa8ae 100644 --- a/test/CodeGen/2009-07-15-pad-wchar_t-array.c +++ b/test/CodeGen/2009-07-15-pad-wchar_t-array.c @@ -5,9 +5,9 @@ typedef __WCHAR_TYPE__ wchar_t; #if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \ || defined(_M_X64) || defined(SHORT_WCHAR) #define WCHAR_T_TYPE unsigned short -#elif defined(__sun) || defined(__AuroraUX__) +#elif defined(__sun) #define WCHAR_T_TYPE long -#else /* Solaris or AuroraUX. */ +#else /* Solaris. */ #define WCHAR_T_TYPE int #endif diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c index c48ad28ad0657..e56f227d2ac6a 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 !{{.*}}, 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 ] +// CHECK: !"0x34\00localstatic\00localstatic\00\005\001\001", !{{.*}}, !{{.*}}, !{{.*}}, i32* @main.localstatic, null} ; [ DW_TAG_variable ] +// CHECK: !"0x34\00global\00global\00\003\000\001", null, !{{.*}}, !{{.*}}, i32* @global, null} ; [ DW_TAG_variable ] diff --git a/test/CodeGen/2010-02-15-DbgStaticVar.c b/test/CodeGen/2010-02-15-DbgStaticVar.c index facd14e03ee6b..8980b60cf68d1 100644 --- a/test/CodeGen/2010-02-15-DbgStaticVar.c +++ b/test/CodeGen/2010-02-15-DbgStaticVar.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -g -emit-llvm %s -o - | grep "metadata ..b., metadata ..b., metadata ...," +// RUN: %clang_cc1 -g -emit-llvm %s -o - | FileCheck %s // Test to check intentionally empty linkage name for a static variable. // Radar 7651244. static int foo(int a) @@ -11,3 +11,4 @@ int main() { int j = foo(1); return 0; } +// CHECK: !"0x34\00b\00b\00\00{{.*}}", diff --git a/test/CodeGen/2010-07-08-DeclDebugLineNo.c b/test/CodeGen/2010-07-08-DeclDebugLineNo.c index 5e9edd9acd99e..44c973acda674 100644 --- a/test/CodeGen/2010-07-08-DeclDebugLineNo.c +++ b/test/CodeGen/2010-07-08-DeclDebugLineNo.c @@ -6,5 +6,5 @@ void foo() { int p = 0; // line #5: CHECK: {{call.*llvm.dbg.declare.*%p.*\!dbg }}[[variable_p:![0-9]+]] } // Now match the line number records: -// CHECK: {{^}}[[variable_l]]{{ = metadata ![{]i32 5,}} -// CHECK: {{^}}[[variable_p]]{{ = metadata ![{]i32 6,}} +// CHECK: {{^}}[[variable_l]] = !MDLocation(line: 5, +// CHECK: {{^}}[[variable_p]] = !MDLocation(line: 6, diff --git a/test/CodeGen/24-bit.c b/test/CodeGen/24-bit.c new file mode 100644 index 0000000000000..9dd0157fd3b4a --- /dev/null +++ b/test/CodeGen/24-bit.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -O0 -o - %s | FileCheck %s + +static union ibtt2 +{ + struct ibtt0 { signed ibt0:10; unsigned short ibt1; } ibt5; + struct ibtt1 { signed ibt2:3; signed ibt3:9; signed ibt4:9; } ibt6; +} ibt15 = {{267, 15266}}; + +void callee_ibt0f(union ibtt2 ibtp5); + +void test(void) { +// CHECK: = load i32* + callee_ibt0f(ibt15); +} diff --git a/test/CodeGen/Atomics.c b/test/CodeGen/Atomics.c index 684f36d404401..f957883575dee 100644 --- a/test/CodeGen/Atomics.c +++ b/test/CodeGen/Atomics.c @@ -49,6 +49,15 @@ void test_op_ignore (void) // CHECK-LABEL: define void @test_op_ignore (void) __sync_fetch_and_xor (&sll, 1); // CHECK: atomicrmw xor i64 (void) __sync_fetch_and_xor (&ull, 1); // CHECK: atomicrmw xor i64 + (void) __sync_fetch_and_nand (&sc, 1); // CHECK: atomicrmw nand i8 + (void) __sync_fetch_and_nand (&uc, 1); // CHECK: atomicrmw nand i8 + (void) __sync_fetch_and_nand (&ss, 1); // CHECK: atomicrmw nand i16 + (void) __sync_fetch_and_nand (&us, 1); // CHECK: atomicrmw nand i16 + (void) __sync_fetch_and_nand (&si, 1); // CHECK: atomicrmw nand i32 + (void) __sync_fetch_and_nand (&ui, 1); // CHECK: atomicrmw nand i32 + (void) __sync_fetch_and_nand (&sll, 1); // CHECK: atomicrmw nand i64 + (void) __sync_fetch_and_nand (&ull, 1); // CHECK: atomicrmw nand i64 + (void) __sync_fetch_and_and (&sc, 1); // CHECK: atomicrmw and i8 (void) __sync_fetch_and_and (&uc, 1); // CHECK: atomicrmw and i8 (void) __sync_fetch_and_and (&ss, 1); // CHECK: atomicrmw and i16 @@ -98,6 +107,15 @@ void test_fetch_and_op (void) // CHECK-LABEL: define void @test_fetch_and_op sll = __sync_fetch_and_xor (&sll, 11); // CHECK: atomicrmw xor ull = __sync_fetch_and_xor (&ull, 11); // CHECK: atomicrmw xor + sc = __sync_fetch_and_nand (&sc, 11); // CHECK: atomicrmw nand + uc = __sync_fetch_and_nand (&uc, 11); // CHECK: atomicrmw nand + ss = __sync_fetch_and_nand (&ss, 11); // CHECK: atomicrmw nand + us = __sync_fetch_and_nand (&us, 11); // CHECK: atomicrmw nand + si = __sync_fetch_and_nand (&si, 11); // CHECK: atomicrmw nand + ui = __sync_fetch_and_nand (&ui, 11); // CHECK: atomicrmw nand + sll = __sync_fetch_and_nand (&sll, 11); // CHECK: atomicrmw nand + ull = __sync_fetch_and_nand (&ull, 11); // CHECK: atomicrmw nand + sc = __sync_fetch_and_and (&sc, 11); // CHECK: atomicrmw and uc = __sync_fetch_and_and (&uc, 11); // CHECK: atomicrmw and ss = __sync_fetch_and_and (&ss, 11); // CHECK: atomicrmw and @@ -147,6 +165,31 @@ void test_op_and_fetch (void) sll = __sync_xor_and_fetch (&sll, uc); // CHECK: atomicrmw xor ull = __sync_xor_and_fetch (&ull, uc); // CHECK: atomicrmw xor + sc = __sync_nand_and_fetch (&sc, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + uc = __sync_nand_and_fetch (&uc, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + ss = __sync_nand_and_fetch (&ss, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + us = __sync_nand_and_fetch (&us, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + si = __sync_nand_and_fetch (&si, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + ui = __sync_nand_and_fetch (&ui, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + sll = __sync_nand_and_fetch (&sll, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + ull = __sync_nand_and_fetch (&ull, uc); // CHECK: atomicrmw nand + // CHECK: and + // CHECK: xor + sc = __sync_and_and_fetch (&sc, uc); // CHECK: atomicrmw and uc = __sync_and_and_fetch (&uc, uc); // CHECK: atomicrmw and ss = __sync_and_and_fetch (&ss, uc); // CHECK: atomicrmw and diff --git a/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/test/CodeGen/aarch64-fix-cortex-a53-835769.c new file mode 100644 index 0000000000000..7ad124012e6de --- /dev/null +++ b/test/CodeGen/aarch64-fix-cortex-a53-835769.c @@ -0,0 +1,27 @@ +// REQUIRES: aarch64-registered-target + +// RUN: %clang -O3 -target aarch64-linux-eabi %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-linux-eabi -mfix-cortex-a53-835769 %s -S -o- 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-linux-eabi -mno-fix-cortex-a53-835769 %s -S -o- 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s + +// RUN: %clang -O3 -target aarch64-android-eabi %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-android-eabi -mfix-cortex-a53-835769 %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-android-eabi -mno-fix-cortex-a53-835769 %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s + +typedef long int64_t; + +int64_t f_load_madd_64(int64_t a, int64_t b, int64_t *c) { + int64_t result = a+b*(*c); + return result; +} + +// CHECK: ldr +// CHECK-YES-NEXT: nop +// CHECK-NO-NEXT-NOT: nop +// CHECK-NEXT: madd diff --git a/test/CodeGen/aarch64-poly64.c b/test/CodeGen/aarch64-poly64.c index 290cc69bd43fb..a14162c053531 100644 --- a/test/CodeGen/aarch64-poly64.c +++ b/test/CodeGen/aarch64-poly64.c @@ -102,6 +102,18 @@ poly64x2_t test_vdupq_n_p64(poly64_t a) { // CHECK: dup {{v[0-9]+}}.2d, {{x[0-9]+}} } +poly64x1_t test_vmov_n_p64(poly64_t a) { + // CHECK-LABEL: test_vmov_n_p64 + return vmov_n_p64(a); + // CHECK: fmov {{d[0-9]+}}, {{x[0-9]+}} +} + +poly64x2_t test_vmovq_n_p64(poly64_t a) { + // CHECK-LABEL: test_vmovq_n_p64 + return vmovq_n_p64(a); + // CHECK: dup {{v[0-9]+}}.2d, {{x[0-9]+}} +} + poly64x1_t test_vdup_lane_p64(poly64x1_t vec) { // CHECK-LABEL: test_vdup_lane_p64 return vdup_lane_p64(vec, 0); diff --git a/test/CodeGen/aarch64-type-sizes.c b/test/CodeGen/aarch64-type-sizes.c index b331b6c3c32c6..3ff8c4f0d4d03 100644 --- a/test/CodeGen/aarch64-type-sizes.c +++ b/test/CodeGen/aarch64-type-sizes.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64_be-none-linux-gnu -emit-llvm -w -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s +// RUN: %clang_cc1 -triple aarch64_be-none-linux-gnu -emit-llvm -w -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s // char by definition has size 1 // CHECK-LE: target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/aarch64-varargs.c b/test/CodeGen/aarch64-varargs.c index f787afe37e51f..248f1c10cec47 100644 --- a/test/CodeGen/aarch64-varargs.c +++ b/test/CodeGen/aarch64-varargs.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LE %s -// RUN: %clang_cc1 -triple arm64_be-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s #include <stdarg.h> diff --git a/test/CodeGen/adc-builtins.c b/test/CodeGen/adc-builtins.c new file mode 100644 index 0000000000000..5577d22c60b37 --- /dev/null +++ b/test/CodeGen/adc-builtins.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffreestanding -emit-llvm -o - %s | FileCheck %s + +#include <x86intrin.h> + +unsigned char test_addcarry_u32(unsigned char __cf, unsigned int __x, + unsigned int __y, unsigned int *__p) { +// CHECK-LABEL: test_addcarry_u32 +// CHECK: call i8 @llvm.x86.addcarry.u32 + return _addcarry_u32(__cf, __x, __y, __p); +} + +unsigned char test_addcarry_u64(unsigned char __cf, unsigned long long __x, + unsigned long long __y, + unsigned long long *__p) { +// CHECK-LABEL: test_addcarry_u64 +// CHECK: call i8 @llvm.x86.addcarry.u64 + return _addcarry_u64(__cf, __x, __y, __p); +} + +unsigned char test_subborrow_u32(unsigned char __cf, unsigned int __x, + unsigned int __y, unsigned int *__p) { +// CHECK-LABEL: test_subborrow_u32 +// CHECK: call i8 @llvm.x86.subborrow.u32 + return _subborrow_u32(__cf, __x, __y, __p); +} + +unsigned char test_subborrow_u64(unsigned char __cf, unsigned long long __x, + unsigned long long __y, + unsigned long long *__p) { +// CHECK-LABEL: test_subborrow_u64 +// CHECK: call i8 @llvm.x86.subborrow.u64 + return _subborrow_u64(__cf, __x, __y, __p); +} diff --git a/test/CodeGen/address-safety-attr.cpp b/test/CodeGen/address-safety-attr.cpp index f94efd62c9c0f..031d013a9b503 100644 --- a/test/CodeGen/address-safety-attr.cpp +++ b/test/CodeGen/address-safety-attr.cpp @@ -1,9 +1,16 @@ -// 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 +int DefinedInDifferentFile(int *a); +// RUN: echo "int DefinedInDifferentFile(int *a) { return *a; }" > %t.extra-source.cpp +// RUN: echo "struct S { S(){} ~S(){} };" >> %t.extra-source.cpp +// RUN: echo "S glob_array[5];" >> %t.extra-source.cpp + +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp | FileCheck -check-prefix=WITHOUT %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address | FileCheck -check-prefix=ASAN %s + // 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 +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s + +// RUN: echo "src:%s" > %t.file.blacklist +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s // FIXME: %t.file.blacklist is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp" // REQUIRES: shell @@ -12,7 +19,25 @@ // when AddressSanitizer is enabled, unless no_sanitize_address attribute // is present. -// WITHOUT: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] +// Attributes for function defined in different source file: +// WITHOUT: DefinedInDifferentFile{{.*}} [[NOATTR:#[0-9]+]] +// BLFILE: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]] +// BLFUNC: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]] +// ASAN: DefinedInDifferentFile{{.*}} [[WITH:#[0-9]+]] + +// Check that functions generated for global in different source file are +// not blacklisted. +// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// WITHOUT: @__cxx_global_array_dtor{{.*}}[[NOATTR_NO_TF]] +// BLFILE: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] +// BLFILE: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]] +// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] +// BLFUNC: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]] +// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF:#[0-9]+]] +// ASAN: @__cxx_global_array_dtor{{.*}}[[WITH_NO_TF]] + + +// WITHOUT: NoAddressSafety1{{.*}}) [[NOATTR]] // BLFILE: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] // BLFUNC: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] // ASAN: NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]] @@ -29,8 +54,8 @@ int NoAddressSafety2(int *a) { return *a; } // WITHOUT: AddressSafetyOk{{.*}}) [[NOATTR]] // BLFILE: AddressSafetyOk{{.*}}) [[NOATTR]] -// BLFUNC: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]] -// ASAN: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]] +// BLFUNC: AddressSafetyOk{{.*}}) [[WITH]] +// ASAN: AddressSafetyOk{{.*}}) [[WITH]] int AddressSafetyOk(int *a) { return *a; } // WITHOUT: BlacklistedFunction{{.*}}) [[NOATTR]] @@ -39,6 +64,21 @@ int AddressSafetyOk(int *a) { return *a; } // ASAN: BlacklistedFunction{{.*}}) [[WITH]] int BlacklistedFunction(int *a) { return *a; } +#define GENERATE_FUNC(name) \ + int name(int *a) { return *a; } +// WITHOUT: GeneratedFunction{{.*}}) [[NOATTR]] +// BLFILE: GeneratedFunction{{.*}}) [[NOATTR]] +// BLFUNC: GeneratedFunction{{.*}}) [[WITH]] +// ASAN: GeneratedFunction{{.*}}) [[WITH]] +GENERATE_FUNC(GeneratedFunction) + +#define GENERATE_NAME(name) name##_generated +// WITHOUT: Function_generated{{.*}}) [[NOATTR]] +// BLFILE: Function_generated{{.*}}) [[NOATTR]] +// BLFUNC: Function_generated{{.*}}) [[WITH]] +// ASAN: Function_generated{{.*}}) [[WITH]] +int GENERATE_NAME(Function)(int *a) { return *a; } + // WITHOUT: TemplateAddressSafetyOk{{.*}}) [[NOATTR]] // BLFILE: TemplateAddressSafetyOk{{.*}}) [[NOATTR]] // BLFUNC: TemplateAddressSafetyOk{{.*}}) [[WITH]] @@ -60,21 +100,23 @@ int force_instance = TemplateAddressSafetyOk<42>() // Check that __cxx_global_var_init* get the sanitize_address attribute. int global1 = 0; int global2 = *(int*)((char*)&global1+1); -// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF:#[0-9]+]] +// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR_NO_TF]] // 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]+]] +// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH_NO_TF]] +// ASAN: @__cxx_global_var_init{{.*}}[[WITH_NO_TF]] // WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} } // WITHOUT: attributes [[NOATTR_NO_TF]] = { nounwind } -// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} } +// BLFILE: attributes [[WITH]] = { nounwind sanitize_address{{.*}} } +// BLFILE: attributes [[WITH_NO_TF]] = { nounwind sanitize_address } // BLFILE: attributes [[NOATTR_NO_TF]] = { nounwind } +// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} } -// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} } // BLFUNC: attributes [[WITH]] = { nounwind sanitize_address{{.*}} } // BLFUNC: attributes [[WITH_NO_TF]] = { nounwind sanitize_address } +// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} } -// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} } // ASAN: attributes [[WITH]] = { nounwind sanitize_address{{.*}} } // ASAN: attributes [[WITH_NO_TF]] = { nounwind sanitize_address } +// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} } diff --git a/test/CodeGen/address-sanitizer-and-array-cookie.cpp b/test/CodeGen/address-sanitizer-and-array-cookie.cpp new file mode 100644 index 0000000000000..ea89537789164 --- /dev/null +++ b/test/CodeGen/address-sanitizer-and-array-cookie.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - %s | FileCheck %s -check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address %s | FileCheck %s -check-prefix=ASAN + +typedef __typeof__(sizeof(0)) size_t; +namespace std { + struct nothrow_t {}; + std::nothrow_t nothrow; +} +void *operator new[](size_t, const std::nothrow_t &) throw(); +void *operator new[](size_t, char *); + +struct C { + int x; + ~C(); +}; + +C *CallNew() { + return new C[10]; +} +// PLAIN-LABEL: CallNew +// PLAIN-NOT: nosanitize +// PLAIN-NOT: __asan_poison_cxx_array_cookie +// ASAN-LABEL: CallNew +// ASAN: store{{.*}}nosanitize +// ASAN-NOT: nosanitize +// ASAN: call void @__asan_poison_cxx_array_cookie + +C *CallNewNoThrow() { + return new (std::nothrow) C[10]; +} +// PLAIN-LABEL: CallNewNoThrow +// PLAIN-NOT: nosanitize +// PLAIN-NOT: __asan_poison_cxx_array_cookie +// ASAN-LABEL: CallNewNoThrow +// ASAN: store{{.*}}nosanitize +// ASAN-NOT: nosanitize +// ASAN: call void @__asan_poison_cxx_array_cookie + +void CallDelete(C *c) { + delete [] c; +} + +// PLAIN-LABEL: CallDelete +// PLAIN-NOT: nosanitize +// ASAN-LABEL: CallDelete +// ASAN-NOT: nosanitize +// ASAN: call i64 @__asan_load_cxx_array_cookie +// ASAN-NOT: nosanitize + +char Buffer[20]; +C *CallPlacementNew() { + return new (Buffer) C[20]; +} +// ASAN-LABEL: CallPlacementNew +// ASAN-NOT: __asan_poison_cxx_array_cookie diff --git a/test/CodeGen/adx-builtins.c b/test/CodeGen/adx-builtins.c new file mode 100644 index 0000000000000..8738c5d177155 --- /dev/null +++ b/test/CodeGen/adx-builtins.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffreestanding -target-feature +adx -emit-llvm -o - %s | FileCheck %s + +#include <x86intrin.h> + +unsigned char test_addcarryx_u32(unsigned char __cf, unsigned int __x, + unsigned int __y, unsigned int *__p) { +// CHECK-LABEL: test_addcarryx_u32 +// CHECK: call i8 @llvm.x86.addcarryx.u32 + return _addcarryx_u32(__cf, __x, __y, __p); +} + +unsigned char test_addcarryx_u64(unsigned char __cf, unsigned long long __x, + unsigned long long __y, + unsigned long long *__p) { +// CHECK-LABEL: test_addcarryx_u64 +// CHECK: call i8 @llvm.x86.addcarryx.u64 + return _addcarryx_u64(__cf, __x, __y, __p); +} diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c index 98449d36edf60..b773cc8de938c 100644 --- a/test/CodeGen/alias.c +++ b/test/CodeGen/alias.c @@ -3,6 +3,8 @@ int g0; // CHECKBASIC: @g0 = common global i32 0 +__thread int TL_WITH_ALIAS; +// CHECKBASIC-DAG: @TL_WITH_ALIAS = thread_local global i32 0, align 4 static int bar1 = 42; // CHECKBASIC: @bar1 = internal global i32 42 @@ -10,11 +12,14 @@ extern int g1; extern int g1 __attribute((alias("g0"))); // CHECKBASIC-DAG: @g1 = alias i32* @g0 +extern __thread int __libc_errno __attribute__ ((alias ("TL_WITH_ALIAS"))); +// CHECKBASIC-DAG: @__libc_errno = thread_local alias i32* @TL_WITH_ALIAS + void f0(void) { } extern void f1(void); extern void f1(void) __attribute((alias("f0"))); // CHECKBASIC-DAG: @f1 = alias void ()* @f0 -// CHECKBASIC-DAG: @test8_foo = alias weak bitcast (void ()* @test8_bar to void (...)*) +// CHECKBASIC-DAG: @test8_foo = weak alias bitcast (void ()* @test8_bar to void (...)*) // CHECKBASIC-DAG: @test8_zed = alias bitcast (void ()* @test8_bar to void (...)*) // CHECKBASIC-DAG: @test9_zed = alias void ()* @test9_bar // CHECKBASIC: define void @f0() [[NUW:#[0-9]+]] { diff --git a/test/CodeGen/align_value.cpp b/test/CodeGen/align_value.cpp new file mode 100644 index 0000000000000..6d0e48128cb2f --- /dev/null +++ b/test/CodeGen/align_value.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +typedef double * __attribute__((align_value(64))) aligned_double; + +void foo(aligned_double x, double * y __attribute__((align_value(32))), + double & z __attribute__((align_value(128)))) { }; +// CHECK: define void @_Z3fooPdS_Rd(double* align 64 %x, double* align 32 %y, double* dereferenceable(8) align 128 %z) + +struct ad_struct { + aligned_double a; +}; + +double *foo(ad_struct& x) { +// CHECK-LABEL: @_Z3fooR9ad_struct + +// CHECK: [[PTRINT1:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR1:%.+]] = and i64 [[PTRINT1]], 63 +// CHECK: [[MASKCOND1:%.+]] = icmp eq i64 [[MASKEDPTR1]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND1]]) + return x.a; +} + +double *goo(ad_struct *x) { +// CHECK-LABEL: @_Z3gooP9ad_struct + +// CHECK: [[PTRINT2:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR2:%.+]] = and i64 [[PTRINT2]], 63 +// CHECK: [[MASKCOND2:%.+]] = icmp eq i64 [[MASKEDPTR2]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND2]]) + return x->a; +} + +double *bar(aligned_double *x) { +// CHECK-LABEL: @_Z3barPPd + +// CHECK: [[PTRINT3:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR3:%.+]] = and i64 [[PTRINT3]], 63 +// CHECK: [[MASKCOND3:%.+]] = icmp eq i64 [[MASKEDPTR3]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND3]]) + return *x; +} + +double *car(aligned_double &x) { +// CHECK-LABEL: @_Z3carRPd + +// CHECK: [[PTRINT4:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR4:%.+]] = and i64 [[PTRINT4]], 63 +// CHECK: [[MASKCOND4:%.+]] = icmp eq i64 [[MASKEDPTR4]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND4]]) + return x; +} + +double *dar(aligned_double *x) { +// CHECK-LABEL: @_Z3darPPd + +// CHECK: [[PTRINT5:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR5:%.+]] = and i64 [[PTRINT5]], 63 +// CHECK: [[MASKCOND5:%.+]] = icmp eq i64 [[MASKEDPTR5]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND5]]) + return x[5]; +} + +aligned_double eep(); +double *ret() { +// CHECK-LABEL: @_Z3retv + +// CHECK: [[PTRINT6:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR6:%.+]] = and i64 [[PTRINT6]], 63 +// CHECK: [[MASKCOND6:%.+]] = icmp eq i64 [[MASKEDPTR6]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND6]]) + return eep(); +} + +double **no1(aligned_double *x) { +// CHECK-LABEL: @_Z3no1PPd + return x; +// CHECK-NOT: call void @llvm.assume +} + +double *&no2(aligned_double &x) { +// CHECK-LABEL: @_Z3no2RPd + return x; +// CHECK-NOT: call void @llvm.assume +} + +double **no3(aligned_double &x) { +// CHECK-LABEL: @_Z3no3RPd + return &x; +// CHECK-NOT: call void @llvm.assume +} + +double no3(aligned_double x) { +// CHECK-LABEL: @_Z3no3Pd + return *x; +// CHECK-NOT: call void @llvm.assume +} + +double *no4(aligned_double x) { +// CHECK-LABEL: @_Z3no4Pd + return x; +// CHECK-NOT: call void @llvm.assume +} + diff --git a/test/CodeGen/arm-aapcs-vfp.c b/test/CodeGen/arm-aapcs-vfp.c index eea6ab2f154d1..7ef7c4e52edb6 100644 --- a/test/CodeGen/arm-aapcs-vfp.c +++ b/test/CodeGen/arm-aapcs-vfp.c @@ -1,4 +1,5 @@ // REQUIRES: arm-registered-target +// REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple thumbv7-apple-darwin9 \ // RUN: -target-abi aapcs \ // RUN: -target-cpu cortex-a8 \ @@ -28,7 +29,7 @@ struct homogeneous_struct { float f4; }; // CHECK: define arm_aapcs_vfpcc %struct.homogeneous_struct @test_struct(%struct.homogeneous_struct %{{.*}}) -// CHECK64: define %struct.homogeneous_struct @test_struct(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) +// CHECK64: define %struct.homogeneous_struct @test_struct([4 x float] %{{.*}}) extern struct homogeneous_struct struct_callee(struct homogeneous_struct); struct homogeneous_struct test_struct(struct homogeneous_struct arg) { return struct_callee(arg); @@ -43,7 +44,7 @@ struct nested_array { double d[4]; }; // CHECK: define arm_aapcs_vfpcc void @test_array(%struct.nested_array %{{.*}}) -// CHECK64: define void @test_array(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}) +// CHECK64: define void @test_array([4 x double] %{{.*}}) extern void array_callee(struct nested_array); void test_array(struct nested_array arg) { array_callee(arg); @@ -51,7 +52,7 @@ void test_array(struct nested_array arg) { extern void complex_callee(__complex__ double); // CHECK: define arm_aapcs_vfpcc void @test_complex({ double, double } %{{.*}}) -// CHECK64: define void @test_complex(double %{{.*}}, double %{{.*}}) +// CHECK64: define void @test_complex([2 x double] %cd.coerce) void test_complex(__complex__ double cd) { complex_callee(cd); } @@ -72,7 +73,7 @@ struct big_struct { float f3; float f4; }; -// CHECK: define arm_aapcs_vfpcc void @test_big({ [5 x i32] } %{{.*}}) +// CHECK: define arm_aapcs_vfpcc void @test_big([5 x i32] %{{.*}}) // CHECK64: define void @test_big(%struct.big_struct* %{{.*}}) // CHECK64: call void @llvm.memcpy // CHECK64: call void @big_callee(%struct.big_struct* @@ -88,7 +89,7 @@ struct heterogeneous_struct { float f1; int i2; }; -// CHECK: define arm_aapcs_vfpcc void @test_hetero({ [2 x i32] } %{{.*}}) +// CHECK: define arm_aapcs_vfpcc void @test_hetero([2 x i32] %{{.*}}) // CHECK64: define void @test_hetero(i64 %{{.*}}) extern void hetero_callee(struct heterogeneous_struct); void test_hetero(struct heterogeneous_struct arg) { @@ -97,7 +98,7 @@ void test_hetero(struct heterogeneous_struct arg) { // Neon multi-vector types are homogeneous aggregates. // CHECK: define arm_aapcs_vfpcc <16 x i8> @f0(%struct.int8x16x4_t %{{.*}}) -// CHECK64: define <16 x i8> @f0(<16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}) +// CHECK64: define <16 x i8> @f0([4 x <16 x i8>] %{{.*}}) int8x16_t f0(int8x16x4_t v4) { return vaddq_s8(v4.val[0], v4.val[3]); } @@ -111,7 +112,7 @@ struct neon_struct { int16x4_t v4; }; // CHECK: define arm_aapcs_vfpcc void @test_neon(%struct.neon_struct %{{.*}}) -// CHECK64: define void @test_neon(<8 x i8> %{{.*}}, <8 x i8> %{{.*}}, <2 x i32> %{{.*}}, <4 x i16> %{{.*}}) +// CHECK64: define void @test_neon([4 x <8 x i8>] %{{.*}}) extern void neon_callee(struct neon_struct); void test_neon(struct neon_struct arg) { neon_callee(arg); @@ -125,25 +126,25 @@ typedef struct { long long x; int y; } struct_long_long_int; // CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_1(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i64 %k, i32 %l) void test_vfp_stack_gpr_split_1(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, long long k, int l) {} -// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], { [2 x i64] } %k.coerce) +// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], [2 x i64] %k.coerce) void test_vfp_stack_gpr_split_2(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_long_long_int k) {} -// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [3 x i32], { [2 x i64] } %k.coerce) +// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(%struct.struct_long_long_int* noalias sret %agg.result, double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, [3 x i32], [2 x i64] %k.coerce) struct_long_long_int test_vfp_stack_gpr_split_3(double a, double b, double c, double d, double e, double f, double g, double h, double i, struct_long_long_int k) {} typedef struct { int a; int b:4; int c; } struct_int_bitfield_int; -// CHECK: define arm_aapcs_vfpcc void @test_test_vfp_stack_gpr_split_bitfield(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i32 %k, [2 x i32], { [3 x i32] } %l.coerce) +// CHECK: define arm_aapcs_vfpcc void @test_test_vfp_stack_gpr_split_bitfield(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, i32 %k, [2 x i32], [3 x i32] %l.coerce) void test_test_vfp_stack_gpr_split_bitfield(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, int k, struct_int_bitfield_int l) {} // Note: this struct requires internal padding typedef struct { int x; long long y; } struct_int_long_long; -// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_4(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], { [2 x i64] } %k.coerce) +// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_4(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, i32 %j, [3 x i32], [2 x i64] %k.coerce) void test_vfp_stack_gpr_split_4(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_int_long_long k) {} // This very large struct (passed byval) uses up the GPRs, so no padding is needed typedef struct { int x[17]; } struct_seventeen_ints; typedef struct { int x[4]; } struct_four_ints; -// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_5(%struct.struct_seventeen_ints* byval align 4 %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, double %j, { [4 x i32] } %k.coerce) +// CHECK: define arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_5(%struct.struct_seventeen_ints* byval align 4 %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, double %i, double %j, [4 x i32] %k.coerce) void test_vfp_stack_gpr_split_5(struct_seventeen_ints a, double b, double c, double d, double e, double f, double g, double h, double i, double j, struct_four_ints k) {} // Here, parameter k would need padding to prevent it from being split, but it diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c index 2c5df91c58ac4..e4a10fd9e27b9 100644 --- a/test/CodeGen/arm-arguments.c +++ b/test/CodeGen/arm-arguments.c @@ -183,14 +183,9 @@ void f33(struct s33 s) { } struct s34 { char c; }; void f34(struct s34 s); void g34(struct s34 *s) { f34(*s); } -// APCS-GNU: @g34(%struct.s34* %s) -// APCS-GNU: %[[a:.*]] = alloca { [1 x i32] } -// APCS-GNU: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0 -// APCS-GNU: load [1 x i32]* %[[gep]] // AAPCS: @g34(%struct.s34* %s) -// AAPCS: %[[a:.*]] = alloca { [1 x i32] } -// AAPCS: %[[gep:.*]] = getelementptr { [1 x i32] }* %[[a]], i32 0, i32 0 -// AAPCS: load [1 x i32]* %[[gep]] +// AAPCS: %[[a:.*]] = alloca [1 x i32] +// AAPCS: load [1 x i32]* %[[a]] // rdar://12596507 struct s35 diff --git a/test/CodeGen/arm-homogenous.c b/test/CodeGen/arm-homogenous.c index d1b489793f988..3426d995caef8 100644 --- a/test/CodeGen/arm-homogenous.c +++ b/test/CodeGen/arm-homogenous.c @@ -5,7 +5,7 @@ // RUN: -ffreestanding -emit-llvm -w -o - %s | FileCheck -check-prefix=CHECK64 %s // RUN: %clang_cc1 -triple arm64-linux-gnu -ffreestanding -emit-llvm -w -o - %s \ -// RUN: | FileCheck --check-prefix=CHECK64-AAPCS %s +// RUN: | FileCheck --check-prefix=CHECK64 %s typedef long long int64_t; typedef unsigned int uint32_t; @@ -22,7 +22,7 @@ extern union_with_first_floats returns_union_with_first_floats(void); void test_union_with_first_floats(void) { takes_union_with_first_floats(g_u_f); } -// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats({ [4 x i32] }) +// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_first_floats([4 x i32]) void test_return_union_with_first_floats(void) { g_u_f = returns_union_with_first_floats(); @@ -42,7 +42,7 @@ extern union_with_non_first_floats returns_union_with_non_first_floats(void); void test_union_with_non_first_floats(void) { takes_union_with_non_first_floats(g_u_nf_f); } -// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats({ [4 x i32] }) +// CHECK: declare arm_aapcs_vfpcc void @takes_union_with_non_first_floats([4 x i32]) void test_return_union_with_non_first_floats(void) { g_u_nf_f = returns_union_with_non_first_floats(); @@ -62,7 +62,7 @@ extern struct_with_union_with_first_floats returns_struct_with_union_with_first_ void test_struct_with_union_with_first_floats(void) { takes_struct_with_union_with_first_floats(g_s_f); } -// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats({ [5 x i32] }) +// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_first_floats([5 x i32]) void test_return_struct_with_union_with_first_floats(void) { g_s_f = returns_struct_with_union_with_first_floats(); @@ -82,7 +82,7 @@ extern struct_with_union_with_non_first_floats returns_struct_with_union_with_no void test_struct_with_union_with_non_first_floats(void) { takes_struct_with_union_with_non_first_floats(g_s_nf_f); } -// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats({ [5 x i32] }) +// CHECK: declare arm_aapcs_vfpcc void @takes_struct_with_union_with_non_first_floats([5 x i32]) void test_return_struct_with_union_with_non_first_floats(void) { g_s_nf_f = returns_struct_with_union_with_non_first_floats(); @@ -176,9 +176,7 @@ void test_struct_of_four_doubles(void) { // CHECK: test_struct_of_four_doubles // CHECK: call arm_aapcs_vfpcc void @takes_struct_of_four_doubles(double {{.*}}, %struct.struct_of_four_doubles {{.*}}, %struct.struct_of_four_doubles {{.*}}, double {{.*}}) // CHECK64: test_struct_of_four_doubles -// CHECK64: call void @takes_struct_of_four_doubles(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [3 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}) -// CHECK64-AAPCS: test_struct_of_four_doubles -// CHECK64-AAPCS: call void @takes_struct_of_four_doubles(double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}, [3 x float] undef, double {{.*}}, double {{.*}}, double {{.*}}, double {{.*}}) +// CHECK64: call void @takes_struct_of_four_doubles(double {{.*}}, [4 x double] {{.*}}, [4 x double] {{.*}}, double {{.*}}) takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0); } @@ -186,7 +184,7 @@ extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubl void test_struct_of_four_doubles_variadic(void) { // CHECK: test_struct_of_four_doubles_variadic -// CHECK: call arm_aapcs_vfpcc void (double, { [4 x i64] }, { [4 x i64] }, double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, { [4 x i64] } {{.*}}, { [4 x i64] } {{.*}}, double {{.*}}) +// CHECK: call arm_aapcs_vfpcc void (double, [4 x i64], [4 x i64], double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, [4 x i64] {{.*}}, [4 x i64] {{.*}}, double {{.*}}) takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0); } @@ -212,9 +210,7 @@ void test_struct_of_vecs(void) { // CHECK: test_struct_of_vecs // CHECK: call arm_aapcs_vfpcc void @takes_struct_of_vecs(double {{.*}}, %struct.struct_of_vecs {{.*}}, %struct.struct_of_vecs {{.*}}, double {{.*}}) // CHECK64: test_struct_of_vecs -// CHECK64: call void @takes_struct_of_vecs(double {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, [3 x float] undef, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, double {{.*}}) -// CHECK64-AAPCS: test_struct_of_vecs -// CHECK64-AAPCS: call void @takes_struct_of_vecs(double {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, [3 x float] undef, <8 x i8> {{.*}}, <4 x i16> {{.*}}, <8 x i8> {{.*}}, <4 x i16> {{.*}}, double {{.*}}) +// CHECK64: call void @takes_struct_of_vecs(double {{.*}}, [4 x <8 x i8>] {{.*}}, [4 x <8 x i8>] {{.*}}, double {{.*}}) takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0); } diff --git a/test/CodeGen/arm-metadata.c b/test/CodeGen/arm-metadata.c index 1cd9880f1b53a..1f7756cc8d484 100644 --- a/test/CodeGen/arm-metadata.c +++ b/test/CodeGen/arm-metadata.c @@ -2,11 +2,11 @@ // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-enums | FileCheck -check-prefix=SHORT-ENUM %s // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-wchar | FileCheck -check-prefix=SHORT-WCHAR %s -// DEFAULT: !{{[0-9]+}} = metadata !{i32 1, metadata !"wchar_size", i32 4} -// DEFAULT: !{{[0-9]+}} = metadata !{i32 1, metadata !"min_enum_size", i32 4} +// DEFAULT: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} +// DEFAULT: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 4} -// SHORT-WCHAR: !{{[0-9]+}} = metadata !{i32 1, metadata !"wchar_size", i32 2} -// SHORT-WCHAR: !{{[0-9]+}} = metadata !{i32 1, metadata !"min_enum_size", i32 4} +// SHORT-WCHAR: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 2} +// SHORT-WCHAR: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 4} -// SHORT_ENUM: !{{[0-9]+}} = metadata !{i32 1, metadata !"wchar_size", i32 4} -// SHORT-ENUM: !{{[0-9]+}} = metadata !{i32 1, metadata !"min_enum_size", i32 1} +// SHORT_ENUM: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} +// SHORT-ENUM: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 1} diff --git a/test/CodeGen/arm-neon-directed-rounding.c b/test/CodeGen/arm-neon-directed-rounding.c new file mode 100644 index 0000000000000..84029318865ce --- /dev/null +++ b/test/CodeGen/arm-neon-directed-rounding.c @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 -ffreestanding -O1 -emit-llvm %s -o - | FileCheck %s + +#include <arm_neon.h> + +float32x2_t test_vrnda_f32(float32x2_t a) { + // CHECK-LABEL: test_vrnda_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> %a) + return vrnda_f32(a); +} + +float32x4_t test_vrndaq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndaq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> %a) + return vrndaq_f32(a); +} + +float32x2_t test_vrndm_f32(float32x2_t a) { + // CHECK-LABEL: test_vrndm_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> %a) + return vrndm_f32(a); +} + +float32x4_t test_vrndmq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndmq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> %a) + return vrndmq_f32(a); +} + +float32x2_t test_vrndn_f32(float32x2_t a) { + // CHECK-LABEL: test_vrndn_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> %a) + return vrndn_f32(a); +} + +float32x4_t test_vrndnq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndnq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> %a) + return vrndnq_f32(a); +} + +float32x2_t test_vrndp_f32(float32x2_t a) { + // CHECK-LABEL: test_vrndp_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> %a) + return vrndp_f32(a); +} + +float32x4_t test_vrndpq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndpq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> %a) + return vrndpq_f32(a); +} + +float32x2_t test_vrndx_f32(float32x2_t a) { + // CHECK-LABEL: test_vrndx_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> %a) + return vrndx_f32(a); +} + +float32x4_t test_vrndxq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndxq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> %a) + return vrndxq_f32(a); +} + +float32x2_t test_vrnd_f32(float32x2_t a) { + // CHECK-LABEL: test_vrnd_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> %a) + return vrnd_f32(a); +} + +float32x4_t test_vrndq_f32(float32x4_t a) { + // CHECK-LABEL: test_vrndq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> %a) + return vrndq_f32(a); +} diff --git a/test/CodeGen/arm-neon-numeric-maxmin.c b/test/CodeGen/arm-neon-numeric-maxmin.c new file mode 100644 index 0000000000000..615a854b5e213 --- /dev/null +++ b/test/CodeGen/arm-neon-numeric-maxmin.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a57 -ffreestanding -O1 -emit-llvm %s -o - | FileCheck %s + +#include <arm_neon.h> + +float32x2_t test_vmaxnm_f32(float32x2_t a, float32x2_t b) { + // CHECK-LABEL: test_vmaxnm_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vmaxnm.v2f32(<2 x float> %a, <2 x float> %b) + return vmaxnm_f32(a, b); +} + +float32x4_t test_vmaxnmq_f32(float32x4_t a, float32x4_t b) { + // CHECK-LABEL: test_vmaxnmq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vmaxnm.v4f32(<4 x float> %a, <4 x float> %b) + return vmaxnmq_f32(a, b); +} + +float32x2_t test_vminnm_f32(float32x2_t a, float32x2_t b) { + // CHECK-LABEL: test_vminnm_f32 + // CHECK: call <2 x float> @llvm.arm.neon.vminnm.v2f32(<2 x float> %a, <2 x float> %b) + return vminnm_f32(a, b); +} + +float32x4_t test_vminnmq_f32(float32x4_t a, float32x4_t b) { + // CHECK-LABEL: test_vminnmq_f32 + // CHECK: call <4 x float> @llvm.arm.neon.vminnm.v4f32(<4 x float> %a, <4 x float> %b) + return vminnmq_f32(a, b); +} diff --git a/test/CodeGen/arm64-aapcs-arguments.c b/test/CodeGen/arm64-aapcs-arguments.c index b430630b0711b..ab302d407041b 100644 --- a/test/CodeGen/arm64-aapcs-arguments.c +++ b/test/CodeGen/arm64-aapcs-arguments.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -target-abi aapcs -ffreestanding -emit-llvm -w -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -target-abi aapcs -ffreestanding -fallow-half-arguments-and-returns -emit-llvm -w -o - %s | FileCheck %s // AAPCS clause C.8 says: If the argument has an alignment of 16 then the NGRN // is rounded up to the next even number. @@ -17,7 +17,7 @@ void test2(int x0, Small x2_x3, int x4, Small x6_x7, int sp, Small sp16) { // stack in order to avoid holes. Make sure we get all of them, and not just the // first: -// CHECK: void @test3(float %s0_s3.0, float %s0_s3.1, float %s0_s3.2, float %s0_s3.3, float %s4, [3 x float], [2 x double] %sp.coerce, [2 x double] %sp16.coerce) +// CHECK: void @test3([4 x float] %s0_s3.coerce, float %s4, [4 x float] %sp.coerce, [4 x float] %sp16.coerce) typedef struct { float arr[4]; } HFA; void test3(HFA s0_s3, float s4, HFA sp, HFA sp16) { } @@ -28,7 +28,7 @@ void test3(HFA s0_s3, float s4, HFA sp, HFA sp16) { // fp128] or something, but leaving them as-is retains more information for // users to debug. -// CHECK: void @test4(<16 x i8> %v0_v2.0, <16 x i8> %v0_v2.1, <16 x i8> %v0_v2.2, <16 x i8> %v3_v5.0, <16 x i8> %v3_v5.1, <16 x i8> %v3_v5.2, [2 x float], <16 x i8> %sp.0, <16 x i8> %sp.1, <16 x i8> %sp.2, double %sp48, <16 x i8> %sp64.0, <16 x i8> %sp64.1, <16 x i8> %sp64.2) +// CHECK: void @test4([3 x <16 x i8>] %v0_v2.coerce, [3 x <16 x i8>] %v3_v5.coerce, [3 x <16 x i8>] %sp.coerce, double %sp48, [3 x <16 x i8>] %sp64.coerce) typedef __attribute__((neon_vector_type(16))) signed char int8x16_t; typedef struct { int8x16_t arr[3]; } BigHFA; void test4(BigHFA v0_v2, BigHFA v3_v5, BigHFA sp, double sp48, BigHFA sp64) { @@ -40,3 +40,12 @@ void test4(BigHFA v0_v2, BigHFA v3_v5, BigHFA sp, double sp48, BigHFA sp64) { // CHECK: define i8 @test5(i8 %a, i16 %b) unsigned char test5(unsigned char a, signed short b) { } + +// __fp16 can be used as a function argument or return type (ACLE 2.0) +// CHECK: define half @test_half(half %{{.*}}) +__fp16 test_half(__fp16 A) { } + +// __fp16 is a base type for homogeneous floating-point aggregates for AArch64 (but not 32-bit ARM). +// CHECK: define %struct.HFA_half @test_half_hfa([4 x half] %{{.*}}) +struct HFA_half { __fp16 a[4]; }; +struct HFA_half test_half_hfa(struct HFA_half A) { } diff --git a/test/CodeGen/arm64-arguments.c b/test/CodeGen/arm64-arguments.c index b2de08dbe68c5..ae1ff98800ac4 100644 --- a/test/CodeGen/arm64-arguments.c +++ b/test/CodeGen/arm64-arguments.c @@ -123,8 +123,7 @@ void f31(struct s31 s) { } struct s32 { double x; }; void f32(struct s32 s) { } -// Expand Homogeneous Aggregate. -// CHECK: @f32(double %{{.*}}) +// CHECK: @f32([1 x double] %{{.*}}) // A composite type larger than 16 bytes should be passed indirectly. struct s33 { char buf[32*32]; }; @@ -197,7 +196,7 @@ typedef struct s35 s35_with_align; typedef __attribute__((neon_vector_type(4))) float float32x4_t; float32x4_t f35(int i, s35_with_align s1, s35_with_align s2) { -// CHECK: define <4 x float> @f35(i32 %i, float %s1.0, float %s1.1, float %s1.2, float %s1.3, float %s2.0, float %s2.1, float %s2.2, float %s2.3) +// CHECK: define <4 x float> @f35(i32 %i, [4 x float] %s1.coerce, [4 x float] %s2.coerce) // CHECK: %s1 = alloca %struct.s35, align 16 // CHECK: %s2 = alloca %struct.s35, align 16 // CHECK: %[[a:.*]] = bitcast %struct.s35* %s1 to <4 x float>* @@ -598,24 +597,24 @@ int caller43_stack() { __attribute__ ((noinline)) int f40_split(int i, int i2, int i3, int i4, int i5, int i6, int i7, s40_no_align s1, s40_no_align s2) { -// CHECK: define i32 @f40_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, [1 x i32], [2 x i64] %s1.coerce, [2 x i64] %s2.coerce) +// CHECK: define i32 @f40_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, [2 x i64] %s1.coerce, [2 x i64] %s2.coerce) return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + s1.s + s2.s; } int caller40_split() { // CHECK: define i32 @caller40_split() -// CHECK: call i32 @f40_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, [1 x i32] undef, [2 x i64] %{{.*}} [2 x i64] %{{.*}}) +// CHECK: call i32 @f40_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, [2 x i64] %{{.*}} [2 x i64] %{{.*}}) return f40_split(1, 2, 3, 4, 5, 6, 7, g40, g40_2); } __attribute__ ((noinline)) int f41_split(int i, int i2, int i3, int i4, int i5, int i6, int i7, s41_with_align s1, s41_with_align s2) { -// CHECK: define i32 @f41_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, [1 x i32], i128 %s1.coerce, i128 %s2.coerce) +// CHECK: define i32 @f41_split(i32 %i, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i128 %s1.coerce, i128 %s2.coerce) return s1.i + s2.i + i + i2 + i3 + i4 + i5 + i6 + i7 + s1.s + s2.s; } int caller41_split() { // CHECK: define i32 @caller41_split() -// CHECK: call i32 @f41_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, [1 x i32] undef, i128 %{{.*}}, i128 %{{.*}}) +// CHECK: call i32 @f41_split(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i128 %{{.*}}, i128 %{{.*}}) return f41_split(1, 2, 3, 4, 5, 6, 7, g41, g41_2); } @@ -642,7 +641,7 @@ float test_hfa(int n, ...) { float test_hfa_call(struct HFA *a) { // CHECK-LABEL: define float @test_hfa_call(%struct.HFA* %a) -// CHECK: call float (i32, ...)* @test_hfa(i32 1, [2 x double] {{.*}}) +// CHECK: call float (i32, ...)* @test_hfa(i32 1, [4 x float] {{.*}}) test_hfa(1, *a); } diff --git a/test/CodeGen/arm64-be-bitfield.c b/test/CodeGen/arm64-be-bitfield.c index f563596bdda34..b8d497c5580de 100644 --- a/test/CodeGen/arm64-be-bitfield.c +++ b/test/CodeGen/arm64-be-bitfield.c @@ -1,9 +1,15 @@ -// RUN: %clang_cc1 -triple arm64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s +// REQUIRES: aarch64-registered-target +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck --check-prefix IR %s +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -S -O1 -o - %s | FileCheck --check-prefix ARM %s struct bt3 { signed b2:10; signed b3:10; } b16; -// The correct right-shift amount is 40 bits for big endian. +// Get the high 32-bits and then shift appropriately for big-endian. signed callee_b0f(struct bt3 bp11) { -// CHECK: = lshr i64 %{{.*}}, 40 +// IR: callee_b0f(i64 [[ARG:%.*]]) +// IR: store i64 [[ARG]], i64* [[PTR:%.*]] +// IR: [[BITCAST:%.*]] = bitcast i64* [[PTR]] to i8* +// IR: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* [[BITCAST]], i64 4 +// ARM: asr x0, x0, #54 return bp11.b2; } diff --git a/test/CodeGen/arm64-be-hfa-vararg.c b/test/CodeGen/arm64-be-hfa-vararg.c index c9d650794d6e0..537aab52b3b5d 100644 --- a/test/CodeGen/arm64-be-hfa-vararg.c +++ b/test/CodeGen/arm64-be-hfa-vararg.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s #include <stdarg.h> diff --git a/test/CodeGen/arm64-lanes.c b/test/CodeGen/arm64-lanes.c index 8ab2bd4c66904..4e80df9d6c521 100644 --- a/test/CodeGen/arm64-lanes.c +++ b/test/CodeGen/arm64-lanes.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -O3 -triple arm64-apple-ios7 -target-feature +neon -ffreestanding -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -O3 -triple arm64_be-linux-gnu -target-feature +neon -ffreestanding -emit-llvm -o - %s | FileCheck %s --check-prefix CHECK-BE +// RUN: %clang_cc1 -O3 -triple aarch64_be-linux-gnu -target-feature +neon -ffreestanding -emit-llvm -o - %s | FileCheck %s --check-prefix CHECK-BE #include <arm_neon.h> diff --git a/test/CodeGen/arm_acle.c b/test/CodeGen/arm_acle.c index 8550c58b3677a..5b024506a50e4 100644 --- a/test/CodeGen/arm_acle.c +++ b/test/CodeGen/arm_acle.c @@ -62,6 +62,53 @@ void test_sevl(void) { __sevl(); } +#if __ARM_32BIT_STATE +// AArch32-LABEL: test_dbg +// AArch32: call void @llvm.arm.dbg(i32 0) +void test_dbg(void) { + __dbg(0); +} +#endif + +/* 8.5 Swap */ +// ARM-LABEL: test_swp +// AArch32: call i32 @llvm.arm.ldrex +// AArch32: call i32 @llvm.arm.strex +// AArch64: call i64 @llvm.aarch64.ldxr +// AArch64: call i32 @llvm.aarch64.stxr +uint32_t test_swp(uint32_t x, volatile void *p) { + __swp(x, p); +} + +/* 8.6 Memory prefetch intrinsics */ +/* 8.6.1 Data prefetch */ +// ARM-LABEL: test_pld +// ARM: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 1) +void test_pld() { + __pld(0); +} + +// ARM-LABEL: test_pldx +// AArch32: call void @llvm.prefetch(i8* null, i32 1, i32 3, i32 1) +// AArch64: call void @llvm.prefetch(i8* null, i32 1, i32 1, i32 1) +void test_pldx() { + __pldx(1, 2, 0, 0); +} + +/* 8.6.2 Instruction prefetch */ +// ARM-LABEL: test_pli +// ARM: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) +void test_pli() { + __pli(0); +} + +// ARM-LABEL: test_plix +// AArch32: call void @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) +// AArch64: call void @llvm.prefetch(i8* null, i32 0, i32 1, i32 0) +void test_plix() { + __plix(2, 0, 0); +} + /* 8.7 NOP */ // ARM-LABEL: test_nop // AArch32: call void @llvm.arm.hint(i32 0) @@ -72,23 +119,31 @@ void test_nop(void) { /* 9 DATA-PROCESSING INTRINSICS */ /* 9.2 Miscellaneous data-processing intrinsics */ -// ARM-LABEL: test_rev -// ARM: call i32 @llvm.bswap.i32(i32 %t) -uint32_t test_rev(uint32_t t) { - return __rev(t); +// ARM-LABEL: test_ror +// ARM: lshr +// ARM: sub +// ARM: shl +// ARM: or +uint32_t test_ror(uint32_t x, uint32_t y) { + return __ror(x, y); } -// ARM-LABEL: test_revl -// AArch32: call i32 @llvm.bswap.i32(i32 %t) -// AArch64: call i64 @llvm.bswap.i64(i64 %t) -long test_revl(long t) { - return __revl(t); +// ARM-LABEL: test_rorl +// ARM: lshr +// ARM: sub +// ARM: shl +// ARM: or +unsigned long test_rorl(unsigned long x, uint32_t y) { + return __rorl(x, y); } -// ARM-LABEL: test_revll -// ARM: call i64 @llvm.bswap.i64(i64 %t) -uint64_t test_revll(uint64_t t) { - return __revll(t); +// ARM-LABEL: test_rorll +// ARM: lshr +// ARM: sub +// ARM: shl +// ARM: or +uint64_t test_rorll(uint64_t x, uint32_t y) { + return __rorll(x, y); } // ARM-LABEL: test_clz @@ -110,6 +165,80 @@ uint64_t test_clzll(uint64_t t) { return __clzll(t); } +// ARM-LABEL: test_rev +// ARM: call i32 @llvm.bswap.i32(i32 %t) +uint32_t test_rev(uint32_t t) { + return __rev(t); +} + +// ARM-LABEL: test_revl +// AArch32: call i32 @llvm.bswap.i32(i32 %t) +// AArch64: call i64 @llvm.bswap.i64(i64 %t) +long test_revl(long t) { + return __revl(t); +} + +// ARM-LABEL: test_revll +// ARM: call i64 @llvm.bswap.i64(i64 %t) +uint64_t test_revll(uint64_t t) { + return __revll(t); +} + +// ARM-LABEL: test_rev16 +// ARM: llvm.bswap +// ARM: lshr +// ARM: shl +// ARM: or +uint32_t test_rev16(uint32_t t) { + return __rev16(t); +} + +// ARM-LABEL: test_rev16l +// ARM: llvm.bswap +// ARM: lshr +// ARM: shl +// ARM: or +long test_rev16l(long t) { + return __rev16l(t); +} + +// ARM-LABEL: test_rev16ll +// ARM: llvm.bswap +// ARM: lshr +// ARM: shl +// ARM: or +uint64_t test_rev16ll(uint64_t t) { + return __rev16ll(t); +} + +// ARM-LABEL: test_revsh +// ARM: call i16 @llvm.bswap.i16(i16 %t) +int16_t test_revsh(int16_t t) { + return __revsh(t); +} + +// ARM-LABEL: test_rbit +// AArch32: call i32 @llvm.arm.rbit +// AArch64: call i32 @llvm.aarch64.rbit.i32 +uint32_t test_rbit(uint32_t t) { + return __rbit(t); +} + +// ARM-LABEL: test_rbitl +// AArch32: call i32 @llvm.arm.rbit +// AArch64: call i64 @llvm.aarch64.rbit.i64 +long test_rbitl(long t) { + return __rbitl(t); +} + +// ARM-LABEL: test_rbitll +// AArch32: call i32 @llvm.arm.rbit +// AArch32: call i32 @llvm.arm.rbit +// AArch64: call i64 @llvm.aarch64.rbit.i64 +uint64_t test_rbitll(uint64_t t) { + return __rbitll(t); +} + /* 9.4 Saturating intrinsics */ #ifdef __ARM_32BIT_STATE diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c index a084d8b2c84c7..756e3b43fc548 100644 --- a/test/CodeGen/arm_neon_intrinsics.c +++ b/test/CodeGen/arm_neon_intrinsics.c @@ -1474,79 +1474,109 @@ poly8x16_t test_vcntq_p8(poly8x16_t a) { // CHECK-LABEL: test_vcombine_s8 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} int8x16_t test_vcombine_s8(int8x8_t a, int8x8_t b) { return vcombine_s8(a, b); } // CHECK-LABEL: test_vcombine_s16 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} int16x8_t test_vcombine_s16(int16x4_t a, int16x4_t b) { return vcombine_s16(a, b); } // CHECK-LABEL: test_vcombine_s32 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} int32x4_t test_vcombine_s32(int32x2_t a, int32x2_t b) { return vcombine_s32(a, b); } // CHECK-LABEL: test_vcombine_s64 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} int64x2_t test_vcombine_s64(int64x1_t a, int64x1_t b) { return vcombine_s64(a, b); } // CHECK-LABEL: test_vcombine_f16 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} float16x8_t test_vcombine_f16(float16x4_t a, float16x4_t b) { return vcombine_f16(a, b); } // CHECK-LABEL: test_vcombine_f32 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} float32x4_t test_vcombine_f32(float32x2_t a, float32x2_t b) { return vcombine_f32(a, b); } // CHECK-LABEL: test_vcombine_u8 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} uint8x16_t test_vcombine_u8(uint8x8_t a, uint8x8_t b) { return vcombine_u8(a, b); } // CHECK-LABEL: test_vcombine_u16 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} uint16x8_t test_vcombine_u16(uint16x4_t a, uint16x4_t b) { return vcombine_u16(a, b); } // CHECK-LABEL: test_vcombine_u32 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} uint32x4_t test_vcombine_u32(uint32x2_t a, uint32x2_t b) { return vcombine_u32(a, b); } // CHECK-LABEL: test_vcombine_u64 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} uint64x2_t test_vcombine_u64(uint64x1_t a, uint64x1_t b) { return vcombine_u64(a, b); } // CHECK-LABEL: test_vcombine_p8 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} poly8x16_t test_vcombine_p8(poly8x8_t a, poly8x8_t b) { return vcombine_p8(a, b); } // CHECK-LABEL: test_vcombine_p16 +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} +// CHECK: vmov d{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}} poly16x8_t test_vcombine_p16(poly16x4_t a, poly16x4_t b) { return vcombine_p16(a, b); } // CHECK-LABEL: test_vcreate_s8 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i8 d{{[0-9]+}}, [[REG]] int8x8_t test_vcreate_s8(uint64_t a) { - return vcreate_s8(a); + return vclz_s8(vcreate_s8(a)); } // CHECK-LABEL: test_vcreate_s16 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i16 d{{[0-9]+}}, [[REG]] int16x4_t test_vcreate_s16(uint64_t a) { - return vcreate_s16(a); + return vclz_s16(vcreate_s16(a)); } // CHECK-LABEL: test_vcreate_s32 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i32 d{{[0-9]+}}, [[REG]] int32x2_t test_vcreate_s32(uint64_t a) { - return vcreate_s32(a); + return vclz_s32(vcreate_s32(a)); } // CHECK-LABEL: test_vcreate_f16 @@ -1560,38 +1590,59 @@ float32x2_t test_vcreate_f32(uint64_t a) { } // CHECK-LABEL: test_vcreate_u8 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i8 d{{[0-9]+}}, [[REG]] uint8x8_t test_vcreate_u8(uint64_t a) { - return vcreate_u8(a); + return vclz_s8(vcreate_u8(a)); } // CHECK-LABEL: test_vcreate_u16 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i16 d{{[0-9]+}}, [[REG]] uint16x4_t test_vcreate_u16(uint64_t a) { - return vcreate_u16(a); + return vclz_s16(vcreate_u16(a)); } // CHECK-LABEL: test_vcreate_u32 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vclz.i32 d{{[0-9]+}}, [[REG]] uint32x2_t test_vcreate_u32(uint64_t a) { - return vcreate_u32(a); + return vclz_s32(vcreate_u32(a)); } + +// We have two ways of lowering that. Either with one 'vmov d, r, r' or +// with two 'vmov d[],r'. LLVM does the latter. We may want to be less +// strict about the matching pattern if it starts causing problem. // CHECK-LABEL: test_vcreate_u64 +// CHECK: vmov.32 [[REG:d[0-9]+]][0], r0 +// CHECK: vmov.32 [[REG]][1], r1 uint64x1_t test_vcreate_u64(uint64_t a) { - return vcreate_u64(a); + uint64x1_t tmp = vcreate_u64(a); + return vadd_u64(tmp, tmp); + } // CHECK-LABEL: test_vcreate_p8 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 +// CHECK: vcnt.8 d{{[0-9]+}}, [[REG]] poly8x8_t test_vcreate_p8(uint64_t a) { - return vcreate_p8(a); + return vcnt_p8(vcreate_p8(a)); } // CHECK-LABEL: test_vcreate_p16 +// CHECK: vmov [[REG:d[0-9]+]], r0, r1 poly16x4_t test_vcreate_p16(uint64_t a) { - return vcreate_p16(a); + poly16x4_t tmp = vcreate_p16(a); + return vbsl_p16(tmp, tmp, tmp); } // CHECK-LABEL: test_vcreate_s64 +// CHECK: vmov.32 [[REG:d[0-9]+]][0], r0 +// CHECK: vmov.32 [[REG]][1], r1 int64x1_t test_vcreate_s64(uint64_t a) { - return vcreate_s64(a); + int64x1_t tmp = vcreate_s64(a); + return vadd_s64(tmp, tmp); } @@ -1855,7 +1906,7 @@ uint16x4_t test_vdup_n_u16(uint16_t a) { } // CHECK-LABEL: test_vdup_n_u32 -// CHECK: vmov +// CHECK: mov uint32x2_t test_vdup_n_u32(uint32_t a) { return vdup_n_u32(a); } @@ -1873,7 +1924,7 @@ int16x4_t test_vdup_n_s16(int16_t a) { } // CHECK-LABEL: test_vdup_n_s32 -// CHECK: vmov +// CHECK: mov int32x2_t test_vdup_n_s32(int32_t a) { return vdup_n_s32(a); } @@ -1897,7 +1948,7 @@ float16x4_t test_vdup_n_f16(float16_t *a) { } // CHECK-LABEL: test_vdup_n_f32 -// CHECK: vmov +// CHECK: mov float32x2_t test_vdup_n_f32(float32_t a) { return vdup_n_f32(a); } @@ -1963,27 +2014,32 @@ float32x4_t test_vdupq_n_f32(float32_t a) { } // CHECK-LABEL: test_vdup_n_s64 -// CHECK: vmov +// CHECK: vmov int64x1_t test_vdup_n_s64(int64_t a) { - return vdup_n_s64(a); + int64x1_t tmp = vdup_n_s64(a); + return vadd_s64(tmp, tmp); } // CHECK-LABEL: test_vdup_n_u64 -// CHECK: vmov +// CHECK: vmov uint64x1_t test_vdup_n_u64(uint64_t a) { - return vdup_n_u64(a); + int64x1_t tmp = vdup_n_u64(a); + return vadd_s64(tmp, tmp); + } // CHECK-LABEL: test_vdupq_n_s64 -// CHECK: vmov +// CHECK: vmov int64x2_t test_vdupq_n_s64(int64_t a) { - return vdupq_n_s64(a); + int64x2_t tmp = vdupq_n_s64(a); + return vaddq_s64(tmp, tmp); } // CHECK-LABEL: test_vdupq_n_u64 -// CHECK: vmov +// CHECK: vmov uint64x2_t test_vdupq_n_u64(uint64_t a) { - return vdupq_n_u64(a); + int64x2_t tmp = vdupq_n_u64(a); + return vaddq_u64(tmp, tmp); } @@ -2302,7 +2358,7 @@ uint16_t test_vget_lane_u16(uint16x4_t a) { } // CHECK-LABEL: test_vget_lane_u32 -// CHECK: vmov +// CHECK: mov uint32_t test_vget_lane_u32(uint32x2_t a) { return vget_lane_u32(a, 1); } @@ -2320,7 +2376,7 @@ int16_t test_vget_lane_s16(int16x4_t a) { } // CHECK-LABEL: test_vget_lane_s32 -// CHECK: vmov +// CHECK: mov int32_t test_vget_lane_s32(int32x2_t a) { return vget_lane_s32(a, 1); } @@ -2398,13 +2454,13 @@ float32_t test_vgetq_lane_f32(float32x4_t a) { } // CHECK-LABEL: test_vget_lane_s64 -// CHECK: vmov +// The optimizer is able to remove all moves now. int64_t test_vget_lane_s64(int64x1_t a) { return vget_lane_s64(a, 0); } // CHECK-LABEL: test_vget_lane_u64 -// CHECK: vmov +// The optimizer is able to remove all moves now. uint64_t test_vget_lane_u64(uint64x1_t a) { return vget_lane_u64(a, 0); } @@ -4849,49 +4905,49 @@ uint32x2_t test_vmovn_u64(uint64x2_t a) { // CHECK-LABEL: test_vmov_n_u8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint8x8_t test_vmov_n_u8(uint8_t a) { return vmov_n_u8(a); } // CHECK-LABEL: test_vmov_n_u16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint16x4_t test_vmov_n_u16(uint16_t a) { return vmov_n_u16(a); } // CHECK-LABEL: test_vmov_n_u32 -// CHECK: vmov +// CHECK: mov {{r[0-9]+}} uint32x2_t test_vmov_n_u32(uint32_t a) { return vmov_n_u32(a); } // CHECK-LABEL: test_vmov_n_s8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int8x8_t test_vmov_n_s8(int8_t a) { return vmov_n_s8(a); } // CHECK-LABEL: test_vmov_n_s16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int16x4_t test_vmov_n_s16(int16_t a) { return vmov_n_s16(a); } // CHECK-LABEL: test_vmov_n_s32 -// CHECK: vmov +// CHECK: mov {{r[0-9]+}} int32x2_t test_vmov_n_s32(int32_t a) { return vmov_n_s32(a); } // CHECK-LABEL: test_vmov_n_p8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} poly8x8_t test_vmov_n_p8(poly8_t a) { return vmov_n_p8(a); } // CHECK-LABEL: test_vmov_n_p16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} poly16x4_t test_vmov_n_p16(poly16_t a) { return vmov_n_p16(a); } @@ -4903,55 +4959,55 @@ float16x4_t test_vmov_n_f16(float16_t *a) { } // CHECK-LABEL: test_vmov_n_f32 -// CHECK: vmov +// CHECK: mov {{r[0-9]+}} float32x2_t test_vmov_n_f32(float32_t a) { return vmov_n_f32(a); } // CHECK-LABEL: test_vmovq_n_u8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint8x16_t test_vmovq_n_u8(uint8_t a) { return vmovq_n_u8(a); } // CHECK-LABEL: test_vmovq_n_u16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint16x8_t test_vmovq_n_u16(uint16_t a) { return vmovq_n_u16(a); } // CHECK-LABEL: test_vmovq_n_u32 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint32x4_t test_vmovq_n_u32(uint32_t a) { return vmovq_n_u32(a); } // CHECK-LABEL: test_vmovq_n_s8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int8x16_t test_vmovq_n_s8(int8_t a) { return vmovq_n_s8(a); } // CHECK-LABEL: test_vmovq_n_s16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int16x8_t test_vmovq_n_s16(int16_t a) { return vmovq_n_s16(a); } // CHECK-LABEL: test_vmovq_n_s32 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int32x4_t test_vmovq_n_s32(int32_t a) { return vmovq_n_s32(a); } // CHECK-LABEL: test_vmovq_n_p8 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} poly8x16_t test_vmovq_n_p8(poly8_t a) { return vmovq_n_p8(a); } // CHECK-LABEL: test_vmovq_n_p16 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} poly16x8_t test_vmovq_n_p16(poly16_t a) { return vmovq_n_p16(a); } @@ -4963,31 +5019,35 @@ float16x8_t test_vmovq_n_f16(float16_t *a) { } // CHECK-LABEL: test_vmovq_n_f32 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} float32x4_t test_vmovq_n_f32(float32_t a) { return vmovq_n_f32(a); } // CHECK-LABEL: test_vmov_n_s64 -// CHECK: vmov +// CHECK: vmov.32 [[REG:d[0-9]+]][0], r0 +// CHECK: vmov.32 [[REG]][1], r1 int64x1_t test_vmov_n_s64(int64_t a) { - return vmov_n_s64(a); + int64x1_t tmp = vmov_n_s64(a); + return vadd_s64(tmp, tmp); } // CHECK-LABEL: test_vmov_n_u64 -// CHECK: vmov +// CHECK: vmov.32 [[REG:d[0-9]+]][0], r0 +// CHECK: vmov.32 [[REG]][1], r1 uint64x1_t test_vmov_n_u64(uint64_t a) { - return vmov_n_u64(a); + uint64x1_t tmp = vmov_n_u64(a); + return vadd_u64(tmp, tmp); } // CHECK-LABEL: test_vmovq_n_s64 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} int64x2_t test_vmovq_n_s64(int64_t a) { return vmovq_n_s64(a); } // CHECK-LABEL: test_vmovq_n_u64 -// CHECK: vmov +// CHECK: vmov {{r[0-9]+}} uint64x2_t test_vmovq_n_u64(uint64_t a) { return vmovq_n_u64(a); } @@ -9056,7 +9116,7 @@ uint16x4_t test_vset_lane_u16(uint16_t a, uint16x4_t b) { } // CHECK-LABEL: test_vset_lane_u32 -// CHECK: vmov +// CHECK: mov uint32x2_t test_vset_lane_u32(uint32_t a, uint32x2_t b) { return vset_lane_u32(a, b, 1); } @@ -9074,7 +9134,7 @@ int16x4_t test_vset_lane_s16(int16_t a, int16x4_t b) { } // CHECK-LABEL: test_vset_lane_s32 -// CHECK: vmov +// CHECK: mov int32x2_t test_vset_lane_s32(int32_t a, int32x2_t b) { return vset_lane_s32(a, b, 1); } @@ -9092,7 +9152,7 @@ poly16x4_t test_vset_lane_p16(poly16_t a, poly16x4_t b) { } // CHECK-LABEL: test_vset_lane_f32 -// CHECK: vmov +// CHECK: mov float32x2_t test_vset_lane_f32(float32_t a, float32x2_t b) { return vset_lane_f32(a, b, 1); } @@ -9152,13 +9212,13 @@ float32x4_t test_vsetq_lane_f32(float32_t a, float32x4_t b) { } // CHECK-LABEL: test_vset_lane_s64 -// CHECK: vmov +// The optimizer is able to get rid of all moves now. int64x1_t test_vset_lane_s64(int64_t a, int64x1_t b) { return vset_lane_s64(a, b, 0); } // CHECK-LABEL: test_vset_lane_u64 -// CHECK: vmov +// The optimizer is able to get rid of all moves now. uint64x1_t test_vset_lane_u64(uint64_t a, uint64x1_t b) { return vset_lane_u64(a, b, 0); } diff --git a/test/CodeGen/asan-globals.cpp b/test/CodeGen/asan-globals.cpp index d9ecc64615421..20c1fa702a86b 100644 --- a/test/CodeGen/asan-globals.cpp +++ b/test/CodeGen/asan-globals.cpp @@ -1,36 +1,37 @@ +// RUN: echo "int extra_global;" > %t.extra-source.cpp // RUN: echo "global:*blacklisted_global*" > %t.blacklist -// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t.blacklist -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist -emit-llvm -o - %s | FileCheck %s // RUN: echo "src:%s" > %t.blacklist-src -// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t.blacklist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST-SRC +// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST-SRC // REQUIRES: shell int global; -// CHECK: [[GLOBAL_LOC:@.asan_loc_descr[0-9]*]] = private unnamed_addr constant {{.*}} i32 [[@LINE-1]], i32 5 -// CHECK: [[GLOBAL_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"global\00" int dyn_init_global = global; -// CHECK: [[DYN_INIT_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 5 -// CHECK: [[DYN_INIT_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"dyn_init_global\00" int blacklisted_global; void func() { static int static_var = 0; - // CHECK: [[STATIC_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 14 - // CHECK: [[STATIC_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"static_var\00" const char *literal = "Hello, world!"; - // CHECK: [[LITERAL_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 25 - // CHECK: [[LITERAL_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"<string literal>\00" } -// CHECK: !llvm.asan.globals = !{![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} -// CHECK: ![[GLOBAL]] = metadata !{{{.*}} [[GLOBAL_LOC]], {{.*}} [[GLOBAL_NAME]], i1 false, i1 false} -// CHECK: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} [[DYN_INIT_LOC]], {{.*}} [[DYN_INIT_NAME]], i1 true, i1 false} -// CHECK: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, null, i1 false, i1 true} -// CHECK: ![[STATIC_VAR]] = metadata !{{{.*}} [[STATIC_LOC]], {{.*}} [[STATIC_NAME]], i1 false, i1 false} -// CHECK: ![[LITERAL]] = metadata !{{{.*}} [[LITERAL_LOC]], {{.*}} [[LITERAL_NAME]], i1 false, i1 false} +// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false} +// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 8, i32 5} +// CHECK: ![[DYN_INIT_GLOBAL]] = !{{{.*}} ![[DYN_INIT_LOC:[0-9]+]], !"dyn_init_global", i1 true, i1 false} +// CHECK: ![[DYN_INIT_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 9, i32 5} +// CHECK: ![[BLACKLISTED_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true} +// CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false} +// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 13, i32 14} +// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"<string literal>", i1 false, i1 false} +// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 14, i32 25} -// BLACKLIST-SRC: !llvm.asan.globals = !{![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} -// BLACKLIST-SRC: ![[GLOBAL]] = metadata !{{{.*}} null, null, i1 false, i1 true} -// BLACKLIST-SRC: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} null, null, i1 true, i1 true} -// BLACKLIST-SRC: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, null, i1 false, i1 true} -// BLACKLIST-SRC: ![[STATIC_VAR]] = metadata !{{{.*}} null, null, i1 false, i1 true} -// BLACKLIST-SRC: ![[LITERAL]] = metadata !{{{.*}} null, null, i1 false, i1 true} +// BLACKLIST-SRC: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} +// BLACKLIST-SRC: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false} +// BLACKLIST-SRC: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5} +// BLACKLIST-SRC: ![[GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[DYN_INIT_GLOBAL]] = !{{{.*}} null, null, i1 true, i1 true} +// BLACKLIST-SRC: ![[BLACKLISTED_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true} diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index 5dbc01b1211d4..038d346e9993a 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -248,3 +248,17 @@ void t29(void) { // CHECK: @t29 // CHECK: call void asm sideeffect "movl %eax, $0", "*m,~{dirflag},~{fpsr},~{flags}"([1 x i32]* @t29_var) } + +void t30(int len) { + __asm__ volatile("" + : "+&&rm"(len)); + // CHECK: @t30 + // CHECK: call void asm sideeffect "", "=*&rm,0,~{dirflag},~{fpsr},~{flags}" +} + +void t31(int len) { + __asm__ volatile("" + : "+%%rm"(len), "+rm"(len)); + // CHECK: @t31 + // CHECK: call void asm sideeffect "", "=*%rm,=*rm,0,1,~{dirflag},~{fpsr},~{flags}" +} diff --git a/test/CodeGen/atomic-ops-libcall.c b/test/CodeGen/atomic-ops-libcall.c index 2a2ff5e80fcf1..e55a1bd1eae37 100644 --- a/test/CodeGen/atomic-ops-libcall.c +++ b/test/CodeGen/atomic-ops-libcall.c @@ -7,31 +7,31 @@ enum memory_order { int *test_c11_atomic_fetch_add_int_ptr(_Atomic(int *) *p) { // CHECK: test_c11_atomic_fetch_add_int_ptr - // CHECK: {{%[^ ]*}} = tail call i32* @__atomic_fetch_add_4(i8* {{%[0-9]+}}, i32 12, i32 5) + // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_add_4(i8* {{%[0-9]+}}, i32 12, i32 5) return __c11_atomic_fetch_add(p, 3, memory_order_seq_cst); } int *test_c11_atomic_fetch_sub_int_ptr(_Atomic(int *) *p) { // CHECK: test_c11_atomic_fetch_sub_int_ptr - // CHECK: {{%[^ ]*}} = tail call i32* @__atomic_fetch_sub_4(i8* {{%[0-9]+}}, i32 20, i32 5) + // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(i8* {{%[0-9]+}}, i32 20, i32 5) return __c11_atomic_fetch_sub(p, 5, memory_order_seq_cst); } int test_c11_atomic_fetch_add_int(_Atomic(int) *p) { // CHECK: test_c11_atomic_fetch_add_int - // CHECK: {{%[^ ]*}} = tail call i32 bitcast (i32* (i8*, i32, i32)* @__atomic_fetch_add_4 to i32 (i8*, i32, i32)*)(i8* {{%[0-9]+}}, i32 3, i32 5) + // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_add_4(i8* {{%[0-9]+}}, i32 3, i32 5) return __c11_atomic_fetch_add(p, 3, memory_order_seq_cst); } int test_c11_atomic_fetch_sub_int(_Atomic(int) *p) { // CHECK: test_c11_atomic_fetch_sub_int - // CHECK: {{%[^ ]*}} = tail call i32 bitcast (i32* (i8*, i32, i32)* @__atomic_fetch_sub_4 to i32 (i8*, i32, i32)*)(i8* {{%[0-9]+}}, i32 5, i32 5) + // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(i8* {{%[0-9]+}}, i32 5, i32 5) return __c11_atomic_fetch_sub(p, 5, memory_order_seq_cst); } int *fp2a(int **p) { // CHECK: @fp2a - // CHECK: {{%[^ ]*}} = tail call i32* @__atomic_fetch_sub_4(i8* {{%[0-9]+}}, i32 4, i32 0) + // CHECK: {{%[^ ]*}} = tail call i32 @__atomic_fetch_sub_4(i8* {{%[0-9]+}}, i32 4, i32 0) // Note, the GNU builtins do not multiply by sizeof(T)! return __atomic_fetch_sub(p, 4, memory_order_relaxed); } diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c index 9e6b4805e8cb0..559b13541323c 100644 --- a/test/CodeGen/atomic-ops.c +++ b/test/CodeGen/atomic-ops.c @@ -1,18 +1,15 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -ffreestanding -triple=i686-apple-darwin9 | FileCheck %s // Also test serialization of atomic operations here, to avoid duplicating the // test. -// RUN: %clang_cc1 %s -emit-pch -o %t -triple=i686-apple-darwin9 -// RUN: %clang_cc1 %s -include-pch %t -triple=i686-apple-darwin9 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -emit-pch -o %t -ffreestanding -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -include-pch %t -ffreestanding -triple=i686-apple-darwin9 -emit-llvm -o - | FileCheck %s #ifndef ALREADY_INCLUDED #define ALREADY_INCLUDED -// Basic IRGen tests for __c11_atomic_* and GNU __atomic_* +#include <stdatomic.h> -typedef enum memory_order { - memory_order_relaxed, memory_order_consume, memory_order_acquire, - memory_order_release, memory_order_acq_rel, memory_order_seq_cst -} memory_order; +// Basic IRGen tests for __c11_atomic_* and GNU __atomic_* int fi1(_Atomic(int) *i) { // CHECK-LABEL: @fi1 @@ -34,6 +31,12 @@ int fi1b(int *i) { return __atomic_load_n(i, memory_order_seq_cst); } +int fi1c(atomic_int *i) { + // CHECK-LABEL: @fi1c + // CHECK: load atomic i32* {{.*}} seq_cst + return atomic_load(i); +} + void fi2(_Atomic(int) *i) { // CHECK-LABEL: @fi2 // CHECK: store atomic i32 {{.*}} seq_cst @@ -53,6 +56,12 @@ void fi2b(int *i) { __atomic_store_n(i, 1, memory_order_seq_cst); } +void fi2c(atomic_int *i) { + // CHECK-LABEL: @fi2c + // CHECK: store atomic i32 {{.*}} seq_cst + atomic_store(i, 1); +} + int fi3(_Atomic(int) *i) { // CHECK-LABEL: @fi3 // CHECK: atomicrmw and @@ -89,8 +98,15 @@ int fi3d(int *i) { return __atomic_nand_fetch(i, 1, memory_order_seq_cst); } +int fi3e(atomic_int *i) { + // CHECK-LABEL: @fi3e + // CHECK: atomicrmw or + // CHECK-NOT: {{ or }} + return atomic_fetch_or(i, 1); +} + _Bool fi4(_Atomic(int) *i) { - // CHECK-LABEL: @fi4 + // CHECK-LABEL: @fi4( // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 @@ -101,7 +117,7 @@ _Bool fi4(_Atomic(int) *i) { } _Bool fi4a(int *i) { - // CHECK-LABEL: @fi4 + // CHECK-LABEL: @fi4a // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 @@ -113,7 +129,7 @@ _Bool fi4a(int *i) { } _Bool fi4b(int *i) { - // CHECK-LABEL: @fi4 + // CHECK-LABEL: @fi4b( // CHECK: [[PAIR:%[.0-9A-Z_a-z]+]] = cmpxchg weak i32* [[PTR:%[.0-9A-Z_a-z]+]], i32 [[EXPECTED:%[.0-9A-Z_a-z]+]], i32 [[DESIRED:%[.0-9A-Z_a-z]+]] // CHECK: [[OLD:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 0 // CHECK: [[CMP:%[.0-9A-Z_a-z]+]] = extractvalue { i32, i1 } [[PAIR]], 1 @@ -123,6 +139,13 @@ _Bool fi4b(int *i) { return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire); } +_Bool fi4c(atomic_int *i) { + // CHECK-LABEL: @fi4c + // CHECK: cmpxchg i32* + int cmp = 0; + return atomic_compare_exchange_strong(i, &cmp, 1); +} + float ff1(_Atomic(float) *d) { // CHECK-LABEL: @ff1 // CHECK: load atomic i32* {{.*}} monotonic @@ -139,6 +162,79 @@ float ff3(_Atomic(float) *d) { return __c11_atomic_exchange(d, 2, memory_order_seq_cst); } +struct S { + double x; +}; + +struct S fd1(struct S *a) { + // CHECK-LABEL: @fd1 + // CHECK: [[RETVAL:%.*]] = alloca %struct.S, align 4 + // CHECK: [[RET:%.*]] = alloca %struct.S, align 4 + // CHECK: [[CALL:%.*]] = call i64 @__atomic_load_8( + // CHECK: [[CAST:%.*]] = bitcast %struct.S* [[RET]] to i64* + // CHECK: store i64 [[CALL]], i64* [[CAST]], align 4 + struct S ret; + __atomic_load(a, &ret, memory_order_seq_cst); + return ret; +} + +void fd2(struct S *a, struct S *b) { + // CHECK-LABEL: @fd2 + // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* + // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64* + // CHECK-NEXT: [[LOAD_B:%.*]] = load i64* [[COERCED_B]], align 4 + // CHECK-NEXT: call void @__atomic_store_8(i8* [[COERCED_A]], i64 [[LOAD_B]], + // CHECK-NEXT: ret void + __atomic_store(a, b, memory_order_seq_cst); +} + +void fd3(struct S *a, struct S *b, struct S *c) { + // CHECK-LABEL: @fd3 + // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: [[C_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: store %struct.S* %c, %struct.S** [[C_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load %struct.S** [[C_ADDR]], align 4 + // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* + // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i64* + // CHECK-NEXT: [[LOAD_B:%.*]] = load i64* [[COERCED_B]], align 4 + // CHECK-NEXT: [[CALL:%.*]] = call i64 @__atomic_exchange_8(i8* [[COERCED_A]], i64 [[LOAD_B]], + // CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64* + // CHECK-NEXT: store i64 [[CALL]], i64* [[COERCED_C]], align 4 + + __atomic_exchange(a, b, c, memory_order_seq_cst); +} + +_Bool fd4(struct S *a, struct S *b, struct S *c) { + // CHECK-LABEL: @fd4 + // CHECK: [[A_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: [[B_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK-NEXT: [[C_ADDR:%.*]] = alloca %struct.S*, align 4 + // CHECK: store %struct.S* %a, %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: store %struct.S* %b, %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: store %struct.S* %c, %struct.S** [[C_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_A_PTR:%.*]] = load %struct.S** [[A_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_B_PTR:%.*]] = load %struct.S** [[B_ADDR]], align 4 + // CHECK-NEXT: [[LOAD_C_PTR:%.*]] = load %struct.S** [[C_ADDR]], align 4 + // CHECK-NEXT: [[COERCED_A:%.*]] = bitcast %struct.S* [[LOAD_A_PTR]] to i8* + // CHECK-NEXT: [[COERCED_B:%.*]] = bitcast %struct.S* [[LOAD_B_PTR]] to i8* + // CHECK-NEXT: [[COERCED_C:%.*]] = bitcast %struct.S* [[LOAD_C_PTR]] to i64* + // CHECK-NEXT: [[LOAD_C:%.*]] = load i64* [[COERCED_C]], align 4 + // CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange_8(i8* [[COERCED_A]], i8* [[COERCED_B]], i64 [[LOAD_C]] + // CHECK-NEXT: ret i1 [[CALL]] + return __atomic_compare_exchange(a, b, c, 1, 5, 5); +} + int* fp1(_Atomic(int*) *p) { // CHECK-LABEL: @fp1 // CHECK: load atomic i32* {{.*}} seq_cst @@ -287,14 +383,23 @@ struct foo structAtomicExchange() { } int structAtomicCmpExchange() { // CHECK-LABEL: @structAtomicCmpExchange + // CHECK: %[[x_mem:.*]] = alloca i8 _Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5); - // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2 + // CHECK: %[[call1:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2 + // CHECK: %[[zext1:.*]] = zext i1 %[[call1]] to i8 + // CHECK: store i8 %[[zext1]], i8* %[[x_mem]], align 1 + // CHECK: %[[x:.*]] = load i8* %[[x_mem]] + // CHECK: %[[x_bool:.*]] = trunc i8 %[[x]] to i1 + // CHECK: %[[conv1:.*]] = zext i1 %[[x_bool]] to i32 struct foo f = {0}; struct foo g = {0}; g.big[12] = 12; return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5); - // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), + // CHECK: %[[call2:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), + // CHECK: %[[conv2:.*]] = zext i1 %[[call2]] to i32 + // CHECK: %[[and:.*]] = and i32 %[[conv1]], %[[conv2]] + // CHECK: ret i32 %[[and]] } // Check that no atomic operations are used in any initialisation of _Atomic @@ -447,4 +552,51 @@ void EMIT_ALL_THE_THINGS(int *ptr, int *ptr2, int new, _Bool weak, int success, // CHECK: = cmpxchg weak {{.*}} seq_cst seq_cst } +int PR21643() { + return __atomic_or_fetch((int __attribute__((address_space(257))) *)0x308, 1, + __ATOMIC_RELAXED); + // CHECK: %[[atomictmp:.*]] = alloca i32, align 4 + // CHECK: %[[atomicdst:.*]] = alloca i32, align 4 + // CHECK: store i32 1, i32* %[[atomictmp]] + // CHECK: %[[one:.*]] = load i32* %[[atomictmp]], align 4 + // CHECK: %[[old:.*]] = atomicrmw or i32 addrspace(257)* inttoptr (i32 776 to i32 addrspace(257)*), i32 %[[one]] monotonic + // CHECK: %[[new:.*]] = or i32 %[[old]], %[[one]] + // CHECK: store i32 %[[new]], i32* %[[atomicdst]], align 4 + // CHECK: %[[ret:.*]] = load i32* %[[atomicdst]], align 4 + // CHECK: ret i32 %[[ret]] +} + +int PR17306_1(volatile _Atomic(int) *i) { + // CHECK-LABEL: @PR17306_1 + // CHECK: %[[i_addr:.*]] = alloca i32 + // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 + // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] + // CHECK-NEXT: %[[addr:.*]] = load i32** %[[i_addr]] + // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32* %[[addr]] seq_cst + // CHECK-NEXT: store i32 %[[res]], i32* %[[atomicdst]] + // CHECK-NEXT: %[[retval:.*]] = load i32* %[[atomicdst]] + // CHECK-NEXT: ret i32 %[[retval]] + return __c11_atomic_load(i, memory_order_seq_cst); +} + +int PR17306_2(volatile int *i, int value) { + // CHECK-LABEL: @PR17306_2 + // CHECK: %[[i_addr:.*]] = alloca i32* + // CHECK-NEXT: %[[value_addr:.*]] = alloca i32 + // CHECK-NEXT: %[[atomictmp:.*]] = alloca i32 + // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 + // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] + // CHECK-NEXT: store i32 %value, i32* %[[value_addr]] + // CHECK-NEXT: %[[i_lval:.*]] = load i32** %[[i_addr]] + // CHECK-NEXT: %[[value:.*]] = load i32* %[[value_addr]] + // CHECK-NEXT: store i32 %[[value]], i32* %[[atomictmp]] + // CHECK-NEXT: %[[value_lval:.*]] = load i32* %[[atomictmp]] + // CHECK-NEXT: %[[old_val:.*]] = atomicrmw volatile add i32* %[[i_lval]], i32 %[[value_lval]] seq_cst + // CHECK-NEXT: %[[new_val:.*]] = add i32 %[[old_val]], %[[value_lval]] + // CHECK-NEXT: store i32 %[[new_val]], i32* %[[atomicdst]] + // CHECK-NEXT: %[[retval:.*]] = load i32* %[[atomicdst]] + // CHECK-NEXT: ret i32 %[[retval]] + return __atomic_add_fetch(i, value, memory_order_seq_cst); +} + #endif diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c index 43f5bc81ee984..4db3c8e6d69cb 100644 --- a/test/CodeGen/atomic.c +++ b/test/CodeGen/atomic.c @@ -50,7 +50,10 @@ int atomic(void) { old = __sync_fetch_and_xor(&val, 0xb); // CHECK: atomicrmw xor i32* %val, i32 11 seq_cst - + + old = __sync_fetch_and_nand(&val, 0xc); + // CHECK: atomicrmw nand i32* %val, i32 12 seq_cst + old = __sync_add_and_fetch(&val, 1); // CHECK: atomicrmw add i32* %val, i32 1 seq_cst @@ -65,7 +68,10 @@ int atomic(void) { old = __sync_xor_and_fetch(&valc, 5); // CHECK: atomicrmw xor i8* %valc, i8 5 seq_cst - + + old = __sync_nand_and_fetch(&valc, 6); + // CHECK: atomicrmw nand i8* %valc, i8 6 seq_cst + __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0); // CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg i32* null, i32 0, i32 0 seq_cst // CHECK: extractvalue { i32, i1 } [[PAIR]], 0 diff --git a/test/CodeGen/atomic_ops.c b/test/CodeGen/atomic_ops.c index 910e9b9505063..29009bef894ce 100644 --- a/test/CodeGen/atomic_ops.c +++ b/test/CodeGen/atomic_ops.c @@ -7,12 +7,12 @@ void foo(int x) // Check that multiply / divides on atomics produce a cmpxchg loop i *= 2; // CHECK: mul nsw i32 - // CHECK: cmpxchg i32* + // CHECK: {{(cmpxchg i32*|i1 @__atomic_compare_exchange\(i32 4,)}} i /= 2; // CHECK: sdiv i32 - // CHECK: cmpxchg i32* + // CHECK: {{(cmpxchg i32*|i1 @__atomic_compare_exchange\(i32 4, )}} j /= x; // CHECK: sdiv i32 - // CHECK: cmpxchg i16* + // CHECK: {{(cmpxchg i16*|i1 @__atomic_compare_exchange\(i32 2, )}} } diff --git a/test/CodeGen/atomics-inlining.c b/test/CodeGen/atomics-inlining.c index ec916e1b5eef6..9cd280294f38e 100644 --- a/test/CodeGen/atomics-inlining.c +++ b/test/CodeGen/atomics-inlining.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=ARM +// RUN: %clang_cc1 -triple arm-linux-gnueabi -emit-llvm %s -o - | FileCheck %s -check-prefix=ARM // 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 @@ -31,17 +31,17 @@ void test1(void) { (void)__atomic_load(&a1, &a2, memory_order_seq_cst); (void)__atomic_store(&a1, &a2, memory_order_seq_cst); -// ARM-LABEL: define arm_aapcscc void @test1 -// ARM: = call arm_aapcscc zeroext i8 @__atomic_load_1(i8* @c1 -// ARM: call arm_aapcscc void @__atomic_store_1(i8* @c1, i8 zeroext -// ARM: = call arm_aapcscc zeroext i16 @__atomic_load_2(i8* bitcast (i16* @s1 to i8*) -// ARM: call arm_aapcscc void @__atomic_store_2(i8* bitcast (i16* @s1 to i8*), i16 zeroext -// ARM: = call arm_aapcscc i32 @__atomic_load_4(i8* bitcast (i32* @i1 to i8*) -// ARM: call arm_aapcscc void @__atomic_store_4(i8* bitcast (i32* @i1 to i8*), i32 -// ARM: = call arm_aapcscc i64 @__atomic_load_8(i8* bitcast (i64* @ll1 to i8*) -// ARM: call arm_aapcscc void @__atomic_store_8(i8* bitcast (i64* @ll1 to i8*), i64 -// ARM: call arm_aapcscc void @__atomic_load(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) -// ARM: call arm_aapcscc void @__atomic_store(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) +// ARM-LABEL: define{{.*}} void @test1 +// ARM: = call{{.*}} zeroext i8 @__atomic_load_1(i8* @c1 +// ARM: call{{.*}} void @__atomic_store_1(i8* @c1, i8 zeroext +// ARM: = call{{.*}} zeroext i16 @__atomic_load_2(i8* bitcast (i16* @s1 to i8*) +// ARM: call{{.*}} void @__atomic_store_2(i8* bitcast (i16* @s1 to i8*), i16 zeroext +// ARM: = call{{.*}} i32 @__atomic_load_4(i8* bitcast (i32* @i1 to i8*) +// ARM: call{{.*}} void @__atomic_store_4(i8* bitcast (i32* @i1 to i8*), i32 +// ARM: = call{{.*}} i64 @__atomic_load_8(i8* bitcast (i64* @ll1 to i8*) +// ARM: call{{.*}} void @__atomic_store_8(i8* bitcast (i64* @ll1 to i8*), i64 +// ARM: call{{.*}} void @__atomic_load(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) +// ARM: call{{.*}} void @__atomic_store(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) // PPC32-LABEL: define void @test1 // PPC32: = load atomic i8* @c1 seq_cst diff --git a/test/CodeGen/attr-naked.c b/test/CodeGen/attr-naked.c index c07dd8d3732a4..270fc7959f443 100644 --- a/test/CodeGen/attr-naked.c +++ b/test/CodeGen/attr-naked.c @@ -12,7 +12,15 @@ 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() [[NAKED]] { -__attribute((naked, always_inline)) void t2() { +__attribute((naked, always_inline)) void t2() { +} + +// Make sure not to generate prolog or epilog for naked functions. +__attribute((naked)) void t3(int x) { +// CHECK: define void @t3(i32) +// CHECK-NOT: alloca +// CHECK-NOT: store +// CHECK: unreachable } // CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } diff --git a/test/CodeGen/attr-optnone.c b/test/CodeGen/attr-optnone.c index e7069b10f21ac..96493bfe36132 100644 --- a/test/CodeGen/attr-optnone.c +++ b/test/CodeGen/attr-optnone.c @@ -1,12 +1,19 @@ // RUN: %clang_cc1 -emit-llvm < %s > %t // RUN: FileCheck %s --check-prefix=PRESENT < %t // RUN: FileCheck %s --check-prefix=ABSENT < %t +// RUN: %clang_cc1 -emit-llvm -Os < %s > %t +// RUN: FileCheck %s --check-prefix=PRESENT < %t +// RUN: FileCheck %s --check-prefix=OPTSIZE < %t +// RUN: %clang_cc1 -emit-llvm -Oz < %s > %t +// RUN: FileCheck %s --check-prefix=PRESENT < %t +// RUN: FileCheck %s --check-prefix=MINSIZE < %t __attribute__((always_inline)) int test2() { return 0; } -// PRESENT-DAG: @test2{{.*}}[[ATTR2:#[0-9]+]] +// OPTSIZE: @test2{{.*}}[[ATTR2:#[0-9]+]] +// MINSIZE: @test2{{.*}}[[ATTR2:#[0-9]+]] -__attribute__((optnone)) __attribute__((minsize)) +__attribute__((optnone)) int test3() { return 0; } // PRESENT-DAG: @test3{{.*}}[[ATTR3:#[0-9]+]] @@ -23,3 +30,13 @@ int test4() { return test2(); } // Check that no 'optsize' or 'minsize' attributes appear. // ABSENT-NOT: optsize // ABSENT-NOT: minsize + +// With -Os, check that 'optsize' appears only on test2. +// OPTSIZE-NOT: optsize +// OPTSIZE: attributes [[ATTR2]] = { {{.*}}optsize{{.*}} } +// OPTSIZE-NOT: optsize + +// With -Oz, check that 'minsize' appears only on test2. +// MINSIZE-NOT: minsize +// MINSIZE: attributes [[ATTR2]] = { {{.*}}minsize{{.*}} } +// MINSIZE-NOT: minsize diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 356a17996a886..5c9c90d7cee4c 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -26,7 +26,7 @@ int t6 __attribute__((visibility("protected"))); // CHECK: @t12 = global i32 0, section "SECT" int t12 __attribute__((section("SECT"))); -// CHECK: @t9 = alias weak bitcast (void ()* @__t8 to void (...)*) +// CHECK: @t9 = weak alias bitcast (void ()* @__t8 to void (...)*) void __t8() {} void t9() __attribute__((weak, alias("__t8"))); diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c index 10c3a1b726a1c..04825ffa2f60e 100644 --- a/test/CodeGen/avx2-builtins.c +++ b/test/CodeGen/avx2-builtins.c @@ -6,7 +6,7 @@ #include <immintrin.h> __m256i test_mm256_mpsadbw_epu8(__m256i x, __m256i y) { - // CHECK: @llvm.x86.avx2.mpsadbw({{.*}}, {{.*}}, i32 3) + // CHECK: @llvm.x86.avx2.mpsadbw({{.*}}, {{.*}}, i8 3) return _mm256_mpsadbw_epu8(x, y, 3); } diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c new file mode 100644 index 0000000000000..ada84657a607d --- /dev/null +++ b/test/CodeGen/avx512bw-builtins.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -ffreestanding -target-feature +avx512bw -emit-llvm -o - -Werror | FileCheck %s + +#include <immintrin.h> + +__mmask64 test_mm512_cmpeq_epi8_mask(__m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.512 + return (__mmask64)_mm512_cmpeq_epi8_mask(__a, __b); +} + +__mmask64 test_mm512_mask_cmpeq_epi8_mask(__mmask64 __u, __m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_mask_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.512 + return (__mmask64)_mm512_mask_cmpeq_epi8_mask(__u, __a, __b); +} + +__mmask32 test_mm512_cmpeq_epi16_mask(__m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.512 + return (__mmask32)_mm512_cmpeq_epi16_mask(__a, __b); +} + +__mmask32 test_mm512_mask_cmpeq_epi16_mask(__mmask32 __u, __m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_mask_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.512 + return (__mmask32)_mm512_mask_cmpeq_epi16_mask(__u, __a, __b); +} diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c new file mode 100644 index 0000000000000..8bb013fef731c --- /dev/null +++ b/test/CodeGen/avx512f-builtins.c @@ -0,0 +1,212 @@ +// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Werror | FileCheck %s + +// Don't include mm_malloc.h, it's system specific. +#define __MM_MALLOC_H + +#include <immintrin.h> + +__m512d test_mm512_sqrt_pd(__m512d a) +{ + // CHECK-LABEL: @test_mm512_sqrt_pd + // CHECK: @llvm.x86.avx512.sqrt.pd.512 + return _mm512_sqrt_pd(a); +} + +__m512 test_mm512_sqrt_ps(__m512 a) +{ + // CHECK-LABEL: @test_mm512_sqrt_ps + // CHECK: @llvm.x86.avx512.sqrt.ps.512 + return _mm512_sqrt_ps(a); +} + +__m512d test_mm512_rsqrt14_pd(__m512d a) +{ + // CHECK-LABEL: @test_mm512_rsqrt14_pd + // CHECK: @llvm.x86.avx512.rsqrt14.pd.512 + return _mm512_rsqrt14_pd(a); +} + +__m512 test_mm512_rsqrt14_ps(__m512 a) +{ + // CHECK-LABEL: @test_mm512_rsqrt14_ps + // CHECK: @llvm.x86.avx512.rsqrt14.ps.512 + return _mm512_rsqrt14_ps(a); +} + +__m512 test_mm512_add_ps(__m512 a, __m512 b) +{ + // CHECK-LABEL: @test_mm512_add_ps + // CHECK: fadd <16 x float> + return _mm512_add_ps(a, b); +} + +__m512d test_mm512_add_pd(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_add_pd + // CHECK: fadd <8 x double> + return _mm512_add_pd(a, b); +} + +__m512 test_mm512_mul_ps(__m512 a, __m512 b) +{ + // CHECK-LABEL: @test_mm512_mul_ps + // CHECK: fmul <16 x float> + return _mm512_mul_ps(a, b); +} + +__m512d test_mm512_mul_pd(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_mul_pd + // CHECK: fmul <8 x double> + return _mm512_mul_pd(a, b); +} + +void test_mm512_storeu_ps(void *p, __m512 a) +{ + // CHECK-LABEL: @test_mm512_storeu_ps + // CHECK: @llvm.x86.avx512.mask.storeu.ps.512 + _mm512_storeu_ps(p, a); +} + +void test_mm512_storeu_pd(void *p, __m512d a) +{ + // CHECK-LABEL: @test_mm512_storeu_pd + // CHECK: @llvm.x86.avx512.mask.storeu.pd.512 + _mm512_storeu_pd(p, a); +} + +void test_mm512_store_ps(void *p, __m512 a) +{ + // CHECK-LABEL: @test_mm512_store_ps + // CHECK: store <16 x float> + _mm512_store_ps(p, a); +} + +void test_mm512_store_pd(void *p, __m512d a) +{ + // CHECK-LABEL: @test_mm512_store_pd + // CHECK: store <8 x double> + _mm512_store_pd(p, a); +} + +__m512 test_mm512_loadu_ps(void *p) +{ + // CHECK-LABEL: @test_mm512_loadu_ps + // CHECK: load <16 x float>* {{.*}}, align 1{{$}} + return _mm512_loadu_ps(p); +} + +__m512d test_mm512_loadu_pd(void *p) +{ + // CHECK-LABEL: @test_mm512_loadu_pd + // CHECK: load <8 x double>* {{.*}}, align 1{{$}} + return _mm512_loadu_pd(p); +} + +__m512d test_mm512_set1_pd(double d) +{ + // CHECK-LABEL: @test_mm512_set1_pd + // CHECK: insertelement <8 x double> {{.*}}, i32 0 + // CHECK: insertelement <8 x double> {{.*}}, i32 1 + // CHECK: insertelement <8 x double> {{.*}}, i32 2 + // CHECK: insertelement <8 x double> {{.*}}, i32 3 + // CHECK: insertelement <8 x double> {{.*}}, i32 4 + // CHECK: insertelement <8 x double> {{.*}}, i32 5 + // CHECK: insertelement <8 x double> {{.*}}, i32 6 + // CHECK: insertelement <8 x double> {{.*}}, i32 7 + return _mm512_set1_pd(d); +} + +__m512d test_mm512_castpd256_pd512(__m256d a) +{ + // CHECK-LABEL: @test_mm512_castpd256_pd512 + // CHECK: shufflevector <4 x double> {{.*}} <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> + return _mm512_castpd256_pd512(a); +} + +__mmask16 test_mm512_knot(__mmask16 a) +{ + // CHECK-LABEL: @test_mm512_knot + // CHECK: @llvm.x86.avx512.knot.w + return _mm512_knot(a); +} + +__m512i test_mm512_valign_epi64(__m512i a, __m512i b) +{ + // CHECK-LABEL: @test_mm512_valign_epi64 + // CHECK: @llvm.x86.avx512.mask.valign.q.512 + return _mm512_valign_epi64(a, b, 2); +} + +__m512d test_mm512_broadcastsd_pd(__m128d a) +{ + // CHECK-LABEL: @test_mm512_broadcastsd_pd + // CHECK: insertelement <8 x double> {{.*}}, i32 0 + // CHECK: insertelement <8 x double> {{.*}}, i32 1 + // CHECK: insertelement <8 x double> {{.*}}, i32 2 + // CHECK: insertelement <8 x double> {{.*}}, i32 3 + // CHECK: insertelement <8 x double> {{.*}}, i32 4 + // CHECK: insertelement <8 x double> {{.*}}, i32 5 + // CHECK: insertelement <8 x double> {{.*}}, i32 6 + // CHECK: insertelement <8 x double> {{.*}}, i32 7 + return _mm512_broadcastsd_pd(a); +} + +__m512i test_mm512_fmadd_pd(__m512d a, __m512d b, __m512d c) +{ + // CHECK-LABEL: @test_mm512_fmadd_pd + // CHECK: @llvm.x86.fma.mask.vfmadd.pd.512 + return _mm512_fmadd_pd(a, b, c); +} + +__mmask16 test_mm512_cmpeq_epi32_mask(__m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.512 + return (__mmask16)_mm512_cmpeq_epi32_mask(__a, __b); +} + +__mmask16 test_mm512_mask_cmpeq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_mask_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.512 + return (__mmask16)_mm512_mask_cmpeq_epi32_mask(__u, __a, __b); +} + +__mmask8 test_mm512_mask_cmpeq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_mask_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.512 + return (__mmask8)_mm512_mask_cmpeq_epi64_mask(__u, __a, __b); +} + +__mmask8 test_mm512_cmpeq_epi64_mask(__m512i __a, __m512i __b) { + // CHECK-LABEL: @test_mm512_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.512 + return (__mmask8)_mm512_cmpeq_epi64_mask(__a, __b); +} + +__m512d test_mm512_unpackhi_pd(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_unpackhi_pd + // CHECK: shufflevector <8 x double> {{.*}} <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15> + return _mm512_unpackhi_pd(a, b); +} + +__m512d test_mm512_unpacklo_pd(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_unpacklo_pd + // CHECK: shufflevector <8 x double> {{.*}} <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14> + return _mm512_unpacklo_pd(a, b); +} + +__m512d test_mm512_unpackhi_ps(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_unpackhi_ps + // CHECK: shufflevector <16 x float> {{.*}} <i32 2, i32 18, i32 3, i32 19, i32 6, i32 22, i32 7, i32 23, i32 10, i32 26, i32 11, i32 27, i32 14, i32 30, i32 15, i32 31> + return _mm512_unpackhi_ps(a, b); +} + +__m512d test_mm512_unpacklo_ps(__m512d a, __m512d b) +{ + // CHECK-LABEL: @test_mm512_unpacklo_ps + // CHECK: shufflevector <16 x float> {{.*}} <i32 0, i32 16, i32 1, i32 17, i32 4, i32 20, i32 5, i32 21, i32 8, i32 24, i32 9, i32 25, i32 12, i32 28, i32 13, i32 29> + return _mm512_unpacklo_ps(a, b); +} diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c new file mode 100644 index 0000000000000..e4b45173bb13a --- /dev/null +++ b/test/CodeGen/avx512vl-builtins.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -ffreestanding -target-feature +avx512f -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s + +#include <immintrin.h> + +__mmask8 test_mm256_cmpeq_epi32_mask(__m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.256 + return (__mmask8)_mm256_cmpeq_epi32_mask(__a, __b); +} + +__mmask8 test_mm256_mask_cmpeq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_mask_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.256 + return (__mmask8)_mm256_mask_cmpeq_epi32_mask(__u, __a, __b); +} + +__mmask8 test_mm_cmpeq_epi32_mask(__m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.128 + return (__mmask8)_mm_cmpeq_epi32_mask(__a, __b); +} + +__mmask8 test_mm_mask_cmpeq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_mask_cmpeq_epi32_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.d.128 + return (__mmask8)_mm_mask_cmpeq_epi32_mask(__u, __a, __b); +} + +__mmask8 test_mm256_cmpeq_epi64_mask(__m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.256 + return (__mmask8)_mm256_cmpeq_epi64_mask(__a, __b); +} + +__mmask8 test_mm256_mask_cmpeq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_mask_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.256 + return (__mmask8)_mm256_mask_cmpeq_epi64_mask(__u, __a, __b); +} + +__mmask8 test_mm_cmpeq_epi64_mask(__m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.128 + return (__mmask8)_mm_cmpeq_epi64_mask(__a, __b); +} + +__mmask8 test_mm_mask_cmpeq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_mask_cmpeq_epi64_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.q.128 + return (__mmask8)_mm_mask_cmpeq_epi64_mask(__u, __a, __b); +} diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c new file mode 100644 index 0000000000000..a304f7b3d3614 --- /dev/null +++ b/test/CodeGen/avx512vlbw-builtins.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -ffreestanding -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s + +#include <immintrin.h> + +__mmask32 test_mm256_cmpeq_epi8_mask(__m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.256 + return (__mmask32)_mm256_cmpeq_epi8_mask(__a, __b); +} + +__mmask32 test_mm256_mask_cmpeq_epi8_mask(__mmask32 __u, __m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_mask_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.256 + return (__mmask32)_mm256_mask_cmpeq_epi8_mask(__u, __a, __b); +} + +__mmask16 test_mm_cmpeq_epi8_mask(__m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.128 + return (__mmask16)_mm_cmpeq_epi8_mask(__a, __b); +} + +__mmask16 test_mm_mask_cmpeq_epi8_mask(__mmask16 __u, __m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_mask_cmpeq_epi8_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.b.128 + return (__mmask16)_mm_mask_cmpeq_epi8_mask(__u, __a, __b); +} + +__mmask16 test_mm256_cmpeq_epi16_mask(__m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.256 + return (__mmask16)_mm256_cmpeq_epi16_mask(__a, __b); +} + +__mmask16 test_mm256_mask_cmpeq_epi16_mask(__mmask16 __u, __m256i __a, __m256i __b) { + // CHECK-LABEL: @test_mm256_mask_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.256 + return (__mmask16)_mm256_mask_cmpeq_epi16_mask(__u, __a, __b); +} + +__mmask8 test_mm_cmpeq_epi16_mask(__m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.128 + return (__mmask8)_mm_cmpeq_epi16_mask(__a, __b); +} + +__mmask8 test_mm_mask_cmpeq_epi16_mask(__mmask8 __u, __m128i __a, __m128i __b) { + // CHECK-LABEL: @test_mm_mask_cmpeq_epi16_mask + // CHECK: @llvm.x86.avx512.mask.pcmpeq.w.128 + return (__mmask8)_mm_mask_cmpeq_epi16_mask(__u, __a, __b); +} diff --git a/test/CodeGen/block-with-perdefinedexpr.c b/test/CodeGen/block-with-perdefinedexpr.c new file mode 100644 index 0000000000000..68fdea60f3796 --- /dev/null +++ b/test/CodeGen/block-with-perdefinedexpr.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 | FileCheck %s +// rdar://18961148 + +void syslog(const char *, ...); + +void handler( ); + +static void (^spd)() = ^() +{ + handler( ^(){ syslog("%s", __FUNCTION__); } ); +}; +// CHECK: @__FUNCTION__.spd_block_invoke_2 = private unnamed_addr constant [19 x i8] c"spd_block_invoke_2\00" +// CHECK: define internal void @spd_block_invoke_2 +// CHECK: @__FUNCTION__.spd_block_invoke_2 diff --git a/test/CodeGen/bmi2-builtins.c b/test/CodeGen/bmi2-builtins.c index 201cac63b9fe9..5aa54fd0ec344 100644 --- a/test/CodeGen/bmi2-builtins.c +++ b/test/CodeGen/bmi2-builtins.c @@ -24,9 +24,9 @@ unsigned int test_pext_u32(unsigned int __X, unsigned int __Y) { unsigned int test_mulx_u32(unsigned int __X, unsigned int __Y, unsigned int *__P) { // CHECK: @test_mulx_u32 - // CHECK-NOT: mul i64 + // CHECK-NOT: mul nuw i64 // B32: @test_mulx_u32 - // B32: mul i64 + // B32: mul nuw i64 return _mulx_u32(__X, __Y, __P); } @@ -48,6 +48,6 @@ unsigned long long test_pext_u64(unsigned long long __X, unsigned long long __Y) unsigned long long test_mulx_u64(unsigned long long __X, unsigned long long __Y, unsigned long long *__P) { // CHECK: @test_mulx_u64 - // CHECK: mul i128 + // CHECK: mul nuw i128 return _mulx_u64(__X, __Y, __P); } diff --git a/test/CodeGen/bool_test.c b/test/CodeGen/bool_test.c index c836b98303392..cf62dba1df21a 100644 --- a/test/CodeGen/bool_test.c +++ b/test/CodeGen/bool_test.c @@ -15,4 +15,4 @@ void f(_Bool *x, _Bool *y) { // CHECK: store i32 [[TOMEM]] // CHECK: ret void -// CHECK: metadata !{i32 0, i32 2} +// CHECK: i32 0, i32 2} diff --git a/test/CodeGen/builtin-assume-aligned.c b/test/CodeGen/builtin-assume-aligned.c new file mode 100644 index 0000000000000..1d807a40cad44 --- /dev/null +++ b/test/CodeGen/builtin-assume-aligned.c @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @test1 +int test1(int *a) { +// CHECK: [[PTRINT1:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR1:%.+]] = and i64 [[PTRINT1]], 31 +// CHECK: [[MASKCOND1:%.+]] = icmp eq i64 [[MASKEDPTR1]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND1]]) + a = __builtin_assume_aligned(a, 32, 0ull); + return a[0]; +} + +// CHECK-LABEL: @test2 +int test2(int *a) { +// CHECK: [[PTRINT2:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR2:%.+]] = and i64 [[PTRINT2]], 31 +// CHECK: [[MASKCOND2:%.+]] = icmp eq i64 [[MASKEDPTR2]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND2]]) + a = __builtin_assume_aligned(a, 32, 0); + return a[0]; +} + +// CHECK-LABEL: @test3 +int test3(int *a) { +// CHECK: [[PTRINT3:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR3:%.+]] = and i64 [[PTRINT3]], 31 +// CHECK: [[MASKCOND3:%.+]] = icmp eq i64 [[MASKEDPTR3]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND3]]) + a = __builtin_assume_aligned(a, 32); + return a[0]; +} + +// CHECK-LABEL: @test4 +int test4(int *a, int b) { +// CHECK-DAG: [[PTRINT4:%.+]] = ptrtoint +// CHECK-DAG: [[CONV4:%.+]] = sext i32 +// CHECK: [[OFFSETPTR4:%.+]] = sub i64 [[PTRINT4]], [[CONV4]] +// CHECK: [[MASKEDPTR4:%.+]] = and i64 [[OFFSETPTR4]], 31 +// CHECK: [[MASKCOND4:%.+]] = icmp eq i64 [[MASKEDPTR4]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND4]]) + a = __builtin_assume_aligned(a, 32, b); + return a[0]; +} + +int *m1() __attribute__((assume_aligned(64))); + +// CHECK-LABEL: @test5 +int test5() { + return *m1(); +// CHECK: [[PTRINT5:%.+]] = ptrtoint +// CHECK: [[MASKEDPTR5:%.+]] = and i64 [[PTRINT5]], 63 +// CHECK: [[MASKCOND5:%.+]] = icmp eq i64 [[MASKEDPTR5]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND5]]) +} + +int *m2() __attribute__((assume_aligned(64, 12))); + +// CHECK-LABEL: @test6 +int test6() { + return *m2(); +// CHECK: [[PTRINT6:%.+]] = ptrtoint +// CHECK: [[OFFSETPTR6:%.+]] = sub i64 [[PTRINT6]], 12 +// CHECK: [[MASKEDPTR6:%.+]] = and i64 [[OFFSETPTR6]], 63 +// CHECK: [[MASKCOND6:%.+]] = icmp eq i64 [[MASKEDPTR6]], 0 +// CHECK: call void @llvm.assume(i1 [[MASKCOND6]]) +} + diff --git a/test/CodeGen/builtin-assume.c b/test/CodeGen/builtin-assume.c index a381a4c1dfb0a..8411b729abf5e 100644 --- a/test/CodeGen/builtin-assume.c +++ b/test/CodeGen/builtin-assume.c @@ -1,8 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple i386-mingw32 -fms-extensions -emit-llvm -o - %s | FileCheck %s // CHECK-LABEL: @test1 -int test1(int *a) { - __assume(a != 0); +int test1(int *a, int i) { +// CHECK: store i32* %a, i32** [[A_ADDR:%.+]], align +// CHECK: [[A:%.+]] = load i32** [[A_ADDR]] +// CHECK: [[CMP:%.+]] = icmp ne i32* [[A]], null +// CHECK: call void @llvm.assume(i1 [[CMP]]) +#ifdef _MSC_VER + __assume(a != 0) +#else + __builtin_assume(a != 0); +#endif + +// Nothing is generated for an assume with side effects... +// CHECK-NOT: load i32** %i.addr +// CHECK-NOT: call void @llvm.assume +#ifdef _MSC_VER + __assume(++i != 0) +#else + __builtin_assume(++i != 0); +#endif + return a[0]; } diff --git a/test/CodeGen/builtin-recursive.cc b/test/CodeGen/builtin-recursive.cpp index 81e9b9a37c256..7553a6e48f532 100644 --- a/test/CodeGen/builtin-recursive.cc +++ b/test/CodeGen/builtin-recursive.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -nostdsysteminc -nobuiltininc -isystem Inputs -emit-llvm-only %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -nostdsysteminc -nobuiltininc -isystem %S/Inputs -emit-llvm-only %s // This used to cause a read past the end of a global variable. diff --git a/test/CodeGen/builtins-arm-msvc-compat-error.c b/test/CodeGen/builtins-arm-msvc-compat-error.c new file mode 100644 index 0000000000000..29469deb6a700 --- /dev/null +++ b/test/CodeGen/builtins-arm-msvc-compat-error.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-extensions -verify %s + +void emit_error(unsigned int opcode) { + __emit(opcode); // expected-error {{argument to '__emit' must be a constant integer}} +} + diff --git a/test/CodeGen/builtins-arm-msvc-compat-only.c b/test/CodeGen/builtins-arm-msvc-compat-only.c new file mode 100644 index 0000000000000..db82ca4066521 --- /dev/null +++ b/test/CodeGen/builtins-arm-msvc-compat-only.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-extensions -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix CHECK-MSVC +// RUN: %clang_cc1 -triple armv7-eabi -emit-llvm %s -o /dev/null 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EABI +// REQUIRES: arm-registered-target + +void emit() { + __emit(0xdefe); +} + +// CHECK-MSVC: call void asm sideeffect ".inst.n 0xDEFE", ""() +// CHECK-EABI: warning: implicit declaration of function '__emit' is invalid in C99 + +void emit_truncated() { + __emit(0x11110000); // movs r0, r0 +} + +// CHECK-MSVC: call void asm sideeffect ".inst.n 0x0", ""() + diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c index a51df15ce56b8..9f3ed9ac78a14 100644 --- a/test/CodeGen/builtins-arm.c +++ b/test/CodeGen/builtins-arm.c @@ -55,6 +55,12 @@ void sevl() { // CHECK: call {{.*}} @llvm.arm.hint(i32 5) +void dbg() { + __builtin_arm_dbg(0); +} + +// CHECK: call {{.*}} @llvm.arm.dbg(i32 0) + void test_barrier() { __builtin_arm_dmb(1); //CHECK: call {{.*}} @llvm.arm.dmb(i32 1) __builtin_arm_dsb(2); //CHECK: call {{.*}} @llvm.arm.dsb(i32 2) @@ -66,3 +72,15 @@ void test_barrier() { unsigned rbit(unsigned a) { return __builtin_arm_rbit(a); } + +void prefetch(int i) { + __builtin_arm_prefetch(&i, 0, 1); +// CHECK: call {{.*}} @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 1) + + __builtin_arm_prefetch(&i, 1, 1); +// CHECK: call {{.*}} @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 1) + + + __builtin_arm_prefetch(&i, 1, 0); +// CHECK: call {{.*}} @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 0) +} diff --git a/test/CodeGen/builtins-arm64.c b/test/CodeGen/builtins-arm64.c index cfa1181227932..cc1f54732b30b 100644 --- a/test/CodeGen/builtins-arm64.c +++ b/test/CodeGen/builtins-arm64.c @@ -29,3 +29,17 @@ void barriers() { __builtin_arm_dsb(2); //CHECK: call {{.*}} @llvm.aarch64.dsb(i32 2) __builtin_arm_isb(3); //CHECK: call {{.*}} @llvm.aarch64.isb(i32 3) } + +void prefetch() { + __builtin_arm_prefetch(0, 1, 2, 0, 1); // pstl3keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 1, i32 1, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1strm +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1) + + __builtin_arm_prefetch(0, 0, 0, 0, 0); // plil1keep +// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) +} diff --git a/test/CodeGen/builtins-nvptx.c b/test/CodeGen/builtins-nvptx.c index cee9061292bdb..5f91f7ad3b0bb 100644 --- a/test/CodeGen/builtins-nvptx.c +++ b/test/CodeGen/builtins-nvptx.c @@ -155,6 +155,8 @@ void nvvm_math(float f1, float f2, double d1, double d2) { float t3 = __nvvm_sqrt_rn_f(f1); // CHECK: call float @llvm.nvvm.rcp.rn.f float t4 = __nvvm_rcp_rn_f(f2); +// CHECK: call float @llvm.nvvm.add.rn.f + float t5 = __nvvm_add_rn_f(f1, f2); // CHECK: call double @llvm.nvvm.fmax.d double td1 = __nvvm_fmax_d(d1, d2); diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c index 31491072a1d47..c6aa3c2faac21 100644 --- a/test/CodeGen/builtins-ppc-altivec.c +++ b/test/CodeGen/builtins-ppc-altivec.c @@ -1047,7 +1047,7 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp /* vec_ctf */ - res_vf = vec_ctf(vi, param_i); + res_vf = vec_ctf(vi, 0); // CHECK: @llvm.ppc.altivec.vcfsx // CHECK-LE: @llvm.ppc.altivec.vcfsx @@ -1082,7 +1082,7 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vctuxs /* vec_dss */ - vec_dss(param_i); + vec_dss(0); // CHECK: @llvm.ppc.altivec.dss // CHECK-LE: @llvm.ppc.altivec.dss diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c new file mode 100644 index 0000000000000..58a8cc32dce30 --- /dev/null +++ b/test/CodeGen/builtins-ppc-vsx.c @@ -0,0 +1,116 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -faltivec -target-feature +vsx -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +vector unsigned char vuc = { 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7}; +vector float vf = { -1.5, 2.5, -3.5, 4.5 }; +vector double vd = { 3.5, -7.5 }; +vector signed int vsi = { -1, 2, -3, 4 }; +vector unsigned int vui = { 0, 1, 2, 3 }; +vector signed long long vsll = { 255LL, -937LL }; +vector unsigned long long vull = { 1447LL, 2894LL }; +double d = 23.4; + +vector float res_vf; +vector double res_vd; +vector signed int res_vsi; +vector unsigned int res_vui; +vector signed long long res_vsll; +vector unsigned long long res_vull; +double res_d; + +void test1() { +// CHECK-LABEL: define void @test1 + + /* vec_div */ + res_vf = vec_div(vf, vf); +// CHECK: @llvm.ppc.vsx.xvdivsp + + res_vd = vec_div(vd, vd); +// CHECK: @llvm.ppc.vsx.xvdivdp + + /* vec_max */ + res_vf = vec_max(vf, vf); +// CHECK: @llvm.ppc.vsx.xvmaxsp + + res_vd = vec_max(vd, vd); +// CHECK: @llvm.ppc.vsx.xvmaxdp + + res_vf = vec_vmaxfp(vf, vf); +// CHECK: @llvm.ppc.vsx.xvmaxsp + + /* vec_min */ + res_vf = vec_min(vf, vf); +// CHECK: @llvm.ppc.vsx.xvminsp + + res_vd = vec_min(vd, vd); +// CHECK: @llvm.ppc.vsx.xvmindp + + res_vf = vec_vminfp(vf, vf); +// CHECK: @llvm.ppc.vsx.xvminsp + + res_d = __builtin_vsx_xsmaxdp(d, d); +// CHECK: @llvm.ppc.vsx.xsmaxdp + + res_d = __builtin_vsx_xsmindp(d, d); +// CHECK: @llvm.ppc.vsx.xsmindp + + /* vec_perm */ + res_vsll = vec_perm(vsll, vsll, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + res_vull = vec_perm(vull, vull, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + res_vd = vec_perm(vd, vd, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + res_vsll = vec_vperm(vsll, vsll, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + res_vull = vec_vperm(vull, vull, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + res_vd = vec_vperm(vd, vd, vuc); +// CHECK: @llvm.ppc.altivec.vperm + + /* vec_vsx_ld */ + + res_vsi = vec_vsx_ld(0, &vsi); +// CHECK: @llvm.ppc.vsx.lxvw4x + + res_vui = vec_vsx_ld(0, &vui); +// CHECK: @llvm.ppc.vsx.lxvw4x + + res_vf = vec_vsx_ld (0, &vf); +// CHECK: @llvm.ppc.vsx.lxvw4x + + res_vsll = vec_vsx_ld(0, &vsll); +// CHECK: @llvm.ppc.vsx.lxvd2x + + res_vull = vec_vsx_ld(0, &vull); +// CHECK: @llvm.ppc.vsx.lxvd2x + + res_vd = vec_vsx_ld(0, &vd); +// CHECK: @llvm.ppc.vsx.lxvd2x + + /* vec_vsx_st */ + + vec_vsx_st(vsi, 0, &res_vsi); +// CHECK: @llvm.ppc.vsx.stxvw4x + + vec_vsx_st(vui, 0, &res_vui); +// CHECK: @llvm.ppc.vsx.stxvw4x + + vec_vsx_st(vf, 0, &res_vf); +// CHECK: @llvm.ppc.vsx.stxvw4x + + vec_vsx_st(vsll, 0, &res_vsll); +// CHECK: @llvm.ppc.vsx.stxvd2x + + vec_vsx_st(vull, 0, &res_vull); +// CHECK: @llvm.ppc.vsx.stxvd2x + + vec_vsx_st(vd, 0, &res_vd); +// CHECK: @llvm.ppc.vsx.stxvd2x +} diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c index 0f038b87355cc..e9ae834b3cfaa 100644 --- a/test/CodeGen/builtins-x86.c +++ b/test/CodeGen/builtins-x86.c @@ -386,7 +386,7 @@ void f0() { tmp_V4f = __builtin_ia32_roundss(tmp_V4f, tmp_V4f, imm_i_0_16); tmp_V2d = __builtin_ia32_roundsd(tmp_V2d, tmp_V2d, imm_i_0_16); tmp_V2d = __builtin_ia32_roundpd(tmp_V2d, imm_i_0_16); - tmp_V4f = __builtin_ia32_insertps128(tmp_V4f, tmp_V4f, tmp_i); + tmp_V4f = __builtin_ia32_insertps128(tmp_V4f, tmp_V4f, imm_i_0_256); #endif tmp_V4d = __builtin_ia32_addsubpd256(tmp_V4d, tmp_V4d); diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 39bd84c5a5a4e..1ab29a659b31a 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -171,32 +171,55 @@ void bar() { void test_float_builtins(float F, double D, long double LD) { volatile int res; res = __builtin_isinf(F); - // CHECK: call float @fabsf(float + // CHECK: call float @llvm.fabs.f32(float // CHECK: fcmp oeq float {{.*}}, 0x7FF0000000000000 res = __builtin_isinf(D); - // CHECK: call double @fabs(double + // CHECK: call double @llvm.fabs.f64(double // CHECK: fcmp oeq double {{.*}}, 0x7FF0000000000000 res = __builtin_isinf(LD); - // CHECK: call x86_fp80 @fabsl(x86_fp80 + // CHECK: call x86_fp80 @llvm.fabs.f80(x86_fp80 // CHECK: fcmp oeq x86_fp80 {{.*}}, 0xK7FFF8000000000000000 res = __builtin_isfinite(F); // CHECK: fcmp oeq float - // CHECK: call float @fabsf + // CHECK: call float @llvm.fabs.f32(float // CHECK: fcmp une float {{.*}}, 0x7FF0000000000000 // CHECK: and i1 res = __builtin_isnormal(F); // CHECK: fcmp oeq float - // CHECK: call float @fabsf + // CHECK: call float @llvm.fabs.f32(float // CHECK: fcmp ult float {{.*}}, 0x7FF0000000000000 // CHECK: fcmp uge float {{.*}}, 0x3810000000000000 // CHECK: and i1 // CHECK: and i1 } +// CHECK-LABEL: define void @test_float_builtin_ops +void test_float_builtin_ops(float F, double D, long double LD) { + volatile float resf; + volatile double resd; + volatile long double resld; + + resf = __builtin_fmodf(F,F); + // CHECK: frem float + + resd = __builtin_fmod(D,D); + // CHECK: frem double + + resld = __builtin_fmodl(LD,LD); + // CHECK: frem x86_fp80 + + resf = __builtin_fabsf(F); + resd = __builtin_fabs(D); + resld = __builtin_fabsl(LD); + // CHECK: call float @llvm.fabs.f32(float + // CHECK: call double @llvm.fabs.f64(double + // CHECK: call x86_fp80 @llvm.fabs.f80(x86_fp80 +} + // CHECK-LABEL: define void @test_builtin_longjmp void test_builtin_longjmp(void **buffer) { // CHECK: [[BITCAST:%.*]] = bitcast diff --git a/test/CodeGen/c11atomics-ios.c b/test/CodeGen/c11atomics-ios.c index ad004fa4b2f31..ad57550441b0d 100644 --- a/test/CodeGen/c11atomics-ios.c +++ b/test/CodeGen/c11atomics-ios.c @@ -6,7 +6,7 @@ // This work was done in pursuit of <rdar://13338582>. -// CHECK-LABEL: define arm_aapcscc void @testFloat(float* +// CHECK-LABEL: define void @testFloat(float* void testFloat(_Atomic(float) *fp) { // CHECK: [[FP:%.*]] = alloca float* // CHECK-NEXT: [[X:%.*]] = alloca float @@ -37,7 +37,7 @@ void testFloat(_Atomic(float) *fp) { // CHECK-NEXT: ret void } -// CHECK: define arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]* +// CHECK: define void @testComplexFloat([[CF:{ float, float }]]* void testComplexFloat(_Atomic(_Complex float) *fp) { // CHECK: [[FP:%.*]] = alloca [[CF]]*, align 4 // CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8 @@ -93,7 +93,7 @@ void testComplexFloat(_Atomic(_Complex float) *fp) { } typedef struct { short x, y, z, w; } S; -// CHECK: define arm_aapcscc void @testStruct([[S:.*]]* +// CHECK: define void @testStruct([[S:.*]]* void testStruct(_Atomic(S) *fp) { // CHECK: [[FP:%.*]] = alloca [[S]]*, align 4 // CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8 @@ -143,7 +143,7 @@ void testStruct(_Atomic(S) *fp) { } typedef struct { short x, y, z; } PS; -// CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]* +// CHECK: define void @testPromotedStruct([[APS:.*]]* void testPromotedStruct(_Atomic(PS) *fp) { // CHECK: [[FP:%.*]] = alloca [[APS]]*, align 4 // CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8 diff --git a/test/CodeGen/c11atomics.c b/test/CodeGen/c11atomics.c index f4c9522cbdb21..376c582674100 100644 --- a/test/CodeGen/c11atomics.c +++ b/test/CodeGen/c11atomics.c @@ -57,7 +57,7 @@ void testinc(void) // CHECK: testdec void testdec(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b b--; // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst i--; @@ -65,7 +65,7 @@ void testdec(void) l--; // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst s--; - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b --b; // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst // CHECK: sub i32 @@ -80,7 +80,7 @@ void testdec(void) // CHECK: testaddeq void testaddeq(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, 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 @@ -92,7 +92,7 @@ void testaddeq(void) // CHECK: testsubeq void testsubeq(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, 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 @@ -104,7 +104,7 @@ void testsubeq(void) // CHECK: testxoreq void testxoreq(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, 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 @@ -116,7 +116,7 @@ void testxoreq(void) // CHECK: testoreq void testoreq(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, 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 @@ -128,7 +128,7 @@ void testoreq(void) // CHECK: testandeq void testandeq(void) { - // CHECK: cmpxchg i8* @b + // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, 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 diff --git a/test/CodeGen/captured-statements-nested.c b/test/CodeGen/captured-statements-nested.c index 2ff9ee9cc88c5..cd20b5a664624 100644 --- a/test/CodeGen/captured-statements-nested.c +++ b/test/CodeGen/captured-statements-nested.c @@ -11,9 +11,9 @@ struct A { void test_nest_captured_stmt(int param, int size, int param_arr[size]) { int w; int arr[param][size]; - // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i{{.+}}*, i32**, i32* } - // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i32**, i32*, i{{.+}}*, i32**, i32* } - // CHECK1: [[T:%struct.anon.*]] = type { i32*, i32*, %struct.A*, i32**, i32*, i{{.+}}*, i32**, i32* } + // CHECK1: %struct.anon{{.*}} = type { [[INT:i.+]]*, [[INT]]*, [[SIZE_TYPE:i.+]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* } + // CHECK1: %struct.anon{{.*}} = type { [[INT]]*, [[INT]]*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* } + // CHECK1: [[T:%struct.anon.*]] = type { [[INT]]*, [[INT]]*, %struct.A*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* } #pragma clang __debug captured { int x; @@ -31,39 +31,45 @@ void test_nest_captured_stmt(int param, int size, int param_arr[size]) { arr[10][z.a] = 12; // CHECK1: define internal void @__captured_stmt{{.*}}([[T]] + // CHECK1: [[PARAM_ARR_SIZE_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 5 + // CHECK1: [[PARAM_ARR_SIZE:%.+]] = load [[SIZE_TYPE]]* [[PARAM_ARR_SIZE_REF]] + // CHECK1: [[ARR_SIZE1_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8 + // CHECK1: [[ARR_SIZE1:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE1_REF]] + // CHECK1: [[ARR_SIZE2_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 9 + // CHECK1: [[ARR_SIZE2:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE2_REF]] // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK1-NEXT: load %struct.A** // CHECK1-NEXT: getelementptr inbounds %struct.A* // CHECK1-NEXT: store i{{.+}} 1 // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 1 - // CHECK1-NEXT: load i32** - // CHECK1-NEXT: store i32 1 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // CHECK1-NEXT: load i{{[0-9]+}}** + // CHECK1-NEXT: store i{{[0-9]+}} 1 // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 0 - // CHECK1-NEXT: load i32** - // CHECK1-NEXT: store i32 1 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK1-NEXT: load i{{[0-9]+}}** + // CHECK1-NEXT: store i{{[0-9]+}} 1 // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 4 - // CHECK1-NEXT: load i32** - // CHECK1-NEXT: load i32* - // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 3 - // CHECK1-NEXT: load i32*** - // CHECK1-NEXT: load i32** - // CHECK1-NEXT: store i32 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 4 + // CHECK1-NEXT: load i{{[0-9]+}}** + // CHECK1-NEXT: load i{{[0-9]+}}* + // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 3 + // CHECK1-NEXT: load i{{[0-9]+}}*** + // CHECK1-NEXT: load i{{[0-9]+}}** + // CHECK1-NEXT: store i{{[0-9]+}} // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK1-NEXT: load %struct.A** // CHECK1-NEXT: getelementptr inbounds %struct.A* // CHECK1-NEXT: store float // - // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2 + // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2 // CHECK1-NEXT: load %struct.A** // CHECK1-NEXT: getelementptr inbounds %struct.A* // CHECK1-NEXT: store i8 99 // - // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 5 + // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7 // CHECK1-DAG: [[SIZE_ADDR:%.*]] = load i{{.+}}** [[SIZE_ADDR_REF]] // CHECK1-DAG: [[SIZE:%.*]] = load i{{.+}}* [[SIZE_ADDR]] // CHECK1-DAG: [[PARAM_ARR_IDX:%.*]] = sub nsw i{{.+}} [[SIZE]], 1 @@ -77,7 +83,7 @@ void test_nest_captured_stmt(int param, int size, int param_arr[size]) { // CHECK1-DAG: [[Z_ADDR:%.*]] = load %struct.A** [[Z_ADDR_REF]] // CHECK1-DAG: [[Z_A_ADDR:%.*]] = getelementptr inbounds %struct.A* [[Z_ADDR]], i{{.+}} 0, i{{.+}} 0 // CHECK1-DAG: [[ARR_IDX_2:%.*]] = load i{{.+}}* [[Z_A_ADDR]] - // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7 + // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 10 // CHECK1-DAG: [[ARR_ADDR:%.*]] = load i{{.+}}** [[ARR_ADDR_REF]] // CHECK1-DAG: [[ARR_IDX_1:%.*]] = mul {{.*}} 10 // CHECK1-DAG: [[ARR_10_ADDR:%.*]] = getelementptr inbounds i{{.+}}* [[ARR_ADDR]], i{{.*}} [[ARR_IDX_1]] @@ -102,15 +108,15 @@ void test_nest_block() { // CHECK2: define internal void @{{.*}}test_nest_block_block_invoke // - // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i32 + // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i{{[0-9]+}}, // CHECK2: alloca %struct.anon{{.*}} // - // CHECK2: store i32 - // CHECK2: store i32* [[Z]] + // CHECK2: store i{{[0-9]+}} + // CHECK2: store i{{[0-9]+}}* [[Z]] // // CHECK2: getelementptr inbounds %struct.anon // CHECK2-NEXT: getelementptr inbounds - // CHECK2-NEXT: store i32* + // CHECK2-NEXT: store i{{[0-9]+}}* // // CHECK2: call void @__captured_stmt @@ -128,22 +134,22 @@ void test_nest_block() { } // CHECK2: alloca %struct.__block_byref_b - // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i32 + // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i{{[0-9]+}} // CHECK2-NEXT: alloca %struct.__block_byref_d // // CHECK2: bitcast %struct.__block_byref_b* // CHECK2-NEXT: store i8* // - // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 7 + // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 7 // - // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i32 0, i32 0 - // CHECK2: load i32** - // CHECK2: load i32* - // CHECK2: store i32 {{.*}}, i32* [[CapA]] + // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // CHECK2: load i{{[0-9]+}}** + // CHECK2: load i{{[0-9]+}}* + // CHECK2: store i{{[0-9]+}} {{.*}}, i{{[0-9]+}}* [[CapA]] // - // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 8 - // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i32* [[C]] - // CHECK2-NEXT: store i32 [[Val]], i32* [[CapC]] + // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8 + // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i{{[0-9]+}}* [[C]] + // CHECK2-NEXT: store i{{[0-9]+}} [[Val]], i{{[0-9]+}}* [[CapC]] // // CHECK2: bitcast %struct.__block_byref_d* // CHECK2-NEXT: store i8* diff --git a/test/CodeGen/captured-statements.c b/test/CodeGen/captured-statements.c index 85d597aeb3c3a..52747fba1e909 100644 --- a/test/CodeGen/captured-statements.c +++ b/test/CodeGen/captured-statements.c @@ -4,6 +4,8 @@ // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3 +typedef __INTPTR_TYPE__ intptr_t; + int foo(); int global; @@ -61,15 +63,16 @@ void test3(int size) { } // Capture VLA array -void test4(int size, int vla_arr[size]) { +void test4(intptr_t size, intptr_t vla_arr[size]) { #pragma clang __debug captured { vla_arr[0] = 1; } - // CHECK-3: test4([[INT:i.+]] {{.*}}[[SIZE:%.+]], [[INT]]* - // CHECK-3: store [[INT]] {{.*}}[[SIZE]], [[INT]]* [[SIZE_ADDR:%.+]], + // CHECK-3: test4([[INTPTR_T:i.+]] {{.*}}[[SIZE_ARG:%.+]], [[INTPTR_T]]* + // CHECK-3: store [[INTPTR_T]] {{.*}}[[SIZE_ARG]], [[INTPTR_T]]* [[SIZE_ADDR:%.+]], + // CHECK-3: [[SIZE:%.+]] = load [[INTPTR_T]]* [[SIZE_ADDR]], // CHECK-3: [[REF:%.+]] = getelementptr inbounds - // CHECK-3: store [[INT]]* [[SIZE_ADDR]], [[INT]]** [[REF]] + // CHECK-3: store [[INTPTR_T]] [[SIZE]], [[INTPTR_T]]* [[REF]] // CHECK-3: call void @__captured_stmt } diff --git a/test/CodeGen/catch-undef-behavior.c b/test/CodeGen/catch-undef-behavior.c index 00962e40f6654..c41b37c39bc8e 100644 --- a/test/CodeGen/catch-undef-behavior.c +++ b/test/CodeGen/catch-undef-behavior.c @@ -1,61 +1,49 @@ -// 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=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-UBSAN +// 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,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-TRAP +// RUN: %clang_cc1 -fsanitize=null -fsanitize-recover=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" } +// CHECK-UBSAN: @[[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 global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i64 4, i8 1 -// CHECK: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 {{.*}}, i64 4, i8 0 -// 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 } +// CHECK-UBSAN: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i64 4, i8 1 +// CHECK-UBSAN: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 {{.*}}, i64 4, i8 0 +// CHECK-UBSAN: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} +// CHECK-UBSAN: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} +// CHECK-UBSAN: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 10 {{.*}} @{{.*}}, i64 4, i8 0 } +// CHECK-UBSAN: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 3 {{.*}} @{{.*}}, i64 4, i8 1 } -// CHECK: @[[STRUCT_S:.*]] = private unnamed_addr constant { i16, i16, [11 x i8] } { i16 -1, i16 0, [11 x i8] c"'struct S'\00" } +// CHECK-UBSAN: @[[STRUCT_S:.*]] = private unnamed_addr constant { i16, i16, [11 x i8] } { i16 -1, i16 0, [11 x i8] c"'struct S'\00" } -// CHECK: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i64 4, i8 3 } -// CHECK: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} } -// CHECK: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} } +// CHECK-UBSAN: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i64 4, i8 3 } +// CHECK-UBSAN: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} } +// CHECK-UBSAN: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} } // CHECK-NULL: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} // PR6805 -// CHECK-LABEL: @foo +// CHECK-COMMON-LABEL: @foo // CHECK-NULL-LABEL: @foo -// CHECK-TRAP-LABEL: @foo void foo() { union { int i; } u; - // CHECK: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null - // CHECK-TRAP: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null + // CHECK-COMMON: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null - // CHECK: %[[I8PTR:.*]] = bitcast i32* %[[PTR]] to i8* - // CHECK-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false) - // CHECK-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 - // CHECK-NEXT: %[[CHECK01:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] + // CHECK-COMMON: %[[I8PTR:.*]] = bitcast i32* %[[PTR]] to i8* + // CHECK-COMMON-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false) + // CHECK-COMMON-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 - // CHECK-TRAP: %[[I8PTR:.*]] = bitcast i32* %[[PTR]] to i8* - // CHECK-TRAP-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false) - // CHECK-TRAP-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 - // CHECK-TRAP-NEXT: %[[CHECK01:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] + // CHECK-COMMON: %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64 + // CHECK-COMMON-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3 + // CHECK-COMMON-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 - // CHECK: %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64 - // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3 - // CHECK-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 + // CHECK-COMMON: %[[CHECK01:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] + // CHECK-COMMON-NEXT: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] - // 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-UBSAN: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize + // CHECK-TRAP: br i1 %[[OK]], {{.*}} - // CHECK: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] - // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize - - // 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]]) + // CHECK-UBSAN: %[[ARG:.*]] = ptrtoint {{.*}} %[[PTR]] to i64 + // CHECK-UBSAN-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 @@ -68,25 +56,17 @@ void foo() { u.i=1; } -// CHECK-LABEL: @bar -// CHECK-TRAP-LABEL: @bar +// CHECK-COMMON-LABEL: @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-COMMON: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 + // CHECK-COMMON-NEXT: icmp uge i64 %[[SIZE]], 4 - // CHECK: %[[PTRINT:.*]] = ptrtoint - // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 - // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 + // CHECK-COMMON: %[[PTRINT:.*]] = ptrtoint + // CHECK-COMMON-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 + // CHECK-COMMON-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]]) + // CHECK-UBSAN: %[[ARG:.*]] = ptrtoint + // CHECK-UBSAN-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 @@ -95,85 +75,62 @@ int bar(int *a) { return *a; } -// CHECK-LABEL: @addr_space +// CHECK-UBSAN-LABEL: @addr_space int addr_space(int __attribute__((address_space(256))) *a) { - // CHECK-NOT: __ubsan + // CHECK-UBSAN-NOT: __ubsan return *a; } -// CHECK-LABEL: @lsh_overflow -// CHECK-TRAP-LABEL: @lsh_overflow +// CHECK-COMMON-LABEL: @lsh_overflow int lsh_overflow(int a, int b) { - // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 - // CHECK-NEXT: br i1 %[[INBOUNDS]], label %[[CHECKBB:.*]], label %[[CONTBB:.*]] - - // CHECK-TRAP: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 - // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]], label %[[CHECKBB:.*]], label %[[CONTBB:.*]] + // CHECK-COMMON: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 + // CHECK-COMMON-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 label %[[CONTBB]] + // CHECK-COMMON: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]] + // CHECK-COMMON-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]] + // CHECK-COMMON-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT]], 0 + // CHECK-COMMON-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-COMMON: %[[VALID:.*]] = phi i1 [ %[[INBOUNDS]], {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECKBB]] ] + // CHECK-UBSAN: br i1 %[[VALID]], {{.*}} !prof ![[WEIGHT_MD]] + // CHECK-TRAP: br i1 %[[VALID]] - // 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]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) - // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds + // CHECK-UBSAN: %[[ARG1:.*]] = zext + // CHECK-UBSAN-NEXT: %[[ARG2:.*]] = zext + // CHECK-UBSAN-NEXT: call void @__ubsan_handle_shift_out_of_bounds(i8* bitcast ({{.*}} @[[LINE_300]] to i8*), i64 %[[ARG1]], i64 %[[ARG2]]) + // CHECK-UBSAN-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]] + // CHECK-COMMON: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]] + // CHECK-COMMON-NEXT: ret i32 %[[RET]] #line 300 return a << b; } -// CHECK-LABEL: @rsh_inbounds -// CHECK-TRAP-LABEL: @rsh_inbounds +// CHECK-COMMON-LABEL: @rsh_inbounds int rsh_inbounds(int a, int b) { - // CHECK: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 - // CHECK: br i1 %[[INBOUNDS]] + // CHECK-COMMON: %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31 + // CHECK-COMMON: 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]]) + // CHECK-UBSAN: %[[ARG1:.*]] = zext + // CHECK-UBSAN-NEXT: %[[ARG2:.*]] = zext + // CHECK-UBSAN-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]] + // CHECK-COMMON: %[[RET:.*]] = ashr i32 %[[LHS]], %[[RHS]] + // CHECK-COMMON-NEXT: ret i32 %[[RET]] #line 400 return a >> b; } -// CHECK-LABEL: @load -// CHECK-TRAP-LABEL: @load +// CHECK-COMMON-LABEL: @load int load(int *p) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_500]] to i8*), i64 %{{.*}}) + // CHECK-UBSAN: 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 @@ -181,10 +138,9 @@ int load(int *p) { return *p; } -// CHECK-LABEL: @store -// CHECK-TRAP-LABEL: @store +// CHECK-COMMON-LABEL: @store void store(int *p, int q) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_600]] to i8*), i64 %{{.*}}) + // CHECK-UBSAN: 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 @@ -194,10 +150,9 @@ void store(int *p, int q) { struct S { int k; }; -// CHECK-LABEL: @member_access -// CHECK-TRAP-LABEL: @member_access +// CHECK-COMMON-LABEL: @member_access int *member_access(struct S *p) { - // CHECK: call void @__ubsan_handle_type_mismatch(i8* bitcast ({{.*}} @[[LINE_700]] to i8*), i64 %{{.*}}) + // CHECK-UBSAN: 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 @@ -205,12 +160,11 @@ int *member_access(struct S *p) { return &p->k; } -// CHECK-LABEL: @signed_overflow -// CHECK-TRAP-LABEL: @signed_overflow +// CHECK-COMMON-LABEL: @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]]) + // CHECK-UBSAN: %[[ARG1:.*]] = zext + // CHECK-UBSAN-NEXT: %[[ARG2:.*]] = zext + // CHECK-UBSAN-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 @@ -218,220 +172,213 @@ int signed_overflow(int a, int b) { return a + b; } -// CHECK-LABEL: @no_return -// CHECK-TRAP-LABEL: @no_return +// CHECK-COMMON-LABEL: @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 // that here even though it's not undefined behavior. - // CHECK-NOT: call - // CHECK-NOT: unreachable - // CHECK: ret i32 - - // CHECK-TRAP-NOT: call - // CHECK-TRAP-NOT: unreachable - // CHECK-TRAP: ret i32 + // CHECK-COMMON-NOT: call + // CHECK-COMMON-NOT: unreachable + // CHECK-COMMON: ret i32 } -// CHECK-LABEL: @vla_bound +// CHECK-UBSAN-LABEL: @vla_bound void vla_bound(int n) { - // CHECK: icmp sgt i32 %[[PARAM:.*]], 0 + // CHECK-UBSAN: 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]]) + // CHECK-UBSAN: %[[ARG:.*]] = zext i32 %[[PARAM]] to i64 + // CHECK-UBSAN-NEXT: call void @__ubsan_handle_vla_bound_not_positive(i8* bitcast ({{.*}} @[[LINE_900]] to i8*), i64 %[[ARG]]) #line 900 int arr[n * 3]; } -// CHECK-LABEL: @int_float_no_overflow +// CHECK-UBSAN-LABEL: @int_float_no_overflow float int_float_no_overflow(__int128 n) { - // CHECK-NOT: call void @__ubsan_handle + // CHECK-UBSAN-NOT: call void @__ubsan_handle return n; } -// CHECK-LABEL: @int_float_overflow -// CHECK-TRAP-LABEL: @int_float_overflow +// CHECK-COMMON-LABEL: @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-COMMON: %[[INBOUNDS:.*]] = icmp ule i128 %{{.*}}, -20282409603651670423947251286016 + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // CHECK-TRAP: %[[INBOUNDS:.*]] = icmp ule i128 %{{.*}}, -20282409603651670423947251286016 - // CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]] + // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow( // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return n; } -// CHECK-LABEL: @int_fp16_overflow -// CHECK-TRAP-LABEL: @int_fp16_overflow +// CHECK-COMMON-LABEL: @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-COMMON: %[[GE:.*]] = icmp sge i32 %{{.*}}, -65504 + // CHECK-COMMON: %[[LE:.*]] = icmp sle i32 %{{.*}}, 65504 + // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // 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-UBSAN: call void @__ubsan_handle_float_cast_overflow( // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable *p = n; } -// CHECK-LABEL: @float_int_overflow -// CHECK-TRAP-LABEL: @float_int_overflow +// CHECK-COMMON-LABEL: @float_int_overflow int float_int_overflow(float f) { - // CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000 - // CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000 - // CHECK: and i1 %[[GE]], %[[LE]] - - // 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-COMMON: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000 + // CHECK-COMMON: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000 + // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // 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-UBSAN: %[[CAST:.*]] = bitcast float %[[F]] to i32 + // CHECK-UBSAN: %[[ARG:.*]] = zext i32 %[[CAST]] to i64 + // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]] // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return f; } -// CHECK-LABEL: @long_double_int_overflow -// CHECK-TRAP-LABEL: @long_double_int_overflow +// CHECK-COMMON-LABEL: @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-UBSAN: alloca x86_fp80 - // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]], !nosanitize - // CHECK: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64 - // CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]] + // CHECK-COMMON: %[[GE:.*]] = fcmp ogt x86_fp80 %[[F:.*]], 0xKC01E800000010000000 + // CHECK-COMMON: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E800000000000000 + // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // 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-UBSAN: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]], !nosanitize + // CHECK-UBSAN: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64 + // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]] // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return ld; } -// CHECK-LABEL: @float_uint_overflow -// CHECK-TRAP-LABEL: @float_uint_overflow +// CHECK-COMMON-LABEL: @float_uint_overflow unsigned float_uint_overflow(float f) { - // 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-COMMON: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.{{0*}}e+00 + // CHECK-COMMON: %[[LE:.*]] = fcmp olt float %[[F]], 0x41F0000000000000 + // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // 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-UBSAN: call void @__ubsan_handle_float_cast_overflow( // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return f; } -// CHECK-LABEL: @fp16_char_overflow -// CHECK-TRAP-LABEL: @fp16_char_overflow +// CHECK-COMMON-LABEL: @fp16_char_overflow signed char fp16_char_overflow(__fp16 *p) { - // 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-COMMON: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.29{{0*}}e+02 + // CHECK-COMMON: %[[LE:.*]] = fcmp olt float %[[F]], 1.28{{0*}}e+02 + // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - // 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-UBSAN: call void @__ubsan_handle_float_cast_overflow( // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return *p; } -// CHECK-LABEL: @float_float_overflow -// CHECK-TRAP-LABEL: @float_float_overflow +// CHECK-COMMON-LABEL: @float_float_overflow float float_float_overflow(double f) { - // 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-COMMON: %[[F:.*]] = call double @llvm.fabs.f64( + // CHECK-COMMON: %[[GE:.*]] = fcmp ogt double %[[F]], 0x47EFFFFFE0000000 + // CHECK-COMMON: %[[LE:.*]] = fcmp olt double %[[F]], 0x7FF0000000000000 + // CHECK-COMMON: %[[OUTOFBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] + // CHECK-COMMON: %[[INBOUNDS:.*]] = xor i1 %[[OUTOFBOUNDS]], true + // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] + + // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow( // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] // CHECK-TRAP-NEXT: unreachable return f; } -// CHECK-LABEL: @int_divide_overflow +// CHECK-COMMON-LABEL: @int_divide_overflow // CHECK-OVERFLOW-LABEL: @int_divide_overflow int int_divide_overflow(int a, int b) { - // CHECK: %[[ZERO:.*]] = icmp ne i32 %[[B:.*]], 0 + // CHECK-COMMON: %[[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 - // CHECK-NEXT: %[[OVER:.*]] = or i1 %[[AOK]], %[[BOK]] + // CHECK-COMMON: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 + // CHECK-COMMON-NEXT: %[[BOK:.*]] = icmp ne i32 %[[B]], -1 + // CHECK-COMMON-NEXT: %[[OVER:.*]] = or i1 %[[AOK]], %[[BOK]] + // CHECK-COMMON: %[[OK:.*]] = and i1 %[[ZERO]], %[[OVER]] + // CHECK-COMMON: br i1 %[[OK]] // CHECK-OVERFLOW: %[[AOK:.*]] = icmp ne i32 %[[A:.*]], -2147483648 // 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-COMMON: } // CHECK-OVERFLOW: } - // CHECK-TRAP: } } -// CHECK-LABEL: @sour_bool +// CHECK-COMMON-LABEL: @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-COMMON: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 + // CHECK-COMMON: br i1 %[[OK]] - // CHECK-TRAP: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 - // CHECK-TRAP: br i1 %[[OK]] + // CHECK-UBSAN: call void @__ubsan_handle_load_invalid_value(i8* bitcast ({{.*}}), i64 {{.*}}) // 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-COMMON-LABEL: @ret_nonnull +__attribute__((returns_nonnull)) +int *ret_nonnull(int *a) { + // CHECK-COMMON: [[OK:%.*]] = icmp ne i32* {{.*}}, null + // CHECK-COMMON: br i1 [[OK]] + + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_return + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP: unreachable + return a; +} + +// CHECK-COMMON-LABEL: @call_decl_nonnull +__attribute__((nonnull)) void decl_nonnull(int *a); +void call_decl_nonnull(int *a) { + // CHECK-COMMON: [[OK:%.*]] = icmp ne i32* {{.*}}, null + // CHECK-COMMON: br i1 [[OK]] + + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + + // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] + // CHECK-TRAP: unreachable + decl_nonnull(a); +} + +// CHECK-COMMON-LABEL: @call_nonnull_variadic +__attribute__((nonnull)) void nonnull_variadic(int a, ...); +void call_nonnull_variadic(int a, int *b) { + // CHECK-COMMON: [[OK:%.*]] = icmp ne i32* {{.*}}, null + // CHECK-COMMON: br i1 [[OK]] + + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + // CHECK-UBSAN-NOT: __ubsan_handle_nonnull_arg + + // CHECK-COMMON: call void (i32, ...)* @nonnull_variadic + nonnull_variadic(a, b); +} + +// CHECK-UBSAN: ![[WEIGHT_MD]] = !{!"branch_weights", i32 1048575, i32 1} // CHECK-TRAP: attributes [[NR_NUW]] = { noreturn nounwind } diff --git a/test/CodeGen/complex-math.c b/test/CodeGen/complex-math.c new file mode 100644 index 0000000000000..36ef271b0ae02 --- /dev/null +++ b/test/CodeGen/complex-math.c @@ -0,0 +1,481 @@ +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple x86_64-pc-win64 -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple i686-unknown-unknown -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple powerpc-unknown-unknown -o - | FileCheck %s --check-prefix=PPC +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARM + +float _Complex add_float_rr(float a, float b) { + // X86-LABEL: @add_float_rr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +float _Complex add_float_cr(float _Complex a, float b) { + // X86-LABEL: @add_float_cr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +float _Complex add_float_rc(float a, float _Complex b) { + // X86-LABEL: @add_float_rc( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +float _Complex add_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @add_float_cc( + // X86: fadd + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} + +float _Complex sub_float_rr(float a, float b) { + // X86-LABEL: @sub_float_rr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +float _Complex sub_float_cr(float _Complex a, float b) { + // X86-LABEL: @sub_float_cr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +float _Complex sub_float_rc(float a, float _Complex b) { + // X86-LABEL: @sub_float_rc( + // X86: fsub + // X86: fsub float -0.{{0+}}e+00, + // X86-NOT: fsub + // X86: ret + return a - b; +} +float _Complex sub_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @sub_float_cc( + // X86: fsub + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} + +float _Complex mul_float_rr(float a, float b) { + // X86-LABEL: @mul_float_rr( + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +float _Complex mul_float_cr(float _Complex a, float b) { + // X86-LABEL: @mul_float_cr( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +float _Complex mul_float_rc(float a, float _Complex b) { + // X86-LABEL: @mul_float_rc( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +float _Complex mul_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @mul_float_cc( + // X86: %[[AC:[^ ]+]] = fmul + // X86: %[[BD:[^ ]+]] = fmul + // X86: %[[AD:[^ ]+]] = fmul + // X86: %[[BC:[^ ]+]] = fmul + // X86: %[[RR:[^ ]+]] = fsub float %[[AC]], %[[BD]] + // X86: %[[RI:[^ ]+]] = fadd float + // X86-DAG: %[[AD]] + // X86-DAG: , + // X86-DAG: %[[BC]] + // X86: fcmp uno float %[[RR]] + // X86: fcmp uno float %[[RI]] + // X86: call {{.*}} @__mulsc3( + // X86: ret + return a * b; +} + +float _Complex div_float_rr(float a, float b) { + // X86-LABEL: @div_float_rr( + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +float _Complex div_float_cr(float _Complex a, float b) { + // X86-LABEL: @div_float_cr( + // X86: fdiv + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +float _Complex div_float_rc(float a, float _Complex b) { + // X86-LABEL: @div_float_rc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divsc3( + // X86: ret + return a / b; +} +float _Complex div_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @div_float_cc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divsc3( + // X86: ret + return a / b; +} + +double _Complex add_double_rr(double a, double b) { + // X86-LABEL: @add_double_rr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +double _Complex add_double_cr(double _Complex a, double b) { + // X86-LABEL: @add_double_cr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +double _Complex add_double_rc(double a, double _Complex b) { + // X86-LABEL: @add_double_rc( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +double _Complex add_double_cc(double _Complex a, double _Complex b) { + // X86-LABEL: @add_double_cc( + // X86: fadd + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} + +double _Complex sub_double_rr(double a, double b) { + // X86-LABEL: @sub_double_rr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +double _Complex sub_double_cr(double _Complex a, double b) { + // X86-LABEL: @sub_double_cr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +double _Complex sub_double_rc(double a, double _Complex b) { + // X86-LABEL: @sub_double_rc( + // X86: fsub + // X86: fsub double -0.{{0+}}e+00, + // X86-NOT: fsub + // X86: ret + return a - b; +} +double _Complex sub_double_cc(double _Complex a, double _Complex b) { + // X86-LABEL: @sub_double_cc( + // X86: fsub + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} + +double _Complex mul_double_rr(double a, double b) { + // X86-LABEL: @mul_double_rr( + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +double _Complex mul_double_cr(double _Complex a, double b) { + // X86-LABEL: @mul_double_cr( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +double _Complex mul_double_rc(double a, double _Complex b) { + // X86-LABEL: @mul_double_rc( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +double _Complex mul_double_cc(double _Complex a, double _Complex b) { + // X86-LABEL: @mul_double_cc( + // X86: %[[AC:[^ ]+]] = fmul + // X86: %[[BD:[^ ]+]] = fmul + // X86: %[[AD:[^ ]+]] = fmul + // X86: %[[BC:[^ ]+]] = fmul + // X86: %[[RR:[^ ]+]] = fsub double %[[AC]], %[[BD]] + // X86: %[[RI:[^ ]+]] = fadd double + // X86-DAG: %[[AD]] + // X86-DAG: , + // X86-DAG: %[[BC]] + // X86: fcmp uno double %[[RR]] + // X86: fcmp uno double %[[RI]] + // X86: call {{.*}} @__muldc3( + // X86: ret + return a * b; +} + +double _Complex div_double_rr(double a, double b) { + // X86-LABEL: @div_double_rr( + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +double _Complex div_double_cr(double _Complex a, double b) { + // X86-LABEL: @div_double_cr( + // X86: fdiv + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +double _Complex div_double_rc(double a, double _Complex b) { + // X86-LABEL: @div_double_rc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divdc3( + // X86: ret + return a / b; +} +double _Complex div_double_cc(double _Complex a, double _Complex b) { + // X86-LABEL: @div_double_cc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divdc3( + // X86: ret + return a / b; +} + +long double _Complex add_long_double_rr(long double a, long double b) { + // X86-LABEL: @add_long_double_rr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +long double _Complex add_long_double_cr(long double _Complex a, long double b) { + // X86-LABEL: @add_long_double_cr( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +long double _Complex add_long_double_rc(long double a, long double _Complex b) { + // X86-LABEL: @add_long_double_rc( + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} +long double _Complex add_long_double_cc(long double _Complex a, long double _Complex b) { + // X86-LABEL: @add_long_double_cc( + // X86: fadd + // X86: fadd + // X86-NOT: fadd + // X86: ret + return a + b; +} + +long double _Complex sub_long_double_rr(long double a, long double b) { + // X86-LABEL: @sub_long_double_rr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +long double _Complex sub_long_double_cr(long double _Complex a, long double b) { + // X86-LABEL: @sub_long_double_cr( + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} +long double _Complex sub_long_double_rc(long double a, long double _Complex b) { + // X86-LABEL: @sub_long_double_rc( + // X86: fsub + // X86: fsub x86_fp80 0xK8{{0+}}, + // X86-NOT: fsub + // X86: ret + return a - b; +} +long double _Complex sub_long_double_cc(long double _Complex a, long double _Complex b) { + // X86-LABEL: @sub_long_double_cc( + // X86: fsub + // X86: fsub + // X86-NOT: fsub + // X86: ret + return a - b; +} + +long double _Complex mul_long_double_rr(long double a, long double b) { + // X86-LABEL: @mul_long_double_rr( + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +long double _Complex mul_long_double_cr(long double _Complex a, long double b) { + // X86-LABEL: @mul_long_double_cr( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +long double _Complex mul_long_double_rc(long double a, long double _Complex b) { + // X86-LABEL: @mul_long_double_rc( + // X86: fmul + // X86: fmul + // X86-NOT: fmul + // X86: ret + return a * b; +} +long double _Complex mul_long_double_cc(long double _Complex a, long double _Complex b) { + // X86-LABEL: @mul_long_double_cc( + // X86: %[[AC:[^ ]+]] = fmul + // X86: %[[BD:[^ ]+]] = fmul + // X86: %[[AD:[^ ]+]] = fmul + // X86: %[[BC:[^ ]+]] = fmul + // X86: %[[RR:[^ ]+]] = fsub x86_fp80 %[[AC]], %[[BD]] + // X86: %[[RI:[^ ]+]] = fadd x86_fp80 + // X86-DAG: %[[AD]] + // X86-DAG: , + // X86-DAG: %[[BC]] + // X86: fcmp uno x86_fp80 %[[RR]] + // X86: fcmp uno x86_fp80 %[[RI]] + // X86: call {{.*}} @__mulxc3( + // X86: ret + // PPC-LABEL: @mul_long_double_cc( + // PPC: %[[AC:[^ ]+]] = fmul + // PPC: %[[BD:[^ ]+]] = fmul + // PPC: %[[AD:[^ ]+]] = fmul + // PPC: %[[BC:[^ ]+]] = fmul + // PPC: %[[RR:[^ ]+]] = fsub ppc_fp128 %[[AC]], %[[BD]] + // PPC: %[[RI:[^ ]+]] = fadd ppc_fp128 + // PPC-DAG: %[[AD]] + // PPC-DAG: , + // PPC-DAG: %[[BC]] + // PPC: fcmp uno ppc_fp128 %[[RR]] + // PPC: fcmp uno ppc_fp128 %[[RI]] + // PPC: call {{.*}} @__multc3( + // PPC: ret + return a * b; +} + +long double _Complex div_long_double_rr(long double a, long double b) { + // X86-LABEL: @div_long_double_rr( + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +long double _Complex div_long_double_cr(long double _Complex a, long double b) { + // X86-LABEL: @div_long_double_cr( + // X86: fdiv + // X86: fdiv + // X86-NOT: fdiv + // X86: ret + return a / b; +} +long double _Complex div_long_double_rc(long double a, long double _Complex b) { + // X86-LABEL: @div_long_double_rc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divxc3( + // X86: ret + // PPC-LABEL: @div_long_double_rc( + // PPC-NOT: fdiv + // PPC: call {{.*}} @__divtc3( + // PPC: ret + return a / b; +} +long double _Complex div_long_double_cc(long double _Complex a, long double _Complex b) { + // X86-LABEL: @div_long_double_cc( + // X86-NOT: fdiv + // X86: call {{.*}} @__divxc3( + // X86: ret + // PPC-LABEL: @div_long_double_cc( + // PPC-NOT: fdiv + // PPC: call {{.*}} @__divtc3( + // PPC: ret + return a / b; +} + +// Comparison operators don't rely on library calls or have interseting math +// properties, but test that mixed types work correctly here. +_Bool eq_float_cr(float _Complex a, float b) { + // X86-LABEL: @eq_float_cr( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool eq_float_rc(float a, float _Complex b) { + // X86-LABEL: @eq_float_rc( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool eq_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @eq_float_cc( + // X86: fcmp oeq + // X86: fcmp oeq + // X86: and i1 + // X86: ret + return a == b; +} +_Bool ne_float_cr(float _Complex a, float b) { + // X86-LABEL: @ne_float_cr( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} +_Bool ne_float_rc(float a, float _Complex b) { + // X86-LABEL: @ne_float_rc( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} +_Bool ne_float_cc(float _Complex a, float _Complex b) { + // X86-LABEL: @ne_float_cc( + // X86: fcmp une + // X86: fcmp une + // X86: or i1 + // X86: ret + return a != b; +} + +// Check that the libcall will obtain proper calling convention on ARM +_Complex double foo(_Complex double a, _Complex double b) { + // ARM-LABEL: @foo( + // ARM: call arm_aapcscc { double, double } @__muldc3 + return a*b; +} diff --git a/test/CodeGen/complex.c b/test/CodeGen/complex.c index 206db253caa45..1c0e7cb2ee950 100644 --- a/test/CodeGen/complex.c +++ b/test/CodeGen/complex.c @@ -98,3 +98,19 @@ void t8() { const _Complex double test9const = 0; _Complex double test9func() { return test9const; } + +// D6217 +void t91() { + // Check for proper type promotion of conditional expression + char c[(int)(sizeof(typeof((0 ? 2.0f : (_Complex double) 2.0f))) - sizeof(_Complex double))]; + // Check for proper codegen + (0 ? 2.0f : (_Complex double) 2.0f); +} + +void t92() { + // Check for proper type promotion of conditional expression + char c[(int)(sizeof(typeof((0 ? (_Complex double) 2.0f : 2.0f))) - sizeof(_Complex double))]; + // Check for proper codegen + (0 ? (_Complex double) 2.0f : 2.0f); +} + diff --git a/test/CodeGen/compound-assign-overflow.c b/test/CodeGen/compound-assign-overflow.c index 15334294d47e7..f126bb05d53c1 100644 --- a/test/CodeGen/compound-assign-overflow.c +++ b/test/CodeGen/compound-assign-overflow.c @@ -1,5 +1,5 @@ // 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 +// RUN: %clang_cc1 -ffreestanding -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-recover=signed-integer-overflow,unsigned-integer-overflow | FileCheck %s #include <stdint.h> diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c index 7d7ccae370dd9..b86274fc82420 100644 --- a/test/CodeGen/const-init.c +++ b/test/CodeGen/const-init.c @@ -159,3 +159,25 @@ void g29() { static int b[1] = { "asdf" }; // expected-warning {{incompatible pointer to integer conversion initializing 'int' with an expression of type 'char [5]'}} static int c[1] = { L"a" }; } + +// PR21300 +void g30() { +#pragma pack(1) + static struct { + int : 1; + int x; + } a = {}; + // CHECK: @g30.a = internal global %struct.anon.1 <{ i8 undef, i32 0 }>, align 1 +#pragma pack() +} + +void g31() { +#pragma pack(4) + static struct { + short a; + long x; + short z; + } a = {23122, -12312731, -312}; +#pragma pack() + // CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4 +} diff --git a/test/CodeGen/debug-info-args.c b/test/CodeGen/debug-info-args.c index 50b85411adb98..33cf5bcbd06ce 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 ![[NUM:[^,]*]], i32 0, null, null, null} ; [ DW_TAG_subroutine_type - // CHECK: ![[NUM]] = {{metadata !{metadata ![^,]*, metadata ![^,]*, metadata ![^,]*, metadata ![^,]*}}} + // CHECK: ![[NUM:[^,]*]], null, null, null} ; [ DW_TAG_subroutine_type + // CHECK: ![[NUM]] = {{!{![^,]*, ![^,]*, ![^,]*, ![^,]*}}} return y; } diff --git a/test/CodeGen/debug-info-block-decl.c b/test/CodeGen/debug-info-block-decl.c index 06c0e1ad31924..f3f5e6bd0a918 100644 --- a/test/CodeGen/debug-info-block-decl.c +++ b/test/CodeGen/debug-info-block-decl.c @@ -9,8 +9,8 @@ int main() { -// CHECK: [[ASSIGNMENT]] = metadata !{i32 [[@LINE+2]], -// CHECK: [[BLOCK_ENTRY]] = metadata !{i32 [[@LINE+1]], +// CHECK: [[ASSIGNMENT]] = !MDLocation(line: [[@LINE+2]], +// CHECK: [[BLOCK_ENTRY]] = !MDLocation(line: [[@LINE+1]], int (^blockptr)(void) = ^(void) { return 0; }; diff --git a/test/CodeGen/debug-info-block-out-return.c b/test/CodeGen/debug-info-block-out-return.c new file mode 100644 index 0000000000000..47b90ce6882a4 --- /dev/null +++ b/test/CodeGen/debug-info-block-out-return.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -fblocks -emit-llvm -o - %s | FileCheck %s + +// Check that arg numbering is not affected by LLVM IR argument numbering - +// since the latter is affected by return-by-out-parameter ABI requirements + +// 1 for the argument number (1 indexed), 2 for the line number +// 16777218 == 1 << 24 | 2 +// 33554434 == 2 << 24 | 2 +// This explains the two magic numbers below, testing that these two arguments +// are numbered correctly. If they are not numbered correctly they may appear +// out of order or not at all (the latter would occur if they were both assigned +// the same argument number by mistake). + +// CHECK: !"0x101\00.block_descriptor\0016777218\00{{[0-9]+}}", {{.*}} ; [ DW_TAG_arg_variable ] [.block_descriptor] +// CHECK: !"0x101\00param\0033554434\00{{[0-9]+}}", {{.*}} ; [ DW_TAG_arg_variable ] [param] + +// Line directive so we don't have to worry about how many lines preceed the +// test code (as the line number is mangled in with the argument number as shown +// above) +#line 1 +typedef struct { int array[12]; } BigStruct_t; +BigStruct_t (^a)() = ^(int param) { + BigStruct_t b; + return b; +}; diff --git a/test/CodeGen/debug-info-enum.c b/test/CodeGen/debug-info-enum.c index acf3f524088b6..1f6b384d85271 100644 --- a/test/CodeGen/debug-info-enum.c +++ b/test/CodeGen/debug-info-enum.c @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -emit-llvm -g %s -o - | FileCheck %s -// CHECK: metadata [[TEST3_ENUMS:![0-9]*]], {{[^,]*}}, null, null, null} ; [ DW_TAG_enumeration_type ] [e] -// CHECK: [[TEST3_ENUMS]] = metadata !{metadata [[TEST3_E:![0-9]*]]} -// CHECK: [[TEST3_E]] = {{.*}}, metadata !"E", i64 -1} ; [ DW_TAG_enumerator ] [E :: -1] +// CHECK: [[TEST3_ENUMS:![0-9]*]], null, null, null} ; [ DW_TAG_enumeration_type ] [e] +// CHECK: [[TEST3_ENUMS]] = !{[[TEST3_E:![0-9]*]]} +// CHECK: [[TEST3_E]] = !{!"0x28\00E\00-1"} ; [ DW_TAG_enumerator ] [E :: -1] enum e; void func(enum e *p) { diff --git a/test/CodeGen/debug-info-line3.c b/test/CodeGen/debug-info-line3.c index d01b023b82d3f..d2efcf724094e 100644 --- a/test/CodeGen/debug-info-line3.c +++ b/test/CodeGen/debug-info-line3.c @@ -13,4 +13,4 @@ void func(char c, char* d) } // CHECK: ret void, !dbg [[LINE:.*]] -// CHECK: [[LINE]] = metadata !{i32 6, +// CHECK: [[LINE]] = !MDLocation(line: 6, diff --git a/test/CodeGen/debug-info-line4.c b/test/CodeGen/debug-info-line4.c index 004176c7a507e..2b3e0fe5bc655 100644 --- a/test/CodeGen/debug-info-line4.c +++ b/test/CodeGen/debug-info-line4.c @@ -8,4 +8,4 @@ int foo(int a, int b) { int c = a + b; } // Without column information we wouldn't change locations for b. -// CHECK: metadata !{i32 4, i32 20, +// CHECK: !MDLocation(line: 4, column: 20, diff --git a/test/CodeGen/debug-info-scope-file.c b/test/CodeGen/debug-info-scope-file.c index 3479ade7a329b..226fb27021eba 100644 --- a/test/CodeGen/debug-info-scope-file.c +++ b/test/CodeGen/debug-info-scope-file.c @@ -7,8 +7,8 @@ // CHECK: ret void, !dbg [[F2_LINE:![0-9]*]] // CHECK: [[F1:![0-9]*]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [f1] // CHECK: [[F2:![0-9]*]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [def] [f2] -// CHECK: [[F1_LINE]] = {{.*}}, metadata [[F1]], null} -// CHECK: [[F2_LINE]] = {{.*}}, metadata [[F2]], null} +// CHECK: [[F1_LINE]] = !MDLocation({{.*}}, scope: [[F1]]) +// CHECK: [[F2_LINE]] = !MDLocation({{.*}}, scope: [[F2]]) void f1() { } diff --git a/test/CodeGen/debug-info-scope.c b/test/CodeGen/debug-info-scope.c index 9decaeafd50ea..d84fafd018d24 100644 --- a/test/CodeGen/debug-info-scope.c +++ b/test/CodeGen/debug-info-scope.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -g -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -gline-tables-only -emit-llvm < %s | FileCheck --check-prefix=GMLT %s // Two variables with same name in separate scope. // Radar 8330217. int main() { @@ -6,10 +7,21 @@ int main() { int k = 0; // CHECK: DW_TAG_auto_variable ] [i] // CHECK-NEXT: DW_TAG_lexical_block + +// FIXME: Looks like we don't actually need both these lexical blocks (disc 2 +// just refers to disc 1, nothing actually uses disc 2). +// GMLT-NOT: DW_TAG_lexical_block +// GMLT: "0xb\002", {{.*}}} ; [ DW_TAG_lexical_block ] +// GMLT-NOT: DW_TAG_lexical_block +// GMLT: "0xb\001", {{.*}}} ; [ DW_TAG_lexical_block ] +// Make sure we don't have any more lexical blocks because we don't need them in +// -gmlt. +// GMLT-NOT: DW_TAG_lexical_block for (int i = 0; i < 10; i++) j++; // CHECK: DW_TAG_auto_variable ] [i] // CHECK-NEXT: DW_TAG_lexical_block +// GMLT-NOT: DW_TAG_lexical_block for (int i = 0; i < 10; i++) k++; return 0; diff --git a/test/CodeGen/debug-info-typedef.c b/test/CodeGen/debug-info-typedef.c index 51ebcc4d8749c..3db7d537890be 100644 --- a/test/CodeGen/debug-info-typedef.c +++ b/test/CodeGen/debug-info-typedef.c @@ -7,5 +7,5 @@ typedef int MyType; MyType a; -// CHECK: metadata ![[HEADER:[0-9]+]], null, metadata !"MyType"{{.*}} ; [ DW_TAG_typedef ] [MyType] [line 2, size 0, align 0, offset 0] [from int] -// CHECK: ![[HEADER]] = metadata !{metadata !"b.h", +// CHECK: !"0x16\00MyType\002\00{{.*}}", ![[HEADER:[0-9]+]], null{{.*}}} ; [ DW_TAG_typedef ] [MyType] [line 2, size 0, align 0, offset 0] [from int] +// CHECK: ![[HEADER]] = !{!"b.h", diff --git a/test/CodeGen/debug-info-version.c b/test/CodeGen/debug-info-version.c index 325345f0b26e0..5fe2e4eb570ba 100644 --- a/test/CodeGen/debug-info-version.c +++ b/test/CodeGen/debug-info-version.c @@ -4,5 +4,5 @@ int main (void) { return 0; } -// CHECK: metadata !{i32 2, metadata !"Debug Info Version", i32 1} -// NO_DEBUG-NOT: metadata !"Debug Info Version" +// CHECK: i32 2, !"Debug Info Version", i32 2} +// NO_DEBUG-NOT: !"Debug Info Version" diff --git a/test/CodeGen/debug-info-vla.c b/test/CodeGen/debug-info-vla.c index 7a8da960db471..ac45dd0a7643b 100644 --- a/test/CodeGen/debug-info-vla.c +++ b/test/CodeGen/debug-info-vla.c @@ -2,7 +2,7 @@ void testVLAwithSize(int s) { -// CHECK: metadata !{i32 {{.*}}, metadata {{.*}}, metadata !"vla", metadata {{.*}}, i32 [[@LINE+1]], metadata {{.*}}, i32 8192, i32 0} ; [ DW_TAG_auto_variable ] [vla] [line [[@LINE+1]]] +// CHECK: !"0x100\00vla\00[[@LINE+1]]\008192", {{.*}}, {{.*}}, {{.*}}} ; [ DW_TAG_auto_variable ] [vla] [line [[@LINE+1]]] int vla[s]; int i; for (i = 0; i < s; i++) { diff --git a/test/CodeGen/debug-info.c b/test/CodeGen/debug-info.c index 12ba6058d39ed..bf08c589809c9 100644 --- a/test/CodeGen/debug-info.c +++ b/test/CodeGen/debug-info.c @@ -42,7 +42,7 @@ struct foo2 foo2; // Radar 7325611 -// CHECK: "barfoo" +// CHECK: !"0x16\00barfoo\00{{.*}}" typedef int barfoo; barfoo foo() { } diff --git a/test/CodeGen/dependent-lib.c b/test/CodeGen/dependent-lib.c index 20913d33f5bea..b3abc2f5bc412 100644 --- a/test/CodeGen/dependent-lib.c +++ b/test/CodeGen/dependent-lib.c @@ -3,13 +3,13 @@ // RUN: %clang_cc1 %s --dependent-lib=msvcrt -triple i686-pc-linux -emit-llvm -o - | FileCheck -check-prefix LINUX %s // CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = metadata !{i32 6, metadata !"Linker Options", metadata ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = metadata !{metadata ![[msvcrt:[0-9]+]]} -// CHECK: ![[msvcrt]] = metadata !{metadata !"/DEFAULTLIB:msvcrt.lib"} +// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} +// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]]} +// CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"} // LINUX: !llvm.module.flags = !{{{.*}}} -// LINUX: !{{[0-9]+}} = metadata !{i32 6, metadata !"Linker Options", metadata ![[link_opts:[0-9]+]]} -// LINUX: ![[link_opts]] = metadata !{metadata ![[msvcrt:[0-9]+]]} -// LINUX: ![[msvcrt]] = metadata !{metadata !"-lmsvcrt"} +// LINUX: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} +// LINUX: ![[link_opts]] = !{![[msvcrt:[0-9]+]]} +// LINUX: ![[msvcrt]] = !{!"-lmsvcrt"} int f(); diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c index b11c67a454213..74532c8fa5b43 100644 --- a/test/CodeGen/designated-initializers.c +++ b/test/CodeGen/designated-initializers.c @@ -139,6 +139,9 @@ union_16644_t union_16644_instance_4[2] = [1].b[1] = 4 }; +// CHECK: @lab = global { [4 x i8], i32 } { [4 x i8] undef, i32 123 } +struct leading_anon_bitfield { int : 32; int n; } lab = { .n = 123 }; + void test1(int argc, char **argv) { // CHECK: internal global %struct.foo { i8* null, i32 1024 } diff --git a/test/CodeGen/dllimport.c b/test/CodeGen/dllimport.c index 32ee81f85924f..89dbb9f3461cd 100644 --- a/test/CodeGen/dllimport.c +++ b/test/CodeGen/dllimport.c @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c11 -O0 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c11 -O0 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c11 -O0 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c11 -O0 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 %s -// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=GNU %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=GNU %s +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=MO1 %s +// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=GO1 %s #define JOIN2(x, y) x##y #define JOIN(x, y) JOIN2(x, y) @@ -44,6 +44,26 @@ __declspec(dllimport) extern int GlobalRedecl3; extern int GlobalRedecl3; // dllimport ignored USEVAR(GlobalRedecl3) +// Make sure this works even if the decl has been used before it's defined (PR20792). +// CHECK: @GlobalRedecl4 = common global i32 +__declspec(dllimport) extern int GlobalRedecl4; +USEVAR(GlobalRedecl4) + int GlobalRedecl4; // dllimport ignored + +// FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR02803). +// CHECK: @GlobalRedecl5 = external dllimport global i32 +__declspec(dllimport) extern int GlobalRedecl5; +USEVAR(GlobalRedecl5) + extern int GlobalRedecl5; // dllimport ignored + +// Redeclaration in local context. +// CHECK: @GlobalRedecl6 = external dllimport global i32 +__declspec(dllimport) int GlobalRedecl6; +int functionScope() { + extern int GlobalRedecl6; // still dllimport + return GlobalRedecl6; +} + //===----------------------------------------------------------------------===// @@ -59,14 +79,18 @@ __declspec(dllimport) void decl(void); void (*use_decl)(void) = &decl; // Import inline function. -// CHECK-DAG: declare dllimport void @inlineFunc() -// O1-DAG: define available_externally dllimport void @inlineFunc() +// MS-DAG: declare dllimport void @inlineFunc() +// MO1-DAG: define available_externally dllimport void @inlineFunc() +// GNU-DAG: declare void @inlineFunc() +// GO1-DAG: define available_externally void @inlineFunc() __declspec(dllimport) inline void inlineFunc(void) {} USE(inlineFunc) // inline attributes -// CHECK-DAG: declare dllimport void @noinline() -// O1-DAG: define available_externally dllimport void @noinline() +// MS-DAG: declare dllimport void @noinline() +// MO1-DAG: define available_externally dllimport void @noinline() +// GNU-DAG: declare void @noinline() +// GO1-DAG: define available_externally void @noinline() // CHECK-NOT: @alwaysInline() // O1-NOT: @alwaysInline() __declspec(dllimport) __attribute__((noinline)) inline void noinline(void) {} @@ -91,3 +115,15 @@ USE(redecl2) __declspec(dllimport) void redecl3(void); void redecl3(void) {} // dllimport ignored USE(redecl3) + +// Make sure this works even if the decl is used before it's defined (PR20792). +// CHECK-DAG: define void @redecl4() +__declspec(dllimport) void redecl4(void); +USE(redecl4) + void redecl4(void) {} // dllimport ignored + +// FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR20803). +// CHECK-DAG: declare dllimport +__declspec(dllimport) void redecl5(void); +USE(redecl5) + void redecl5(void); // dllimport ignored diff --git a/test/CodeGen/dwarf-version.c b/test/CodeGen/dwarf-version.c index 0c67b4f86eb5b..cb95f28bc735e 100644 --- a/test/CodeGen/dwarf-version.c +++ b/test/CodeGen/dwarf-version.c @@ -5,10 +5,11 @@ // RUN: %clang -target x86_64-apple-darwin -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2 // RUN: %clang -target powerpc-unknown-openbsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2 // RUN: %clang -target powerpc-unknown-freebsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2 +// RUN: %clang -target i386-pc-solaris -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2 int main (void) { return 0; } -// VER2: metadata !{i32 2, metadata !"Dwarf Version", i32 2} -// VER3: metadata !{i32 2, metadata !"Dwarf Version", i32 3} -// VER4: metadata !{i32 2, metadata !"Dwarf Version", i32 4} +// VER2: !{i32 2, !"Dwarf Version", i32 2} +// VER3: !{i32 2, !"Dwarf Version", i32 3} +// VER4: !{i32 2, !"Dwarf Version", i32 4} diff --git a/test/CodeGen/ext-vector-indexing.c b/test/CodeGen/ext-vector-indexing.c new file mode 100644 index 0000000000000..28c0e1e9e25a1 --- /dev/null +++ b/test/CodeGen/ext-vector-indexing.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s + +typedef __attribute__(( ext_vector_type(4) )) float float4; +// CHECK: @test +void test() +{ + float4 va; + va.hi[0] = 3.0; +// CHECK: [[VA:%.*]] = alloca <4 x float> +// CHECK: [[CONV:%.*]] = bitcast <4 x float>* [[VA]] to float* +// CHECK: [[ADD:%.*]] = getelementptr inbounds float* [[CONV]], i64 2 +// CHECK: [[ARRIDX:%.*]] = getelementptr inbounds float* [[ADD]], i64 0 +// CHECK: store float 3.000000e+00, float* [[ARRIDX]] +} diff --git a/test/CodeGen/fp128_complex.c b/test/CodeGen/fp128_complex.c new file mode 100644 index 0000000000000..8775999329518 --- /dev/null +++ b/test/CodeGen/fp128_complex.c @@ -0,0 +1,9 @@ +// RUN: %clang -target aarch64-linux-gnuabi %s -O3 -S -emit-llvm -o - | FileCheck %s + +_Complex long double a, b, c, d; +void test_fp128_compound_assign(void) { + // CHECK: tail call { fp128, fp128 } @__multc3 + a *= b; + // CHECK: tail call { fp128, fp128 } @__divtc3 + c /= d; +} diff --git a/test/CodeGen/fsgsbase-builtins.c b/test/CodeGen/fsgsbase-builtins.c new file mode 100644 index 0000000000000..14c51a9945f84 --- /dev/null +++ b/test/CodeGen/fsgsbase-builtins.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 %s -O3 -triple=x86_64-apple-darwin -target-feature +fsgsbase -emit-llvm -o - | FileCheck %s + +// Don't include mm_malloc.h, it's system specific. +#define __MM_MALLOC_H + +#include <x86intrin.h> + +unsigned int test_readfsbase_u32() +{ + // CHECK: @llvm.x86.rdfsbase.32 + return _readfsbase_u32(); +} + +unsigned long long test_readfsbase_u64() +{ + // CHECK: @llvm.x86.rdfsbase.64 + return _readfsbase_u64(); +} + +unsigned int test_readgsbase_u32() +{ + // CHECK: @llvm.x86.rdgsbase.32 + return _readgsbase_u32(); +} + +unsigned long long test_readgsbase_u64() +{ + // CHECK: @llvm.x86.rdgsbase.64 + return _readgsbase_u64(); +} + +void test_writefsbase_u32(unsigned int __X) +{ + // CHECK: @llvm.x86.wrfsbase.32 + _writefsbase_u32(__X); +} + +void test_writefsbase_u64(unsigned long long __X) +{ + // CHECK: @llvm.x86.wrfsbase.64 + _writefsbase_u64(__X); +} + +void test_writegsbase_u32(unsigned int __X) +{ + // CHECK: @llvm.x86.wrgsbase.32 + _writegsbase_u32(__X); +} + +void test_writegsbase_u64(unsigned long long __X) +{ + // CHECK: @llvm.x86.wrgsbase.64 + _writegsbase_u64(__X); +} diff --git a/test/CodeGen/lineno-dbginfo.c b/test/CodeGen/lineno-dbginfo.c index 1f9b7a569eceb..28c72438f5426 100644 --- a/test/CodeGen/lineno-dbginfo.c +++ b/test/CodeGen/lineno-dbginfo.c @@ -1,5 +1,6 @@ // RUN: echo "#include <stddef.h>" > %t.h -// RUN: %clang_cc1 -S -g -include %t.h %s -emit-llvm -o %t.ll -// RUN: grep "i32 5" %t.ll -// outer is at line number 5. +// RUN: %clang_cc1 -S -g -include %t.h %s -emit-llvm -o - | FileCheck %s + +// CHECK: !"0x34\00outer\00outer\00\00[[@LINE+1]]\000\001" int outer = 42; + diff --git a/test/CodeGen/linetable-endscope.c b/test/CodeGen/linetable-endscope.c index 236f605d7efaf..9a737cf79655c 100644 --- a/test/CodeGen/linetable-endscope.c +++ b/test/CodeGen/linetable-endscope.c @@ -11,7 +11,7 @@ void foo(char c) { int i; - // CHECK: ![[CONV]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[CONV]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) i = c; - // CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + // CHECK: ![[RET]] = !MDLocation(line: [[@LINE+1]], scope: !{{.*}}) } diff --git a/test/CodeGen/link-bitcode-file.c b/test/CodeGen/link-bitcode-file.c index cf9493f988ae7..fb97b4d1f5857 100644 --- a/test/CodeGen/link-bitcode-file.c +++ b/test/CodeGen/link-bitcode-file.c @@ -6,7 +6,7 @@ int f(void); #ifdef BITCODE -// CHECK-BC: 'f': symbol multiply defined +// CHECK-BC: fatal error: cannot link module {{.*}}'f': symbol multiply defined int f(void) { return 42; } diff --git a/test/CodeGen/lzcnt-builtins.c b/test/CodeGen/lzcnt-builtins.c index a43c4eede4521..a083de9d35f0a 100644 --- a/test/CodeGen/lzcnt-builtins.c +++ b/test/CodeGen/lzcnt-builtins.c @@ -22,3 +22,15 @@ unsigned long long test__lzcnt64(unsigned long long __X) // CHECK: @llvm.ctlz.i64 return __lzcnt64(__X); } + +unsigned int test_lzcnt_u32(unsigned int __X) +{ + // CHECK: @llvm.ctlz.i32 + return _lzcnt_u32(__X); +} + +unsigned long long test__lzcnt_u64(unsigned long long __X) +{ + // CHECK: @llvm.ctlz.i64 + return _lzcnt_u64(__X); +} diff --git a/test/CodeGen/mangle-blocks.c b/test/CodeGen/mangle-blocks.c new file mode 100644 index 0000000000000..c5e08e9dd5b11 --- /dev/null +++ b/test/CodeGen/mangle-blocks.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple i386-apple-ios -fblocks -emit-llvm -o - %s | FileCheck %s + +void __assert_rtn(const char *, const char *, int, const char *) + __attribute__ (( noreturn )); + +void (^mangle(void))(void) { + return ^{ + void (^block)(void) = ^{ + __assert_rtn(__func__, __FILE__, __LINE__, "mangle"); + }; + }; +} + +// CHECK: @__func__.__mangle_block_invoke_2 = private unnamed_addr constant [24 x i8] c"__mangle_block_invoke_2\00", align 1 +// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1 +// CHECK: @.str1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1 + +// CHECK: define internal void @__mangle_block_invoke(i8* %.block_descriptor) + +// CHECK: define internal void @__mangle_block_invoke_2(i8* %.block_descriptor){{.*}}{ +// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([24 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 9, i8* getelementptr inbounds ([7 x i8]* @.str1, i32 0, i32 0)) +// CHECK: } + diff --git a/test/CodeGen/mangle-windows.c b/test/CodeGen/mangle-windows.c index 37d1018283589..4a108751aa4b5 100644 --- a/test/CodeGen/mangle-windows.c +++ b/test/CodeGen/mangle-windows.c @@ -1,33 +1,68 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-mingw32 | FileCheck %s --check-prefix=X64 void __stdcall f1(void) {} // CHECK: define x86_stdcallcc void @"\01_f1@0" +// X64: define void @f1( void __fastcall f2(void) {} // CHECK: define x86_fastcallcc void @"\01@f2@0" +// X64: define void @f2( void __stdcall f3() {} // CHECK: define x86_stdcallcc void @"\01_f3@0" +// X64: define void @f3( void __fastcall f4(char a) {} // CHECK: define x86_fastcallcc void @"\01@f4@4" +// X64: define void @f4( void __fastcall f5(short a) {} // CHECK: define x86_fastcallcc void @"\01@f5@4" +// X64: define void @f5( void __fastcall f6(int a) {} // CHECK: define x86_fastcallcc void @"\01@f6@4" +// X64: define void @f6( void __fastcall f7(long a) {} // CHECK: define x86_fastcallcc void @"\01@f7@4" +// X64: define void @f7( void __fastcall f8(long long a) {} // CHECK: define x86_fastcallcc void @"\01@f8@8" +// X64: define void @f8( void __fastcall f9(long long a, char b, char c, short d) {} -// CHECK: define x86_fastcallcc void @"\01@f9@20"(i64 %a, i8 signext %b, i8 -// signext %c, i16 signext %d) +// CHECK: define x86_fastcallcc void @"\01@f9@20"(i64 %a, i8 signext %b, i8 signext %c, i16 signext %d) +// X64: define void @f9( void f12(void) {} // CHECK: define void @f12( +// X64: define void @f12( + +void __vectorcall v1(void) {} +// CHECK: define x86_vectorcallcc void @"\01v1@@0"( +// X64: define x86_vectorcallcc void @"\01v1@@0"( + +void __vectorcall v2(char a) {} +// CHECK: define x86_vectorcallcc void @"\01v2@@4"( +// X64: define x86_vectorcallcc void @"\01v2@@8"( + +void __vectorcall v3(short a) {} +// CHECK: define x86_vectorcallcc void @"\01v3@@4"( +// X64: define x86_vectorcallcc void @"\01v3@@8"( + +void __vectorcall v4(int a) {} +// CHECK: define x86_vectorcallcc void @"\01v4@@4"( +// X64: define x86_vectorcallcc void @"\01v4@@8"( + +void __vectorcall v5(long long a) {} +// CHECK: define x86_vectorcallcc void @"\01v5@@8"( +// X64: define x86_vectorcallcc void @"\01v5@@8"( + +void __vectorcall v6(char a, char b) {} +// CHECK: define x86_vectorcallcc void @"\01v6@@8"( +// X64: define x86_vectorcallcc void @"\01v6@@16"( diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c index 4d6f721f6abb4..520b7abea6c17 100644 --- a/test/CodeGen/may-alias.c +++ b/test/CodeGen/may-alias.c @@ -27,16 +27,16 @@ void test1(struct Test1MA *p1, struct Test1 *p2) { // PATH: store i32 3, i32* {{%.*}}, !tbaa [[TAG_test1_x:!.*]] p2->x = 3; } -// CHECK: metadata !{metadata !"any pointer", metadata [[TYPE_CHAR:!.*]], -// CHECK: [[TYPE_CHAR]] = metadata !{metadata !"omnipotent char", metadata [[TAG_CXX_TBAA:!.*]], -// CHECK: [[TAG_CXX_TBAA]] = metadata !{metadata !"Simple C/C++ TBAA"} -// CHECK: [[TAG_CHAR]] = metadata !{metadata [[TYPE_CHAR]], metadata [[TYPE_CHAR]], i64 0} -// CHECK: [[TAG_INT]] = metadata !{metadata [[TYPE_INT:!.*]], metadata [[TYPE_INT]], i64 0} -// CHECK: [[TYPE_INT]] = metadata !{metadata !"int", metadata [[TYPE_CHAR]] +// CHECK: !"any pointer", [[TYPE_CHAR:!.*]], +// CHECK: [[TYPE_CHAR]] = !{!"omnipotent char", [[TAG_CXX_TBAA:!.*]], +// CHECK: [[TAG_CXX_TBAA]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TAG_CHAR]] = !{[[TYPE_CHAR]], [[TYPE_CHAR]], i64 0} +// CHECK: [[TAG_INT]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} +// CHECK: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]] -// PATH: [[TYPE_CHAR:!.*]] = metadata !{metadata !"omnipotent char", metadata !{{.*}} -// PATH: [[TAG_CHAR]] = metadata !{metadata [[TYPE_CHAR]], metadata [[TYPE_CHAR]], i64 0} -// PATH: [[TAG_INT]] = metadata !{metadata [[TYPE_INT:!.*]], metadata [[TYPE_INT]], i64 0} -// PATH: [[TYPE_INT]] = metadata !{metadata !"int", metadata [[TYPE_CHAR]] -// PATH: [[TAG_test1_x]] = metadata !{metadata [[TYPE_test1:!.*]], metadata [[TYPE_INT]], i64 0} -// PATH: [[TYPE_test1]] = metadata !{metadata !"Test1", metadata [[TYPE_INT]], i64 0} +// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", !{{.*}} +// PATH: [[TAG_CHAR]] = !{[[TYPE_CHAR]], [[TYPE_CHAR]], i64 0} +// PATH: [[TAG_INT]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} +// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]] +// PATH: [[TAG_test1_x]] = !{[[TYPE_test1:!.*]], [[TYPE_INT]], i64 0} +// PATH: [[TYPE_test1]] = !{!"Test1", [[TYPE_INT]], i64 0} diff --git a/test/CodeGen/merge-statics.c b/test/CodeGen/merge-statics.c index 6716935c4d122..4baf902488c53 100644 --- a/test/CodeGen/merge-statics.c +++ b/test/CodeGen/merge-statics.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 < %s -emit-llvm | grep internal | count 1 +// RUN: %clang_cc1 < %s -emit-llvm | FileCheck %s // The two decls for 'a' should merge into one llvm GlobalVariable. @@ -11,3 +11,6 @@ static struct s a = { 10 }; +// CHECK-NOT: internal global +// CHECK: @a = internal global %struct.s { i32 10 } +// CHECK-NOT: internal-global diff --git a/test/CodeGen/microsoft-call-conv.c b/test/CodeGen/microsoft-call-conv.c index b80c58dfd1f21..c24db1296f129 100644 --- a/test/CodeGen/microsoft-call-conv.c +++ b/test/CodeGen/microsoft-call-conv.c @@ -20,6 +20,11 @@ void __thiscall f6(void) { f3(); // CHECK: call x86_thiscallcc void @f3() } +void __vectorcall f61(void) { +// CHECK-LABEL: define x86_vectorcallcc void @f61() + f3(); +// CHECK: call x86_thiscallcc void @f3() +} // PR5280 void (__fastcall *pf1)(void) = f1; @@ -28,19 +33,22 @@ void (__thiscall *pf3)(void) = f3; void (__fastcall *pf4)(void) = f4; void (__stdcall *pf5)(void) = f5; void (__thiscall *pf6)(void) = f6; +void (__vectorcall *pf7)(void) = f61; int main(void) { - f4(); f5(); f6(); + f4(); f5(); f6(); f61(); // CHECK: call x86_fastcallcc void @f4() // CHECK: call x86_stdcallcc void @f5() // CHECK: call x86_thiscallcc void @f6() - pf1(); pf2(); pf3(); pf4(); pf5(); pf6(); + // CHECK: call x86_vectorcallcc void @f61() + pf1(); pf2(); pf3(); pf4(); pf5(); pf6(); pf7(); // CHECK: call x86_fastcallcc void %{{.*}}() // CHECK: call x86_stdcallcc void %{{.*}}() // CHECK: call x86_thiscallcc void %{{.*}}() // CHECK: call x86_fastcallcc void %{{.*}}() // CHECK: call x86_stdcallcc void %{{.*}}() // CHECK: call x86_thiscallcc void %{{.*}}() + // CHECK: call x86_vectorcallcc void %{{.*}}() return 0; } diff --git a/test/CodeGen/mips-constraint-regs.c b/test/CodeGen/mips-constraint-regs.c index 0d533f5fc7712..4dfd62ddbfcf7 100644 --- a/test/CodeGen/mips-constraint-regs.c +++ b/test/CodeGen/mips-constraint-regs.c @@ -9,7 +9,7 @@ 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]+}}) [[NUW:#[0-9]+]], !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "addi $0,$1,$2 \0A\09\09", "=c,c,I,~{$1}"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) [[NUW:#[0-9]+]], !srcloc !{{[0-9]+}} int __s, __v = 17; int __t; __asm__ __volatile__( @@ -20,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]+}}) [[NUW]], !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "mtlo $1 \0A\09\09", "=l,r,~{lo},~{$1}"(i32 %{{[0-9]+}}) [[NUW]], !srcloc !{{[0-9]+}} int i_temp = 44; int i_result; __asm__ __volatile__( @@ -32,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]+}}) [[NUW]], !srcloc !{{[0-9]+}} + // CHECK: %{{[0-9]+}} = call i64 asm sideeffect "mthi $1 \0A\09\09mtlo $2 \0A\09\09", "=x,r,r,~{$1}"(i32 %{{[0-9]+}}, i32 %{{[0-9]+}}) [[NUW]], !srcloc !{{[0-9]+}} int i_hi = 3; int i_lo = 2; long long ll_result = 0; diff --git a/test/CodeGen/mips-constraints-mem.c b/test/CodeGen/mips-constraints-mem.c index 2c3c01ac11e2f..295d67cadf0a7 100644 --- a/test/CodeGen/mips-constraints-mem.c +++ b/test/CodeGen/mips-constraints-mem.c @@ -9,7 +9,7 @@ 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, + // CHECK: %{{[0-9]+}} = call i32 asm sideeffect "lwl $0, 1 + $1\0A\09lwr $0, 2 + $1\0A\09", "=r,*R,~{$1}"(i32* %{{[0-9,a-f]+}}) #1, int c = 0xffbbccdd; diff --git a/test/CodeGen/mips-inline-asm-modifiers.c b/test/CodeGen/mips-inline-asm-modifiers.c index 9d697e8b228e9..9437dbe5abe57 100644 --- a/test/CodeGen/mips-inline-asm-modifiers.c +++ b/test/CodeGen/mips-inline-asm-modifiers.c @@ -7,9 +7,9 @@ int printf(const char*, ...); typedef int v4i32 __attribute__((vector_size(16))); - // CHECK: %{{[0-9]+}} = call i32 asm ".set noreorder;\0Alw $0,$1;\0A.set reorder;\0A", "=r,*m"(i32* getelementptr inbounds ([8 x i32]* @b, i32 {{[0-9]+}}, i32 {{[0-9]+}})) #2, - // CHECK: %{{[0-9]+}} = call i32 asm "lw $0,${1:D};\0A", "=r,*m"(i32* getelementptr inbounds ([8 x i32]* @b, i32 {{[0-9]+}}, i32 {{[0-9]+}})) #2, - // CHECK: %{{[0-9]+}} = call <4 x i32> asm "ldi.w ${0:w},1", "=f" + // CHECK: %{{[0-9]+}} = call i32 asm ".set noreorder;\0Alw $0,$1;\0A.set reorder;\0A", "=r,*m,~{$1}"(i32* getelementptr inbounds ([8 x i32]* @b, i32 {{[0-9]+}}, i32 {{[0-9]+}})) #2, + // CHECK: %{{[0-9]+}} = call i32 asm "lw $0,${1:D};\0A", "=r,*m,~{$1}"(i32* getelementptr inbounds ([8 x i32]* @b, i32 {{[0-9]+}}, i32 {{[0-9]+}})) #2, + // CHECK: %{{[0-9]+}} = call <4 x i32> asm "ldi.w ${0:w},1", "=f,~{$1}" int b[8] = {0,1,2,3,4,5,6,7}; int main() { diff --git a/test/CodeGen/mips-transparent-union.c b/test/CodeGen/mips-transparent-union.c new file mode 100644 index 0000000000000..ad417dd9f5da4 --- /dev/null +++ b/test/CodeGen/mips-transparent-union.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple mips64-linux-gnu -S -o - -emit-llvm %s | FileCheck %s +// +// Transparent unions are passed according to the calling convention rules of +// the first member. In this case, it is as if it were a void pointer so we +// do not have the inreg attribute we would normally have for unions. +// +// This comes up in glibc's wait() function and matters for the big-endian N32 +// case where pointers are promoted to i64 and a non-transparent union would be +// passed in the upper 32-bits of an i64. + +union either_pointer { + void *void_ptr; + int *int_ptr; +} __attribute__((transparent_union)); + +extern void foo(union either_pointer p); + +int data; + +void bar(void) { + return foo(&data); +} + +// CHECK-LABEL: define void @bar() +// CHECK: call void @foo(i8* %{{[0-9]+}}) + +// CHECK: declare void @foo(i8*) diff --git a/test/CodeGen/mips-varargs.c b/test/CodeGen/mips-varargs.c index ad202ff85bf0b..383831f2e824d 100644 --- a/test/CodeGen/mips-varargs.c +++ b/test/CodeGen/mips-varargs.c @@ -28,18 +28,19 @@ int test_i32(char *fmt, ...) { // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* // ALL: call void @llvm.va_start(i8* [[VA1]]) // -// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] -// -// O32: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i32* -// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// O32: [[TMP0:%.+]] = bitcast i8** %va to i32** +// O32: [[AP_CUR:%.+]] = load i32** [[TMP0]], align [[PTRALIGN]] +// NEW: [[TMP0:%.+]] = bitcast i8** %va to i64** +// NEW: [[AP_CUR:%.+]] = load i64** [[TMP0]], align [[PTRALIGN]] // -// O32: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], i32 4 -// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], {{i32|i64}} 8 +// O32: [[AP_NEXT:%.+]] = getelementptr i32* [[AP_CUR]], i32 1 +// NEW: [[AP_NEXT:%.+]] = getelementptr i64* [[AP_CUR]], {{i32|i64}} 1 // -// ALL: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// O32: store i32* [[AP_NEXT]], i32** [[TMP0]], align [[PTRALIGN]] +// NEW: store i64* [[AP_NEXT]], i64** [[TMP0]], align [[PTRALIGN]] // -// O32: [[ARG1:%.+]] = load i32* [[TMP0]], align 4 -// NEW: [[TMP2:%.+]] = load i64* [[TMP0]], align 8 +// O32: [[ARG1:%.+]] = load i32* [[AP_CUR]], align 4 +// NEW: [[TMP2:%.+]] = load i64* [[AP_CUR]], align 8 // NEW: [[ARG1:%.+]] = trunc i64 [[TMP2]] to i32 // // ALL: call void @llvm.va_end(i8* [[VA1]]) @@ -63,32 +64,30 @@ int test_i32_2args(char *fmt, ...) { // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* // ALL: call void @llvm.va_start(i8* [[VA1]]) // -// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] -// -// O32: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i32* -// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// O32: [[TMP0:%.+]] = bitcast i8** %va to i32** +// O32: [[AP_CUR:%.+]] = load i32** [[TMP0]], align [[PTRALIGN]] +// NEW: [[TMP0:%.+]] = bitcast i8** %va to i64** +// NEW: [[AP_CUR:%.+]] = load i64** [[TMP0]], align [[PTRALIGN]] // -// O32: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], i32 4 -// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T:i32|i64]] 8 +// O32: [[AP_NEXT1:%.+]] = getelementptr i32* [[AP_CUR]], i32 1 +// NEW: [[AP_NEXT1:%.+]] = getelementptr i64* [[AP_CUR]], [[INTPTR_T:i32|i64]] 1 // -// O32: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// O32: store i32* [[AP_NEXT1]], i32** [[TMP0]], align [[PTRALIGN]] // FIXME: N32 optimised this store out. Why only for this ABI? -// N64: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// N64: store i64* [[AP_NEXT1]], i64** [[TMP0]], align [[PTRALIGN]] // -// O32: [[ARG1:%.+]] = load i32* [[TMP0]], align 4 -// NEW: [[TMP3:%.+]] = load i64* [[TMP0]], align 8 +// O32: [[ARG1:%.+]] = load i32* [[AP_CUR]], align 4 +// NEW: [[TMP3:%.+]] = load i64* [[AP_CUR]], align 8 // NEW: [[ARG1:%.+]] = trunc i64 [[TMP3]] to i32 // -// O32: [[TMP1:%.+]] = bitcast i8* [[AP_NEXT]] to i32* -// NEW: [[TMP1:%.+]] = bitcast i8* [[AP_NEXT]] to i64* +// O32: [[AP_NEXT2:%.+]] = getelementptr i32* [[AP_CUR]], i32 2 +// NEW: [[AP_NEXT2:%.+]] = getelementptr i64* [[AP_CUR]], [[INTPTR_T]] 2 // -// O32: [[AP_NEXT3:%.+]] = getelementptr i8* [[AP_CUR]], i32 8 -// NEW: [[AP_NEXT3:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T]] 16 +// O32: store i32* [[AP_NEXT2]], i32** [[TMP0]], align [[PTRALIGN]] +// NEW: store i64* [[AP_NEXT2]], i64** [[TMP0]], align [[PTRALIGN]] // -// ALL: store i8* [[AP_NEXT3]], i8** %va, align [[PTRALIGN]] -// -// O32: [[ARG2:%.+]] = load i32* [[TMP1]], align 4 -// NEW: [[TMP4:%.+]] = load i64* [[TMP1]], align 8 +// O32: [[ARG2:%.+]] = load i32* [[AP_NEXT1]], align 4 +// NEW: [[TMP4:%.+]] = load i64* [[AP_NEXT1]], align 8 // NEW: [[ARG2:%.+]] = trunc i64 [[TMP4]] to i32 // // ALL: call void @llvm.va_end(i8* [[VA1]]) @@ -112,9 +111,9 @@ long long test_i64(char *fmt, ...) { // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* // ALL: call void @llvm.va_start(i8* [[VA1]]) // -// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] -// -// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// O32: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] +// NEW: [[TMP0:%.+]] = bitcast i8** %va to i64** +// NEW: [[AP_CUR:%.+]] = load i64** [[TMP0]], align [[PTRALIGN]] // // i64 is 8-byte aligned, while this is within O32's stack alignment there's no // guarantee that the offset is still 8-byte aligned after earlier reads. @@ -125,17 +124,67 @@ long long test_i64(char *fmt, ...) { // O32: [[PTR4:%.+]] = inttoptr [[INTPTR_T]] [[PTR2]] to i8* // // O32: [[AP_NEXT:%.+]] = getelementptr i8* [[PTR4]], [[INTPTR_T]] 8 -// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T]] 8 +// NEW: [[AP_NEXT:%.+]] = getelementptr i64* [[AP_CUR]], [[INTPTR_T:i32|i64]] 1 // -// ALL: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// O32: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// NEW: store i64* [[AP_NEXT]], i64** [[TMP0]], align [[PTRALIGN]] // // O32: [[ARG1:%.+]] = load i64* [[PTR3]], align 8 -// NEW: [[ARG1:%.+]] = load i64* [[TMP0]], align 8 +// NEW: [[ARG1:%.+]] = load i64* [[AP_CUR]], align 8 // // ALL: call void @llvm.va_end(i8* [[VA1]]) // ALL: ret i64 [[ARG1]] // ALL: } +char *test_ptr(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + char *v = va_arg(va, char *); + va_end(va); + + return v; +} + +// ALL-LABEL: define i8* @test_ptr(i8*{{.*}} %fmt, ...) +// +// O32: %va = alloca i8*, align [[PTRALIGN:4]] +// N32: %va = alloca i8*, align [[PTRALIGN:4]] +// N64: %va = alloca i8*, align [[PTRALIGN:8]] +// +// ALL: [[VA1:%.+]] = bitcast i8** %va to i8* +// ALL: call void @llvm.va_start(i8* [[VA1]]) +// +// O32: [[TMP0:%.+]] = bitcast i8** %va to i8*** +// O32: [[AP_CUR:%.+]] = load i8*** [[TMP0]], align [[PTRALIGN]] +// N32 differs because the vararg is not a N32 pointer. It's been promoted to 64-bit. +// N32: [[TMP0:%.+]] = bitcast i8** %va to i64** +// N32: [[AP_CUR:%.+]] = load i64** [[TMP0]], align [[PTRALIGN]] +// N64: [[TMP0:%.+]] = bitcast i8** %va to i8*** +// N64: [[AP_CUR:%.+]] = load i8*** [[TMP0]], align [[PTRALIGN]] +// +// O32: [[AP_NEXT:%.+]] = getelementptr i8** [[AP_CUR]], i32 1 +// N32 differs because the vararg is not a N32 pointer. It's been promoted to 64-bit. +// N32: [[AP_NEXT:%.+]] = getelementptr i64* [[AP_CUR]], {{i32|i64}} 1 +// N64: [[AP_NEXT:%.+]] = getelementptr i8** [[AP_CUR]], {{i32|i64}} 1 +// +// O32: store i8** [[AP_NEXT]], i8*** [[TMP0]], align [[PTRALIGN]] +// N32 differs because the vararg is not a N32 pointer. It's been promoted to 64-bit. +// N32: store i64* [[AP_NEXT]], i64** [[TMP0]], align [[PTRALIGN]] +// N64: store i8** [[AP_NEXT]], i8*** [[TMP0]], align [[PTRALIGN]] +// +// O32: [[ARG1:%.+]] = load i8** [[AP_CUR]], align 4 +// N32 differs because the vararg is not a N32 pointer. It's been promoted to +// 64-bit so we must truncate the excess and bitcast to a N32 pointer. +// N32: [[TMP2:%.+]] = load i64* [[AP_CUR]], align 8 +// N32: [[TMP3:%.+]] = trunc i64 [[TMP2]] to i32 +// N32: [[ARG1:%.+]] = inttoptr i32 [[TMP3]] to i8* +// N64: [[ARG1:%.+]] = load i8** [[AP_CUR]], align 8 +// +// ALL: call void @llvm.va_end(i8* [[VA1]]) +// ALL: ret i8* [[ARG1]] +// ALL: } + int test_v4i32(char *fmt, ...) { va_list va; diff --git a/test/CodeGen/mmx-inline-asm-error.c b/test/CodeGen/mmx-inline-asm-error.c index 876c664e3b570..1e2246176a117 100644 --- a/test/CodeGen/mmx-inline-asm-error.c +++ b/test/CodeGen/mmx-inline-asm-error.c @@ -4,9 +4,9 @@ typedef int vec256 __attribute__((ext_vector_type(8))); vec256 foo(vec256 in) { vec256 out; - asm("something %0" : : "y"(in)); // expected-error {{invalid type 'vec256' (vector of 8 'int' values) in asm input for constraint 'y'}} - asm("something %0" : "=y"(out)); // expected-error {{invalid type 'vec256' (vector of 8 'int' values) in asm input for constraint 'y'}} - asm("something %0, %0" : "+y"(out)); // expected-error {{invalid type 'vec256' (vector of 8 'int' values) in asm input for constraint 'y'}} + asm("something %0" : : "y"(in)); // expected-error {{invalid input size for constraint 'y'}} + asm("something %0" : "=y"(out)); // expected-error {{invalid output size for constraint '=y'}} + asm("something %0, %0" : "+y"(out)); // expected-error {{invalid output size for constraint '+y'}} return out; } diff --git a/test/CodeGen/mozilla-ms-inline-asm.c b/test/CodeGen/mozilla-ms-inline-asm.c index 0f541d70fcddd..b8b7a2d677dd7 100644 --- a/test/CodeGen/mozilla-ms-inline-asm.c +++ b/test/CodeGen/mozilla-ms-inline-asm.c @@ -3,6 +3,8 @@ // Some test cases for MS inline asm support from Mozilla code base. +void invoke_copy_to_stack() {} + void invoke(void* that, unsigned methodIndex, unsigned paramCount, void* params) { @@ -18,24 +20,25 @@ void invoke(void* that, unsigned methodIndex, // CHECK: call void asm sideeffect inteldialect // CHECK: mov edx,dword ptr $1 // CHECK: test edx,edx -// CHECK: jz noparams +// CHECK: jz {{[^_]*}}__MSASMLABEL_.0__noparams +// ^ Can't use {{.*}} here because the matching is greedy. // CHECK: mov eax,edx // CHECK: shl eax,$$3 // CHECK: sub esp,eax // CHECK: mov ecx,esp // CHECK: push dword ptr $0 -// CHECK: call invoke_copy_to_stack -// CHECK: noparams: -// CHECK: mov ecx,dword ptr $2 +// CHECK: call dword ptr $2 +// CHECK: {{.*}}__MSASMLABEL_.0__noparams: +// CHECK: mov ecx,dword ptr $3 // CHECK: push ecx // CHECK: mov edx,[ecx] -// CHECK: mov eax,dword ptr $3 +// CHECK: mov eax,dword ptr $4 // CHECK: call dword ptr[edx+eax*$$4] // CHECK: mov esp,ebp // CHECK: pop ebp // CHECK: ret -// CHECK: "=*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}" -// CHECK: (i8** %8, i32* %7, i8** %5, i32* %6) +// CHECK: "=*m,*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}" +// CHECK: (i8** %8, i32* %7, void (...)* bitcast (void ()* @invoke_copy_to_stack to void (...)*), i8** %5, i32* %6) // CHECK: ret void __asm { mov edx,paramCount diff --git a/test/CodeGen/mrtd.c b/test/CodeGen/mrtd.c index 8fa7cf02cead9..f929d4c26b284 100644 --- a/test/CodeGen/mrtd.c +++ b/test/CodeGen/mrtd.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -mrtd -triple i386-unknown-unknown -std=c89 -emit-llvm -o - %s 2>&1 | FileCheck %s + +// CHECK: mrtd.c:10:3: warning: function with no prototype cannot use the stdcall calling convention void baz(int arg); diff --git a/test/CodeGen/ms-align-tentative.c b/test/CodeGen/ms-align-tentative.c new file mode 100644 index 0000000000000..ccd7616164712 --- /dev/null +++ b/test/CodeGen/ms-align-tentative.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -o - | FileCheck %s + +char __declspec(align(8192)) x; +// CHECK-DAG: @x = global i8 0, align 8192 + +typedef char __declspec(align(8192)) T; +T y; +// CHECK-DAG: @y = global i8 0, align 8192 + +T __declspec(align(8192)) z; +// CHECK-DAG: @z = global i8 0, align 8192 + +int __declspec(align(16)) redef; +int __declspec(align(32)) redef = 8; +// CHECK-DAG: @redef = global i32 8, align 32 diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c index 5dc7787b8fb99..328fc835d3475 100644 --- a/test/CodeGen/ms-declspecs.c +++ b/test/CodeGen/ms-declspecs.c @@ -2,8 +2,8 @@ __declspec(selectany) int x1 = 1; const __declspec(selectany) int x2 = 2; -// CHECK: @x1 = weak_odr global i32 1, align 4 -// CHECK: @x2 = weak_odr constant i32 2, align 4 +// CHECK: @x1 = weak_odr global i32 1, comdat, align 4 +// CHECK: @x2 = weak_odr constant i32 2, comdat, align 4 struct __declspec(align(16)) S { char x; diff --git a/test/CodeGen/ms-inline-asm-functions.c b/test/CodeGen/ms-inline-asm-functions.c new file mode 100644 index 0000000000000..1a6ead9286dff --- /dev/null +++ b/test/CodeGen/ms-inline-asm-functions.c @@ -0,0 +1,60 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i386-pc-windows-msvc -fms-extensions -S -o - | FileCheck %s + +// Yes, this is an assembly test from Clang, because we need to make it all the +// way through code generation to know if our call became a direct, pc-relative +// call or an indirect call through memory. + +int k(int); +__declspec(dllimport) int kimport(int); +int (*kptr)(int); +int (*gptr())(int); + +int foo() { + // CHECK-LABEL: _foo: + int (*r)(int) = gptr(); + + // Simple case: direct call. + __asm call k; + // CHECK: calll _k + + // Marginally harder: indirect calls, via dllimport or function pointer. + __asm call r; + // CHECK: calll *({{.*}}) + __asm call kimport; + // CHECK: calll *({{.*}}) + + // Broken case: Call through a global function pointer. + __asm call kptr; + // CHECK: calll _kptr + // CHECK-FIXME: calll *_kptr +} + +int bar() { + // CHECK-LABEL: _bar: + __asm jmp k; + // CHECK: jmp _k +} + +int baz() { + // CHECK-LABEL: _baz: + __asm mov eax, k; + // CHECK: movl _k, %eax + __asm mov eax, kptr; + // CHECK: movl _kptr, %eax +} + +// Test that this asm blob doesn't require more registers than available. This +// has to be an LLVM code generation test. + +void __declspec(naked) naked() { + __asm pusha + __asm call k + __asm popa + __asm ret + // CHECK-LABEL: _naked: + // CHECK: pushal + // CHECK-NEXT: calll _k + // CHECK-NEXT: popal + // CHECK-NEXT: retl +} diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c index 2c67106941420..59ff2023a4653 100644 --- a/test/CodeGen/ms-inline-asm.c +++ b/test/CodeGen/ms-inline-asm.c @@ -10,9 +10,7 @@ void t1() { void t2() { // CHECK: @t2 -// 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: call void asm sideeffect inteldialect "nop\0A\09nop\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() // CHECK: ret void __asm nop __asm nop @@ -28,8 +26,7 @@ void t3() { void t4(void) { // CHECK: @t4 -// 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: 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 @@ -69,9 +66,7 @@ int t8() { __asm int 4 return 10; // CHECK: t8 -// 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: call i32 asm sideeffect inteldialect "int $$4\0A\09int $$4", "={eax},~{dirflag},~{fpsr},~{flags}"() // CHECK: ret i32 10 } @@ -93,10 +88,11 @@ unsigned t10(void) { } return j; // CHECK: t10 +// CHECK: [[r:%[a-zA-Z0-9]+]] = alloca i32, align 4 // 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* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $2\0A\09mov dword ptr $0, eax", "=*m,={eax},*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}) // CHECK: [[RET:%[a-zA-Z0-9]+]] = load i32* [[J]], align 4 // CHECK: ret i32 [[RET]] } @@ -117,7 +113,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* %{{.*}}) +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $3\0A\09mov dword ptr $0, eax\0A\09mov eax, dword ptr $4\0A\09mov dword ptr $1, eax", "=*m,=*m,={eax},*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t13() { @@ -126,8 +122,7 @@ 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* %{{.*}}) -// CHECK: call void asm sideeffect inteldialect "movzx eax, word ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i16* %{{.*}}) +// CHECK: call void asm sideeffect inteldialect "movzx eax, byte ptr $0\0A\09movzx eax, word ptr $1", "*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i8* %{{.*}}i, i16* %{{.*}}j) } void t14() { @@ -145,14 +140,15 @@ void t14() { int gvar = 10; void t15() { +// CHECK: t15 int lvar = 10; __asm mov eax, lvar ; eax = 10 +// CHECK: mov eax, dword ptr $0 __asm mov eax, offset lvar ; eax = address of lvar +// CHECK: mov eax, $1 __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* %{{.*}}) -// 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* @{{.*}}) +// CHECK: mov eax, $2 +// CHECK: "*m,r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* @{{.*}}) } void t16() { @@ -163,50 +159,52 @@ void t16() { } void t17() { +// CHECK: t17 __asm _emit 0x4A +// CHECK: .byte 0x4A __asm _emit 0x43 +// CHECK: .byte 0x43 __asm _emit 0x4B +// CHECK: .byte 0x4B __asm _EMIT 0x4B -// CHECK: t17 -// 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}"() +// CHECK: .byte 0x4B +// CHECK: "~{dirflag},~{fpsr},~{flags}"() } void t20() { +// CHECK: t20 char bar; int foo; char _bar[2]; int _foo[4]; __asm mov eax, LENGTH foo +// CHECK: mov eax, $$1 __asm mov eax, LENGTH bar +// CHECK: mov eax, $$1 __asm mov eax, LENGTH _foo +// CHECK: mov eax, $$4 __asm mov eax, LENGTH _bar -// CHECK: t20 -// 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}"() +// CHECK: mov eax, $$2 __asm mov eax, TYPE foo +// CHECK: mov eax, $$4 __asm mov eax, TYPE bar +// CHECK: mov eax, $$1 __asm mov eax, TYPE _foo +// CHECK: mov eax, $$4 __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}"() +// CHECK: mov eax, $$1 __asm mov eax, SIZE foo +// CHECK: mov eax, $$4 __asm mov eax, SIZE bar +// CHECK: mov eax, $$1 __asm mov eax, SIZE _foo +// CHECK: mov eax, $$16 __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}"() +// CHECK: mov eax, $$2 +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t21() { @@ -242,45 +240,46 @@ void t23() { the_label: } // CHECK: t23 -// CHECK: call void asm sideeffect inteldialect "the_label:", "~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.0__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) +// CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void ()* @t24_helper) } void t25() { +// CHECK: t25 __asm mov eax, 0ffffffffh +// CHECK: mov eax, $$4294967295 __asm mov eax, 0fh +// CHECK: mov eax, $$15 __asm mov eax, 0a2h +// CHECK: mov eax, $$162 __asm mov eax, 0xa2h +// CHECK: mov eax, $$0xa2h __asm mov eax, 0xa2 -// CHECK: t25 -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967295", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$15", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$162", "~{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}"() +// CHECK: mov eax, $$0xa2 +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t26() { +// CHECK: t26 __asm pushad +// CHECK: pushad __asm mov eax, 0 +// CHECK: mov eax, $$0 __asm __emit 0fh +// CHECK: .byte 0fh __asm __emit 0a2h +// CHECK: .byte 0a2h __asm __EMIT 0a2h +// CHECK: .byte 0a2h __asm popad -// FIXME: These all need to be merged into the same asm blob. -// CHECK: t26 -// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{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", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: popad +// CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() } void t27() { @@ -290,160 +289,171 @@ void t27() { } void t28() { +// CHECK: t28 __asm align 8 +// CHECK: .align 3 __asm align 16; +// CHECK: .align 4 __asm align 128; +// CHECK: .align 7 __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}"() +// CHECK: .align 8 +// CHECK: "~{dirflag},~{fpsr},~{flags}"() } void t29() { +// CHECK: t29 int arr[2] = {0, 0}; int olen = 0, osize = 0, otype = 0; __asm mov olen, LENGTH arr +// CHECK: mov dword ptr $0, $$2 __asm mov osize, SIZE arr +// CHECK: mov dword ptr $1, $$8 __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* %{{.*}}) +// CHECK: mov dword ptr $2, $$4 +// CHECK: "=*m,=*m,=*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } int results[2] = {13, 37}; int *t30() +// CHECK: t30 { int *res; __asm lea edi, results +// CHECK: lea edi, dword ptr $2 __asm mov res, edi +// CHECK: mov dword ptr $0, 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** %{{.*}}) +// CHECK: "=*m,={eax},*m,~{edi},~{dirflag},~{fpsr},~{flags}"(i32** %{{.*}}, [2 x i32]* @{{.*}}) } void t31() { +// CHECK: t31 __asm pushad +// CHECK: pushad __asm popad -// CHECK: t31 -// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "popad", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() +// CHECK: popad +// CHECK: "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() } void t32() { +// CHECK: t32 int i; __asm mov eax, i +// CHECK: mov eax, dword ptr $0 __asm mov eax, dword ptr i +// CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr i +// CHECK: mov ax, word ptr $2 __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* %{{.*}}) +// CHECK: mov al, byte ptr $3 +// CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t33() { +// CHECK: t33 int i; __asm mov eax, [i] +// CHECK: mov eax, dword ptr $0 __asm mov eax, dword ptr [i] +// CHECK: mov eax, dword ptr $1 __asm mov ax, word ptr [i] +// CHECK: mov ax, word ptr $2 __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* %{{.*}}) +// CHECK: mov al, byte ptr $3 +// CHECK: "*m,*m,*m,*m,~{al},~{ax},~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}, i32* %{{.*}}) } void t34() { +// CHECK: t34 __asm prefetchnta 64[eax] +// CHECK: 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}"() +// CHECK: mov eax, dword ptr $$4[eax] +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t35() { +// CHECK: t35 __asm prefetchnta [eax + (200*64)] +// CHECK: prefetchnta [eax + ($$200*$$64)] __asm mov eax, dword ptr [eax + (200*64)] -// CHECK: t35 -// CHECK: call void asm sideeffect inteldialect "prefetchnta [eax + ($$200*$$64)]", "~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr [eax + ($$200*$$64)]", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: mov eax, dword ptr [eax + ($$200*$$64)] +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t36() { - int arr[4]; - __asm mov eax, 4[arr] - __asm mov eax, 4[arr + 4] - __asm mov eax, 8[arr + 4 + 32*2 - 4] - __asm mov eax, 12[4 + arr] - __asm mov eax, 4[4 + arr + 4] - __asm mov eax, 4[64 + arr + (2*32)] - __asm mov eax, 4[64 + arr - 2*32] - __asm mov eax, [arr + 4] - __asm mov eax, [arr + 4 + 32*2 - 4] - __asm mov eax, [4 + arr] - __asm mov eax, [4 + arr + 4] - __asm mov eax, [64 + arr + (2*32)] - __asm mov eax, [64 + arr - 2*32] // CHECK: t36 + int arr[4]; + // Work around PR20368: These should be single line blocks + __asm { mov eax, 4[arr] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4[arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 8[arr + 4 + 32*2 - 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$72$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 12[4 + arr] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$16$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4[4 + arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4[64 + arr + (2*32)] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$132$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4[64 + arr - 2*32] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [arr + 4 + 32*2 - 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$64$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [4 + arr] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$4$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [4 + arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [64 + arr + (2*32)] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$128$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, [64 + arr - 2*32] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } void t37() { +// CHECK: t37 __asm mov eax, 4 + 8 +// CHECK: mov eax, $$12 __asm mov eax, 4 + 8 * 16 +// CHECK: mov eax, $$132 __asm mov eax, -4 + 8 * 16 +// CHECK: mov eax, $$124 __asm mov eax, (4 + 4) * 16 +// CHECK: mov eax, $$128 __asm mov eax, 4 + 8 * -16 +// CHECK: mov eax, $$4294967172 __asm mov eax, 4 + 16 / -8 +// CHECK: mov eax, $$2 __asm mov eax, (16 + 16) / -8 +// CHECK: mov eax, $$4294967292 __asm mov eax, ~15 -// CHECK: t37 -// CHECK: call void asm sideeffect inteldialect "mov eax, $$12", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$132", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$124", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$128", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967172", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967292", "~{eax},~{dirflag},~{fpsr},~{flags}"() -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4294967280", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: mov eax, $$4294967280 +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t38() { - int arr[4]; - __asm mov eax, 4+4[arr] - __asm mov eax, (4+4)[arr + 4] - __asm mov eax, 8*2[arr + 4 + 32*2 - 4] - __asm mov eax, 12+20[4 + arr] - __asm mov eax, 4*16+4[4 + arr + 4] - __asm mov eax, 4*4[64 + arr + (2*32)] - __asm mov eax, 4*(4-2)[64 + arr - 2*32] - __asm mov eax, 32*(4-2)[arr - 2*32] // CHECK: t38 + int arr[4]; + // Work around PR20368: These should be single line blocks + __asm { mov eax, 4+4[arr] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, (4+4)[arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$12$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 8*2[arr + 4 + 32*2 - 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$80$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 12+20[4 + arr] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$36$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4*16+4[4 + arr + 4] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$76$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4*4[64 + arr + (2*32)] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$144$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 4*(4-2)[64 + arr - 2*32] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$8$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) + __asm { mov eax, 32*(4-2)[arr - 2*32] } // CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $$0$0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"([4 x i32]* %{{.*}}) } @@ -459,38 +469,87 @@ typedef struct { } A; void t39() { +// CHECK-LABEL: define void @t39 __asm mov eax, [eax].A.b +// CHECK: mov eax, [eax].4 __asm mov eax, [eax] A.b +// CHECK: mov eax, [eax] .4 __asm mov eax, fs:[0] A.b - // CHECK-LABEL: define void @t39 - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() - // CHECK: call void asm sideeffect inteldialect "mov eax, [eax] .4", "~{eax},~{dirflag},~{fpsr},~{flags}"() - // CHECK: call void asm sideeffect inteldialect "mov eax, fs:[$$0] .4", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: mov eax, fs:[$$0] .4 +// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() } void t40(float a) { +// CHECK-LABEL: define void @t40 int i; __asm fld a +// CHECK: fld dword ptr $1 __asm fistp i - // CHECK-LABEL: define void @t40 - // CHECK: call void asm sideeffect inteldialect "fld dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(float* {{.*}}) - // CHECK: call void asm sideeffect inteldialect "fistp dword ptr $0", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* {{.*}}) +// CHECK: fistp dword ptr $0 +// CHECK: "=*m,*m,~{dirflag},~{fpsr},~{flags}"(i32* %{{.*}}, float* %{{.*}}) } void t41(unsigned short a) { +// CHECK-LABEL: define void @t41(i16 zeroext %a) __asm mov cs, a; +// CHECK: mov cs, word ptr $0 __asm mov ds, a; +// CHECK: mov ds, word ptr $1 __asm mov es, a; +// CHECK: mov es, word ptr $2 __asm mov fs, a; +// CHECK: mov fs, word ptr $3 __asm mov gs, a; +// CHECK: mov gs, word ptr $4 __asm mov ss, a; - // CHECK-LABEL: define void @t41(i16 zeroext %a) - // CHECK: [[T41_A_ADDR:%.+]] = alloca i16 - // CHECK: store i16 %a, i16* [[T41_A_ADDR]] - // CHECK: call void asm sideeffect inteldialect "mov cs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) - // CHECK: call void asm sideeffect inteldialect "mov ds, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) - // CHECK: call void asm sideeffect inteldialect "mov es, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) - // CHECK: call void asm sideeffect inteldialect "mov fs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) - // CHECK: call void asm sideeffect inteldialect "mov gs, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) - // CHECK: call void asm sideeffect inteldialect "mov ss, word ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(i16* [[T41_A_ADDR]]) +// CHECK: mov ss, word ptr $5 +// CHECK: "*m,*m,*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}, i16* {{.*}}) +} + +void call_clobber() { + __asm call t41 + // CHECK-LABEL: define void @call_clobber + // CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void (i16)* @t41) +} + +void xgetbv() { + __asm xgetbv +} +// CHECK-LABEL: define void @xgetbv() +// CHECK: call void asm sideeffect inteldialect "xgetbv", "~{eax},~{edx},~{dirflag},~{fpsr},~{flags}"() + +void label1() { + __asm { + label: + jmp label + } + // CHECK-LABEL: define void @label1 + // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.1__label:\0A\09jmp {{.*}}__MSASMLABEL_.1__label", "~{dirflag},~{fpsr},~{flags}"() +} + +void label2() { + __asm { + jmp label + label: + } + // CHECK-LABEL: define void @label2 + // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.2__label\0A\09{{.*}}__MSASMLABEL_.2__label:", "~{dirflag},~{fpsr},~{flags}"() +} + +void label3() { + __asm { + label: + mov eax, label + } + // CHECK-LABEL: define void @label3 + // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.3__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.3__label", "~{eax},~{dirflag},~{fpsr},~{flags}"() +} + +void label4() { + __asm { + label: + mov eax, [label] + } + // CHECK-LABEL: define void @label4 + // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.4__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.4__label", "~{eax},~{dirflag},~{fpsr},~{flags}"() } diff --git a/test/CodeGen/ms-inline-asm.cpp b/test/CodeGen/ms-inline-asm.cpp index 83fe1075aff78..03d971e698b53 100644 --- a/test/CodeGen/ms-inline-asm.cpp +++ b/test/CodeGen/ms-inline-asm.cpp @@ -22,11 +22,7 @@ void t1() { __asm mov eax, dword ptr [Foo :: ptr] __asm mov eax, dword ptr [Foo :: ptr] // CHECK: @_Z2t1v -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE) -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3Bar3ptrE) -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE) -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE) -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE) +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0\0A\09mov eax, dword ptr $1\0A\09mov eax, dword ptr $2\0A\09mov eax, dword ptr $3\0A\09mov eax, dword ptr $4", "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE) } int gvar = 10; @@ -35,38 +31,26 @@ void t2() { __asm mov eax, offset Foo::ptr __asm mov eax, offset Foo::Bar::ptr // CHECK: t2 -// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE) -// CHECK: call void asm sideeffect inteldialect "mov eax, $0", "r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3Bar3ptrE) +// CHECK: call void asm sideeffect inteldialect "mov eax, $0\0A\09mov eax, $1", "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE) } // CHECK-LABEL: define void @_Z2t3v() void t3() { __asm mov eax, LENGTH Foo::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, LENGTH Foo::Bar::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, LENGTH Foo::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, LENGTH Foo::Bar::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, TYPE Foo::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, TYPE Foo::Bar::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, TYPE Foo::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, TYPE Foo::Bar::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, SIZE Foo::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, SIZE Foo::Bar::ptr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$4", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, SIZE Foo::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$16", "~{eax},~{dirflag},~{fpsr},~{flags}"() __asm mov eax, SIZE Foo::Bar::arr -// CHECK: call void asm sideeffect inteldialect "mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() +// CHECK: call void asm sideeffect inteldialect "mov eax, $$1\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$2\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$1\0A\09mov eax, $$4\0A\09mov eax, $$4\0A\09mov eax, $$16\0A\09mov eax, $$2", "~{eax},~{dirflag},~{fpsr},~{flags}"() } @@ -82,9 +66,8 @@ void T4::test() { // CHECK: [[THIS:%.*]] = load [[T4]]** [[T0]] // CHECK: [[X:%.*]] = getelementptr inbounds [[T4]]* [[THIS]], i32 0, i32 0 __asm mov eax, x; -// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $0", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* [[X]]) __asm mov y, eax; -// CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, eax", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE) +// CHECK: call void asm sideeffect inteldialect "mov eax, dword ptr $1\0A\09mov dword ptr $0, eax", "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}}) } template <class T> struct T5 { @@ -97,11 +80,9 @@ void test5() { // CHECK: [[Y:%.*]] = alloca i32 int x, y; __asm push y - // CHECK: call void asm sideeffect inteldialect "push dword ptr $0", "=*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* [[Y]]) __asm call T5<int>::create<float> - // CHECK: call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(i32 (float)* @_ZN2T5IiE6createIfEEiT_) __asm mov x, eax - // CHECK: call void asm sideeffect inteldialect "mov dword ptr $0, eax", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* [[X]]) + // CHECK: call void asm sideeffect inteldialect "push dword ptr $0\0A\09call dword ptr $2\0A\09mov dword ptr $1, eax", "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_) } // Just verify this doesn't emit an error. @@ -141,3 +122,20 @@ void t7_using() { // CHECK-LABEL: define void @_Z8t7_usingv // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"() } + +void t8() { + __asm some_label: + // CHECK-LABEL: define void @_Z2t8v() + // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.1__some_label:", "~{dirflag},~{fpsr},~{flags}"() + struct A { + static void g() { + __asm jmp some_label ; This should jump forwards + __asm some_label: + __asm nop + // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv() + // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.2__some_label\0A\09L__MSASMLABEL_.2__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"() + } + }; + A::g(); +} + diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c index fb0f62c61c4be..4498b34bc48dd 100644 --- a/test/CodeGen/ms-intrinsics.c +++ b/test/CodeGen/ms-intrinsics.c @@ -1,15 +1,28 @@ -// RUN: %clang_cc1 -triple i686--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -triple thumbv7--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple i686--windows -Oz -emit-llvm %s -o - \ +// RUN: | FileCheck %s -check-prefix CHECK -check-prefix CHECK-I386 +// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple thumbv7--windows -Oz -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64--windows -Oz -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64 + +// Intrin.h needs size_t, but -ffreestanding prevents us from getting it from +// stddef.h. Work around it with this typedef. +typedef __SIZE_TYPE__ size_t; + +#include <Intrin.h> void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) { return _InterlockedExchangePointer(Target, Value); } // CHECK: define{{.*}}i8* @test_InterlockedExchangePointer(i8** %Target, i8* %Value){{.*}}{ -// CHECK: %[[TARGET:[0-9]+]] = bitcast i8** %Target to i32* -// CHECK: %[[VALUE:[0-9]+]] = ptrtoint i8* %Value to i32 -// CHECK: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg i32* %[[TARGET]], i32 %[[VALUE]] seq_cst -// CHECK: %[[RESULT:[0-9]+]] = inttoptr i32 %[[EXCHANGE]] to i8* +// CHECK: %[[TARGET:[0-9]+]] = bitcast i8** %Target to [[iPTR:i[0-9]+]]* +// CHECK: %[[VALUE:[0-9]+]] = ptrtoint i8* %Value to [[iPTR]] +// CHECK: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg [[iPTR]]* %[[TARGET]], [[iPTR]] %[[VALUE]] seq_cst +// CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXCHANGE]] to i8* // CHECK: ret i8* %[[RESULT]] // CHECK: } @@ -19,12 +32,12 @@ void *test_InterlockedCompareExchangePointer(void * volatile *Destination, } // CHECK: define{{.*}}i8* @test_InterlockedCompareExchangePointer(i8** %Destination, i8* %Exchange, i8* %Comparand){{.*}}{ -// CHECK: %[[DEST:[0-9]+]] = bitcast i8** %Destination to i32* -// CHECK: %[[EXCHANGE:[0-9]+]] = ptrtoint i8* %Exchange to i32 -// CHECK: %[[COMPARAND:[0-9]+]] = ptrtoint i8* %Comparand to i32 -// CHECK: %[[XCHG:[0-9]+]] = cmpxchg volatile i32* %[[DEST:[0-9]+]], i32 %[[COMPARAND:[0-9]+]], i32 %[[EXCHANGE:[0-9]+]] seq_cst seq_cst -// CHECK: %[[EXTRACT:[0-9]+]] = extractvalue { i32, i1 } %[[XCHG]], 0 -// CHECK: %[[RESULT:[0-9]+]] = inttoptr i32 %[[EXTRACT]] to i8* +// CHECK: %[[DEST:[0-9]+]] = bitcast i8** %Destination to [[iPTR]]* +// CHECK: %[[EXCHANGE:[0-9]+]] = ptrtoint i8* %Exchange to [[iPTR]] +// CHECK: %[[COMPARAND:[0-9]+]] = ptrtoint i8* %Comparand to [[iPTR]] +// CHECK: %[[XCHG:[0-9]+]] = cmpxchg volatile [[iPTR]]* %[[DEST:[0-9]+]], [[iPTR]] %[[COMPARAND:[0-9]+]], [[iPTR]] %[[EXCHANGE:[0-9]+]] seq_cst seq_cst +// CHECK: %[[EXTRACT:[0-9]+]] = extractvalue { [[iPTR]], i1 } %[[XCHG]], 0 +// CHECK: %[[RESULT:[0-9]+]] = inttoptr [[iPTR]] %[[EXTRACT]] to i8* // CHECK: ret i8* %[[RESULT:[0-9]+]] // CHECK: } @@ -36,3 +49,25 @@ long test_InterlockedExchange(long *Target, long Value) { // CHECK: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg i32* %Target, i32 %Value seq_cst // CHECK: ret i32 %[[EXCHANGE:[0-9]+]] // CHECK: } + +#if defined(__i386__) +long test__readfsdword(unsigned long Offset) { + return __readfsdword(Offset); +} + +// CHECK-I386: define i32 @test__readfsdword(i32 %Offset){{.*}}{ +// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)* +// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i32 addrspace(257)* [[PTR]], align 4 +// CHECK-I386: ret i32 [[VALUE:%[0-9]+]] +// CHECK-I386: } +#endif + +#if defined(__x86_64__) +unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) { + return __umulh(a, b); +} +// CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b) +// CHECK-X64: = mul nuw i128 % + +#endif + diff --git a/test/CodeGen/mult-alt-generic.c b/test/CodeGen/mult-alt-generic.c index 6c9d789e412b2..303edfcf3c42c 100644 --- a/test/CodeGen/mult-alt-generic.c +++ b/test/CodeGen/mult-alt-generic.c @@ -17,7 +17,7 @@ int marray[2]; // CHECK: @single_m void single_m() { - // CHECK: call void asm "foo $1,$0", "=*m,*m[[CLOBBERS:[a-zA-Z0-9@%{},~_ ]*\"]](i32* {{[a-zA-Z0-9@%]+}}, i32* {{[a-zA-Z0-9@%]+}}) + // CHECK: call void asm "foo $1,$0", "=*m,*m[[CLOBBERS:[a-zA-Z0-9@%{},~_$ ]*\"]](i32* {{[a-zA-Z0-9@%]+}}, i32* {{[a-zA-Z0-9@%]+}}) asm("foo %1,%0" : "=m" (mout0) : "m" (min1)); } diff --git a/test/CodeGen/named_reg_global.c b/test/CodeGen/named_reg_global.c index 8117daef615c9..d888a3ff1733c 100644 --- a/test/CodeGen/named_reg_global.c +++ b/test/CodeGen/named_reg_global.c @@ -44,4 +44,4 @@ void fn2(struct p4_Thread *val) { // CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] %[[regw]]) // CHECK: !llvm.named.register.sp = !{!0} -// CHECK: !0 = metadata !{metadata !"sp"} +// CHECK: !0 = !{!"sp"} diff --git a/test/CodeGen/nonnull.c b/test/CodeGen/nonnull.c index 4d6cc4568d8b1..7c33e6329fddf 100644 --- a/test/CodeGen/nonnull.c +++ b/test/CodeGen/nonnull.c @@ -21,3 +21,31 @@ int * bar3() __attribute__((returns_nonnull)) { return &a; } +// CHECK: define i32 @bar4(i32 %n, i32* nonnull %p) +int bar4(int n, int *p) __attribute__((nonnull)) { + return n + *p; +} + +// CHECK: define i32 @bar5(i32 %n, i32* nonnull %p) +int bar5(int n, int *p) __attribute__((nonnull(1, 2))) { + return n + *p; +} + +typedef union { + unsigned long long n; + int *p; + double d; +} TransparentUnion __attribute__((transparent_union)); + +// CHECK: define i32 @bar6(i64 % +int bar6(TransparentUnion tu) __attribute__((nonnull(1))) { + return *tu.p; +} + +// CHECK: define void @bar7(i32* nonnull %a, i32* nonnull %b) +void bar7(int *a, int *b) __attribute__((nonnull(1))) +__attribute__((nonnull(2))) {} + +// CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b) +void bar8(int *a, int *b) __attribute__((nonnull)) +__attribute__((nonnull(1))) {} diff --git a/test/CodeGen/nvptx-abi.c b/test/CodeGen/nvptx-abi.c index f846def2de520..58ad6a17f242a 100644 --- a/test/CodeGen/nvptx-abi.c +++ b/test/CodeGen/nvptx-abi.c @@ -5,13 +5,39 @@ typedef struct float4_s { float x, y, z, w; } float4_t; -float4_t my_function(void); - -// CHECK-DAG: declare %struct.float4_s @my_function +float4_t my_function(void) { +// CHECK-LABEL: define %struct.float4_s @my_function + float4_t t; + return t; +}; float bar(void) { float4_t ret; -// CHECK-DAG: call %struct.float4_s @my_function +// CHECK-LABEL: @bar +// CHECK: call %struct.float4_s @my_function ret = my_function(); return ret.x; } + +void foo(float4_t x) { +// CHECK-LABEL: @foo +// CHECK: %struct.float4_s* byval %x +} + +void fooN(float4_t x, float4_t y, float4_t z) { +// CHECK-LABEL: @fooN +// CHECK: %struct.float4_s* byval %x +// CHECK: %struct.float4_s* byval %y +// CHECK: %struct.float4_s* byval %z +} + +typedef struct nested_s { + unsigned long long x; + float z[64]; + float4_t t; +} nested_t; + +void baz(nested_t x) { +// CHECK-LABEL: @baz +// CHECK: %struct.nested_s* byval %x) +} diff --git a/test/CodeGen/piclevels.c b/test/CodeGen/piclevels.c new file mode 100644 index 0000000000000..54744e2efa7d3 --- /dev/null +++ b/test/CodeGen/piclevels.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -emit-llvm -pic-level 2 %s -o - | FileCheck %s -check-prefix=CHECK-BIGPIC +// RUN: %clang_cc1 -emit-llvm -pic-level 1 %s -o - | FileCheck %s -check-prefix=CHECK-SMALLPIC + +// CHECK-BIGPIC: !llvm.module.flags = !{{{.*}}} +// CHECK-BIGPIC: !{{[0-9]+}} = !{i32 1, !"PIC Level", i32 2} +// CHECK-SMALLPIC: !llvm.module.flags = !{{{.*}}} +// CHECK-SMALLPIC: !{{[0-9]+}} = !{i32 1, !"PIC Level", i32 1} diff --git a/test/CodeGen/ppc-signbit.c b/test/CodeGen/ppc-signbit.c new file mode 100644 index 0000000000000..31b71d8cdbb93 --- /dev/null +++ b/test/CodeGen/ppc-signbit.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple powerpc64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple powerpc64le-linux-gnu | FileCheck %s + +int test(long double x) { return __builtin_signbitl(x); } + +// CHECK-LABEL: define signext i32 @test(ppc_fp128 %x) +// CHECK: bitcast ppc_fp128 %{{.*}} to i128 +// CHECK: trunc i128 %{{.*}} to i64 +// CHECK: icmp slt i64 %{{.*}}, 0 +// CHECK: zext i1 %{{.*}} to i32 + diff --git a/test/CodeGen/ppc-varargs-struct.c b/test/CodeGen/ppc-varargs-struct.c new file mode 100644 index 0000000000000..f0e075b048d7d --- /dev/null +++ b/test/CodeGen/ppc-varargs-struct.c @@ -0,0 +1,112 @@ +// REQUIRES: powerpc-registered-target +// REQUIRES: asserts +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-PPC + +#include <stdarg.h> + +struct x { + long a; + double b; +}; + +void testva (int n, ...) +{ + va_list ap; + + struct x t = va_arg (ap, struct x); +// CHECK: bitcast i8* %{{[a-z.0-9]*}} to %struct.x* +// CHECK: bitcast %struct.x* %t to i8* +// CHECK: bitcast %struct.x* %{{[0-9]+}} to i8* +// CHECK: call void @llvm.memcpy +// CHECK-PPC: [[ARRAYDECAY:%[a-z0-9]+]] = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0 +// CHECK-PPC-NEXT: [[GPRPTR:%[a-z0-9]+]] = bitcast %struct.__va_list_tag* [[ARRAYDECAY]] to i8* +// CHECK-PPC-NEXT: [[ZERO:%[0-9]+]] = ptrtoint i8* [[GPRPTR]] to i32 +// CHECK-PPC-NEXT: [[ONE:%[0-9]+]] = add i32 [[ZERO]], 1 +// CHECK-PPC-NEXT: [[TWO:%[0-9]+]] = inttoptr i32 [[ONE]] to i8* +// CHECK-PPC-NEXT: [[THREE:%[0-9]+]] = add i32 [[ONE]], 3 +// CHECK-PPC-NEXT: [[FOUR:%[0-9]+]] = inttoptr i32 [[THREE]] to i8** +// CHECK-PPC-NEXT: [[FIVE:%[0-9]+]] = add i32 [[THREE]], 4 +// CHECK-PPC-NEXT: [[SIX:%[0-9]+]] = inttoptr i32 [[FIVE]] to i8** +// CHECK-PPC-NEXT: [[GPR:%[a-z0-9]+]] = load i8* [[GPRPTR]] +// CHECK-PPC-NEXT: [[FPR:%[a-z0-9]+]] = load i8* [[TWO]] +// CHECK-PPC-NEXT: [[OVERFLOW_AREA:%[a-z_0-9]+]] = load i8** [[FOUR]] +// CHECK-PPC-NEXT: [[SEVEN:%[0-9]+]] = ptrtoint i8* [[OVERFLOW_AREA]] to i32 +// CHECK-PPC-NEXT: [[REGSAVE_AREA:%[a-z_0-9]+]] = load i8** [[SIX]] +// CHECK-PPC-NEXT: [[EIGHT:%[0-9]+]] = ptrtoint i8* [[REGSAVE_AREA]] to i32 +// CHECK-PPC-NEXT: [[COND:%[a-z0-9]+]] = icmp ult i8 [[GPR]], 8 +// CHECK-PPC-NEXT: [[NINE:%[0-9]+]] = mul i8 [[GPR]], 4 +// CHECK-PPC-NEXT: [[TEN:%[0-9]+]] = sext i8 [[NINE]] to i32 +// CHECK-PPC-NEXT: [[ELEVEN:%[0-9]+]] = add i32 [[EIGHT]], [[TEN]] +// CHECK-PPC-NEXT: br i1 [[COND]], label [[USING_REGS:%[a-z_0-9]+]], label [[USING_OVERFLOW:%[a-z_0-9]+]] +// +// CHECK-PPC1:[[USING_REGS]] +// CHECK-PPC: [[TWELVE:%[0-9]+]] = inttoptr i32 [[ELEVEN]] to %struct.x* +// CHECK-PPC-NEXT: [[THIRTEEN:%[0-9]+]] = add i8 [[GPR]], 1 +// CHECK-PPC-NEXT: store i8 [[THIRTEEN]], i8* [[GPRPTR]] +// CHECK-PPC-NEXT: br label [[CONT:%[a-z0-9]+]] +// +// CHECK-PPC1:[[USING_OVERFLOW]] +// CHECK-PPC: [[FOURTEEN:%[0-9]+]] = inttoptr i32 [[SEVEN]] to %struct.x* +// CHECK-PPC-NEXT: [[FIFTEEN:%[0-9]+]] = add i32 [[SEVEN]], 4 +// CHECK-PPC-NEXT: [[SIXTEEN:%[0-9]+]] = inttoptr i32 [[FIFTEEN]] to i8* +// CHECK-PPC-NEXT: store i8* [[SIXTEEN]], i8** [[FOUR]] +// CHECK-PPC-NEXT: br label [[CONT]] +// +// CHECK-PPC1:[[CONT]] +// CHECK-PPC: [[VAARG_ADDR:%[a-z.0-9]+]] = phi %struct.x* [ [[TWELVE]], [[USING_REGS]] ], [ [[FOURTEEN]], [[USING_OVERFLOW]] ] +// CHECK-PPC-NEXT: [[AGGRPTR:%[a-z0-9]+]] = bitcast %struct.x* [[VAARG_ADDR]] to i8** +// CHECK-PPC-NEXT: [[AGGR:%[a-z0-9]+]] = load i8** [[AGGRPTR]] +// CHECK-PPC-NEXT: [[SEVENTEEN:%[0-9]+]] = bitcast %struct.x* %t to i8* +// CHECK-PPC-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[SEVENTEEN]], i8* [[AGGR]], i32 16, i32 8, i1 false) + + int v = va_arg (ap, int); +// CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64 +// CHECK: add i64 %{{[0-9]+}}, 4 +// CHECK: inttoptr i64 %{{[0-9]+}} to i8* +// CHECK: bitcast i8* %{{[0-9]+}} to i32* +// CHECK-PPC: [[ARRAYDECAY1:%[a-z0-9]+]] = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0 +// CHECK-PPC-NEXT: [[GPRPTR1:%[a-z0-9]+]] = bitcast %struct.__va_list_tag* [[ARRAYDECAY1]] to i8* +// CHECK-PPC-NEXT: [[EIGHTEEN:%[0-9]+]] = ptrtoint i8* [[GPRPTR1]] to i32 +// CHECK-PPC-NEXT: [[NINETEEN:%[0-9]+]] = add i32 [[EIGHTEEN]], 1 +// CHECK-PPC-NEXT: [[TWENTY:%[0-9]+]] = inttoptr i32 [[NINETEEN]] to i8* +// CHECK-PPC-NEXT: [[TWENTYONE:%[0-9]+]] = add i32 [[NINETEEN]], 3 +// CHECK-PPC-NEXT: [[TWENTYTWO:%[0-9]+]] = inttoptr i32 [[TWENTYONE]] to i8** +// CHECK-PPC-NEXT: [[TWENTYTHREE:%[0-9]+]] = add i32 [[TWENTYONE]], 4 +// CHECK-PPC-NEXT: [[TWENTYFOUR:%[0-9]+]] = inttoptr i32 [[TWENTYTHREE]] to i8** +// CHECK-PPC-NEXT: [[GPR1:%[a-z0-9]+]] = load i8* [[GPRPTR1]] +// CHECK-PPC-NEXT: [[FPR1:%[a-z0-9]+]] = load i8* [[TWENTY]] +// CHECK-PPC-NEXT: [[OVERFLOW_AREA1:%[a-z_0-9]+]] = load i8** [[TWENTYTWO]] +// CHECK-PPC-NEXT: [[TWENTYFIVE:%[0-9]+]] = ptrtoint i8* [[OVERFLOW_AREA1]] to i32 +// CHECK-PPC-NEXT: [[REGSAVE_AREA1:%[a-z_0-9]+]] = load i8** [[TWENTYFOUR]] +// CHECK-PPC-NEXT: [[TWENTYSIX:%[0-9]+]] = ptrtoint i8* [[REGSAVE_AREA1]] to i32 +// CHECK-PPC-NEXT: [[COND1:%[a-z0-9]+]] = icmp ult i8 [[GPR1]], 8 +// CHECK-PPC-NEXT: [[TWENTYSEVEN:%[0-9]+]] = mul i8 [[GPR1]], 4 +// CHECK-PPC-NEXT: [[TWENTYEIGHT:%[0-9]+]] = sext i8 [[TWENTYSEVEN]] to i32 +// CHECK-PPC-NEXT: [[TWENTYNINE:%[0-9]+]] = add i32 [[TWENTYSIX]], [[TWENTYEIGHT]] +// CHECK-PPC-NEXT: br i1 [[COND1]], label [[USING_REGS1:%[a-z_0-9]+]], label [[USING_OVERFLOW1:%[a-z_0-9]+]] +// +// CHECK-PPC1:[[USING_REGS1]]: +// CHECK-PPC: [[THIRTY:%[0-9]+]] = inttoptr i32 [[TWENTYNINE]] to i32* +// CHECK-PPC-NEXT: [[THIRTYONE:%[0-9]+]] = add i8 [[GPR1]], 1 +// CHECK-PPC-NEXT: store i8 [[THIRTYONE]], i8* [[GPRPTR1]] +// CHECK-PPC-NEXT: br label [[CONT1:%[a-z0-9]+]] +// +// CHECK-PPC1:[[USING_OVERFLOW1]]: +// CHECK-PPC: [[THIRTYTWO:%[0-9]+]] = inttoptr i32 [[TWENTYFIVE]] to i32* +// CHECK-PPC-NEXT: [[THIRTYTHREE:%[0-9]+]] = add i32 [[TWENTYFIVE]], 4 +// CHECK-PPC-NEXT: [[THIRTYFOUR:%[0-9]+]] = inttoptr i32 [[THIRTYTHREE]] to i8* +// CHECK-PPC-NEXT: store i8* [[THIRTYFOUR]], i8** [[TWENTYTWO]] +// CHECK-PPC-NEXT: br label [[CONT1]] +// +// CHECK-PPC1:[[CONT1]]: +// CHECK-PPC: [[VAARG_ADDR1:%[a-z.0-9]+]] = phi i32* [ [[THIRTY]], [[USING_REGS1]] ], [ [[THIRTYTWO]], [[USING_OVERFLOW1]] ] +// CHECK-PPC-NEXT: [[THIRTYFIVE:%[0-9]+]] = load i32* [[VAARG_ADDR1]] +// CHECK-PPC-NEXT: store i32 [[THIRTYFIVE]], i32* %v, align 4 + +#ifdef __powerpc64__ + __int128_t u = va_arg (ap, __int128_t); +#endif +// CHECK: bitcast i8* %{{[a-z.0-9]+}} to i128* +// CHECK-NEXT: load i128* %{{[0-9]+}} +} diff --git a/test/CodeGen/ppc64-elf-abi.c b/test/CodeGen/ppc64-elf-abi.c new file mode 100644 index 0000000000000..0dd183e2a6da9 --- /dev/null +++ b/test/CodeGen/ppc64-elf-abi.c @@ -0,0 +1,40 @@ +// REQUIRES: powerpc-registered-target + +// Verify ABI selection by the front end + +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ELFv2 + +// CHECK-ELFv1: define void @func_fab(%struct.fab* noalias sret %agg.result, i64 %x.coerce) +// CHECK-ELFv2: define [2 x float] @func_fab([2 x float] %x.coerce) +struct fab { float a; float b; }; +struct fab func_fab(struct fab x) { return x; } + +// Verify ABI choice is passed on to the back end + +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 + +// CHECK-ASM-ELFv2: .abiversion 2 +// CHECK-ASM-ELFv1-NOT: .abiversion 2 + diff --git a/test/CodeGen/ppc64-varargs-struct.c b/test/CodeGen/ppc64-varargs-struct.c deleted file mode 100644 index 70b242c7f4172..0000000000000 --- a/test/CodeGen/ppc64-varargs-struct.c +++ /dev/null @@ -1,30 +0,0 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s - -#include <stdarg.h> - -struct x { - long a; - double b; -}; - -void testva (int n, ...) -{ - va_list ap; - - struct x t = va_arg (ap, struct x); -// CHECK: bitcast i8* %{{[a-z.0-9]*}} to %struct.x* -// CHECK: bitcast %struct.x* %t to i8* -// CHECK: bitcast %struct.x* %{{[0-9]+}} to i8* -// CHECK: call void @llvm.memcpy - - int v = va_arg (ap, int); -// CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64 -// CHECK: add i64 %{{[0-9]+}}, 4 -// CHECK: inttoptr i64 %{{[0-9]+}} to i8* -// CHECK: bitcast i8* %{{[0-9]+}} to i32* - - __int128_t u = va_arg (ap, __int128_t); -// CHECK: bitcast i8* %{{[a-z.0-9]+}} to i128* -// CHECK-NEXT: load i128* %{{[0-9]+}} -} diff --git a/test/CodeGen/ppc64le-aggregates.c b/test/CodeGen/ppc64le-aggregates.c index acf34a8a80123..e193dcc3faeff 100644 --- a/test/CodeGen/ppc64le-aggregates.c +++ b/test/CodeGen/ppc64le-aggregates.c @@ -1,4 +1,3 @@ -// REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -faltivec -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s // Test homogeneous float aggregate passing and returning. @@ -16,6 +15,8 @@ struct f9 { float f[9]; }; struct fab { float a; float b; }; struct fabc { float a; float b; float c; }; +struct f2a2b { float a[2]; float b[2]; }; + // CHECK: define [1 x float] @func_f1(float inreg %x.coerce) struct f1 func_f1(struct f1 x) { return x; } @@ -49,6 +50,9 @@ struct fab func_fab(struct fab x) { return x; } // CHECK: define [3 x float] @func_fabc([3 x float] %x.coerce) struct fabc func_fabc(struct fabc x) { return x; } +// CHECK: define [4 x float] @func_f2a2b([4 x float] %x.coerce) +struct f2a2b func_f2a2b(struct f2a2b x) { return x; } + // CHECK-LABEL: @call_f1 // CHECK: %[[TMP:[^ ]+]] = load float* getelementptr inbounds (%struct.f1* @global_f1, i32 0, i32 0, i32 0), align 1 // CHECK: call [1 x float] @func_f1(float inreg %[[TMP]]) diff --git a/test/CodeGen/pr5406.c b/test/CodeGen/pr5406.c index 2d198220a7700..0f04a8e069cd5 100644 --- a/test/CodeGen/pr5406.c +++ b/test/CodeGen/pr5406.c @@ -6,7 +6,7 @@ typedef struct { char x[3]; } A0; void foo (int i, ...); -// CHECK: call arm_aapcscc void (i32, ...)* @foo(i32 1, [1 x i32] {{.*}}) +// CHECK: call void (i32, ...)* @foo(i32 1, [1 x i32] {{.*}}) int main (void) { A0 a3; diff --git a/test/CodeGen/pragma-comment.c b/test/CodeGen/pragma-comment.c index 73cc5483bcf6e..221cfc87f9196 100644 --- a/test/CodeGen/pragma-comment.c +++ b/test/CodeGen/pragma-comment.c @@ -10,14 +10,14 @@ #pragma comment(linker," /bar=" BAR) // CHECK: !llvm.module.flags = !{{{.*}}} -// CHECK: !{{[0-9]+}} = metadata !{i32 6, metadata !"Linker Options", metadata ![[link_opts:[0-9]+]]} -// CHECK: ![[link_opts]] = metadata !{metadata ![[msvcrt:[0-9]+]], metadata ![[kernel32:[0-9]+]], metadata ![[USER32:[0-9]+]], metadata ![[bar:[0-9]+]]} -// CHECK: ![[msvcrt]] = metadata !{metadata !"/DEFAULTLIB:msvcrt.lib"} -// CHECK: ![[kernel32]] = metadata !{metadata !"/DEFAULTLIB:kernel32.lib"} -// CHECK: ![[USER32]] = metadata !{metadata !"/DEFAULTLIB:USER32.LIB"} -// CHECK: ![[bar]] = metadata !{metadata !" /bar=2"} +// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} +// CHECK: ![[link_opts]] = !{![[msvcrt:[0-9]+]], ![[kernel32:[0-9]+]], ![[USER32:[0-9]+]], ![[bar:[0-9]+]]} +// CHECK: ![[msvcrt]] = !{!"/DEFAULTLIB:msvcrt.lib"} +// CHECK: ![[kernel32]] = !{!"/DEFAULTLIB:kernel32.lib"} +// CHECK: ![[USER32]] = !{!"/DEFAULTLIB:USER32.LIB"} +// CHECK: ![[bar]] = !{!" /bar=2"} -// LINUX: metadata !{metadata !"-lmsvcrt.lib"} -// LINUX: metadata !{metadata !"-lkernel32"} -// LINUX: metadata !{metadata !"-lUSER32.LIB"} -// LINUX: metadata !{metadata !" /bar=2"} +// LINUX: !{!"-lmsvcrt.lib"} +// LINUX: !{!"-lkernel32"} +// LINUX: !{!"-lUSER32.LIB"} +// LINUX: !{!" /bar=2"} diff --git a/test/CodeGen/pragma-detect_mismatch.c b/test/CodeGen/pragma-detect_mismatch.c index b223a61c9b033..c5f3af340aae3 100644 --- a/test/CodeGen/pragma-detect_mismatch.c +++ b/test/CodeGen/pragma-detect_mismatch.c @@ -1,12 +1,12 @@ -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
-
-#pragma detect_mismatch("test", "1")
-
-#define BAR "2"
-#pragma detect_mismatch("test2", BAR)
-
-// CHECK: !llvm.module.flags = !{{{.*}}}
-// CHECK: !{{[0-9]+}} = metadata !{i32 6, metadata !"Linker Options", metadata ![[link_opts:[0-9]+]]}
-// CHECK: ![[link_opts]] = metadata !{metadata ![[test:[0-9]+]], metadata ![[test2:[0-9]+]]}
-// CHECK: ![[test]] = metadata !{metadata !"/FAILIFMISMATCH:\22test=1\22"}
-// CHECK: ![[test2]] = metadata !{metadata !"/FAILIFMISMATCH:\22test2=2\22"}
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s + +#pragma detect_mismatch("test", "1") + +#define BAR "2" +#pragma detect_mismatch("test2", BAR) + +// CHECK: !llvm.module.flags = !{{{.*}}} +// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]} +// CHECK: ![[link_opts]] = !{![[test:[0-9]+]], ![[test2:[0-9]+]]} +// CHECK: ![[test]] = !{!"/FAILIFMISMATCH:\22test=1\22"} +// CHECK: ![[test2]] = !{!"/FAILIFMISMATCH:\22test2=2\22"} diff --git a/test/CodeGen/pragma-loop.cpp b/test/CodeGen/pragma-loop.cpp index bdcd304263150..dd40c1d72600e 100644 --- a/test/CodeGen/pragma-loop.cpp +++ b/test/CodeGen/pragma-loop.cpp @@ -8,7 +8,7 @@ void while_test(int *List, int Length) { #pragma clang loop vectorize(enable) #pragma clang loop interleave_count(4) #pragma clang loop vectorize_width(4) -#pragma clang loop unroll(enable) +#pragma clang loop unroll(full) while (i < Length) { // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] List[i] = i * 2; @@ -28,11 +28,13 @@ void do_test(int *List, int Length) { } while (i < Length); } +enum struct Tuner : short { Interleave = 4, Unroll = 8 }; + // Verify for loop is recognized after sequence of pragma clang loop directives. void for_test(int *List, int Length) { #pragma clang loop interleave(enable) -#pragma clang loop interleave_count(4) -#pragma clang loop unroll_count(8) +#pragma clang loop interleave_count(static_cast<int>(Tuner::Interleave)) +#pragma clang loop unroll_count(static_cast<int>(Tuner::Unroll)) for (int i = 0; i < Length; i++) { // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] List[i] = i * 2; @@ -74,28 +76,74 @@ void for_define_test(int *List, int Length, int Value) { } } +// Verify constant expressions are handled correctly. +void for_contant_expression_test(int *List, int Length) { +#pragma clang loop vectorize_width(1 + 4) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + List[i] = i; + } + +#pragma clang loop vectorize_width(3 + VECWIDTH) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]] + List[i] += i; + } +} + // Verify metadata is generated when template is used. template <typename A> void for_template_test(A *List, int Length, A Value) { - #pragma clang loop vectorize_width(8) interleave_count(8) unroll_count(8) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_9:.*]] List[i] = i * Value; } } // Verify define is resolved correctly when template is used. -template <typename A> +template <typename A, typename T> void for_template_define_test(A *List, int Length, A Value) { -#pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT) -#pragma clang loop unroll_count(UNROLLCOUNT) + const T VWidth = VECWIDTH; + const T ICount = INTCOUNT; + const T UCount = UNROLLCOUNT; +#pragma clang loop vectorize_width(VWidth) interleave_count(ICount) +#pragma clang loop unroll_count(UCount) for (int i = 0; i < Length; i++) { - // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]] + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_10:.*]] List[i] = i * Value; } } +// Verify templates and constant expressions are handled correctly. +template <typename A, int V, int I, int U> +void for_template_constant_expression_test(A *List, int Length) { +#pragma clang loop vectorize_width(V) interleave_count(I) unroll_count(U) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_11:.*]] + List[i] = i; + } + +#pragma clang loop vectorize_width(V * 2 + VECWIDTH) interleave_count(I * 2 + INTCOUNT) unroll_count(U * 2 + UNROLLCOUNT) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_12:.*]] + List[i] += i; + } + + const int Scale = 4; +#pragma clang loop vectorize_width(Scale * V) interleave_count(Scale * I) unroll_count(Scale * U) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_13:.*]] + List[i] += i; + } + +#pragma clang loop vectorize_width((Scale * V) + 2) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_14:.*]] + List[i] += i; + } +} + #undef VECWIDTH #undef INTCOUNT #undef UNROLLCOUNT @@ -105,25 +153,39 @@ void template_test(double *List, int Length) { double Value = 10; for_template_test<double>(List, Length, Value); - for_template_define_test<double>(List, Length, Value); + for_template_define_test<double, int>(List, Length, Value); + for_template_constant_expression_test<double, 2, 4, 8>(List, Length); } -// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[UNROLLENABLE_1:.*]], metadata ![[WIDTH_4:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[INTENABLE_1:.*]]} -// CHECK: ![[UNROLLENABLE_1]] = metadata !{metadata !"llvm.loop.unroll.enable", i1 true} -// CHECK: ![[WIDTH_4]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 4} -// CHECK: ![[INTERLEAVE_4]] = metadata !{metadata !"llvm.loop.interleave.count", i32 4} -// CHECK: ![[INTENABLE_1]] = metadata !{metadata !"llvm.loop.vectorize.enable", i1 true} -// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[WIDTH_8:.*]]} -// CHECK: ![[UNROLLENABLE_0]] = metadata !{metadata !"llvm.loop.unroll.enable", i1 false} -// CHECK: ![[WIDTH_8]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 8} -// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[ENABLE_1:.*]]} -// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.loop.unroll.count", i32 8} -// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]} -// CHECK: ![[INTERLEAVE_2]] = metadata !{metadata !"llvm.loop.interleave.count", i32 2} -// CHECK: ![[WIDTH_2]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 2} -// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[WIDTH_1:.*]]} -// CHECK: ![[WIDTH_1]] = metadata !{metadata !"llvm.loop.vectorize.width", i32 1} -// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]} -// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_8:.*]], metadata ![[WIDTH_8:.*]]} -// CHECK: ![[INTERLEAVE_8]] = metadata !{metadata !"llvm.loop.interleave.count", i32 8} -// CHECK: ![[LOOP_8]] = metadata !{metadata ![[LOOP_8]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]]} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4} +// CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4} +// CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[ENABLE_1:.*]]} +// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]], ![[WIDTH_1:.*]]} +// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]} +// CHECK: ![[WIDTH_5]] = !{!"llvm.loop.vectorize.width", i32 5} +// CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], ![[WIDTH_5:.*]]} +// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[UNROLL_8:.*]], ![[INTERLEAVE_8:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[INTERLEAVE_8]] = !{!"llvm.loop.interleave.count", i32 8} +// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[UNROLL_24:.*]], ![[INTERLEAVE_10:.*]], ![[WIDTH_6:.*]]} +// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} +// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[WIDTH_6]] = !{!"llvm.loop.vectorize.width", i32 6} +// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[UNROLL_32:.*]], ![[INTERLEAVE_16:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} +// CHECK: ![[INTERLEAVE_16]] = !{!"llvm.loop.interleave.count", i32 16} +// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], ![[WIDTH_10:.*]]} +// CHECK: ![[WIDTH_10]] = !{!"llvm.loop.vectorize.width", i32 10} diff --git a/test/CodeGen/pragma-unroll.cpp b/test/CodeGen/pragma-unroll.cpp index b321e74a11540..8b73fa6c8aab4 100644 --- a/test/CodeGen/pragma-unroll.cpp +++ b/test/CodeGen/pragma-unroll.cpp @@ -17,7 +17,7 @@ void while_test(int *List, int Length) { void do_test(int *List, int Length) { int i = 0; -#pragma unroll 16 +#pragma nounroll do { // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] List[i] = i * 2; @@ -86,14 +86,14 @@ void template_test(double *List, int Length) { for_template_define_test<double>(List, Length, Value); } -// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[UNROLLENABLE_1:.*]]} -// CHECK: ![[UNROLLENABLE_1]] = metadata !{metadata !"llvm.loop.unroll.enable", i1 true} -// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLL_16:.*]]} -// CHECK: ![[UNROLL_16]] = metadata !{metadata !"llvm.loop.unroll.count", i32 16} -// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_8:.*]]} -// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.loop.unroll.count", i32 8} -// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[UNROLL_4:.*]]} -// CHECK: ![[UNROLL_4]] = metadata !{metadata !"llvm.loop.unroll.count", i32 4} -// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[UNROLL_8:.*]]} -// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_8:.*]]} -// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]]} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]} +// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_4:.*]]} +// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]} diff --git a/test/CodeGen/pragma-weak.c b/test/CodeGen/pragma-weak.c index b5d186324bf67..aba98e185b4e4 100644 --- a/test/CodeGen/pragma-weak.c +++ b/test/CodeGen/pragma-weak.c @@ -7,16 +7,16 @@ // CHECK-DAG: @both = alias void ()* @__both // CHECK-DAG: @both2 = alias void ()* @__both2 -// CHECK-DAG: @weakvar_alias = alias weak i32* @__weakvar_alias -// CHECK-DAG: @foo = alias weak void ()* @__foo -// CHECK-DAG: @foo2 = alias weak void ()* @__foo2 -// CHECK-DAG: @stutter = alias weak void ()* @__stutter -// CHECK-DAG: @stutter2 = alias weak void ()* @__stutter2 -// CHECK-DAG: @declfirst = alias weak void ()* @__declfirst -// CHECK-DAG: @declfirstattr = alias weak void ()* @__declfirstattr -// CHECK-DAG: @mix2 = alias weak void ()* @__mix2 -// CHECK-DAG: @a1 = alias weak void ()* @__a1 -// CHECK-DAG: @xxx = alias weak void ()* @__xxx +// CHECK-DAG: @weakvar_alias = weak alias i32* @__weakvar_alias +// CHECK-DAG: @foo = weak alias void ()* @__foo +// CHECK-DAG: @foo2 = weak alias void ()* @__foo2 +// CHECK-DAG: @stutter = weak alias void ()* @__stutter +// CHECK-DAG: @stutter2 = weak alias void ()* @__stutter2 +// CHECK-DAG: @declfirst = weak alias void ()* @__declfirst +// CHECK-DAG: @declfirstattr = weak alias void ()* @__declfirstattr +// CHECK-DAG: @mix2 = weak alias void ()* @__mix2 +// CHECK-DAG: @a1 = weak alias void ()* @__a1 +// CHECK-DAG: @xxx = weak alias void ()* @__xxx diff --git a/test/CodeGen/predefined-expr.c b/test/CodeGen/predefined-expr.c index 6c94152b737ea..3ccdeb3b4ce3f 100644 --- a/test/CodeGen/predefined-expr.c +++ b/test/CodeGen/predefined-expr.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -fms-extensions %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fms-extensions %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s // CHECK: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00" // CHECK: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [21 x i8] c"void plainFunction()\00" diff --git a/test/CodeGen/sanitize-address-field-padding.cpp b/test/CodeGen/sanitize-address-field-padding.cpp new file mode 100644 index 0000000000000..d4eea1b9e69dc --- /dev/null +++ b/test/CodeGen/sanitize-address-field-padding.cpp @@ -0,0 +1,237 @@ +// Test -fsanitize-address-field-padding +// RUN: echo 'type:SomeNamespace::BlacklistedByName=field-padding' > %t.type.blacklist +// RUN: echo 'src:*sanitize-address-field-padding.cpp=field-padding' > %t.file.blacklist +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s -O1 -mconstructor-aliases 2>&1 | FileCheck %s --check-prefix=WITH_CTOR_ALIASES +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.file.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=FILE_BLACKLIST +// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=NO_PADDING +// + +// The reasons to ignore a particular class are not set in stone and will change. +// +// CHECK: -fsanitize-address-field-padding applied to Positive1 +// CHECK: -fsanitize-address-field-padding ignored for Negative1 because it is trivially copyable +// CHECK: -fsanitize-address-field-padding ignored for Negative2 because it is trivially copyable +// CHECK: -fsanitize-address-field-padding ignored for Negative3 because it is a union +// CHECK: -fsanitize-address-field-padding ignored for Negative4 because it is trivially copyable +// CHECK: -fsanitize-address-field-padding ignored for Negative5 because it is packed +// CHECK: -fsanitize-address-field-padding ignored for SomeNamespace::BlacklistedByName because it is blacklisted +// CHECK: -fsanitize-address-field-padding ignored for ExternCStruct because it is not C++ +// +// FILE_BLACKLIST: -fsanitize-address-field-padding ignored for Positive1 because it is in a blacklisted file +// FILE_BLACKLIST-NOT: __asan_poison_intra_object_redzone +// NO_PADDING-NOT: __asan_poison_intra_object_redzone + + +class Positive1 { + public: + Positive1() {} + ~Positive1() {} + int make_it_non_standard_layout; + private: + char private1; + int private2; + short private_array[6]; + long long private3; +}; + +Positive1 positive1; +// Positive1 with extra paddings +// CHECK: type { i32, [12 x i8], i8, [15 x i8], i32, [12 x i8], [6 x i16], [12 x i8], i64, [8 x i8] } + +struct VirtualBase { + int foo; +}; + +class ClassWithVirtualBase : public virtual VirtualBase { + public: + ClassWithVirtualBase() {} + ~ClassWithVirtualBase() {} + int make_it_non_standard_layout; + private: + char x[7]; + char y[9]; +}; + +ClassWithVirtualBase class_with_virtual_base; + +class WithFlexibleArray1 { + public: + WithFlexibleArray1() {} + ~WithFlexibleArray1() {} + int make_it_non_standard_layout; + private: + char private1[33]; + int flexible[]; // Don't insert padding after this field. +}; + +WithFlexibleArray1 with_flexible_array1; +// CHECK: %class.WithFlexibleArray1 = type { i32, [12 x i8], [33 x i8], [15 x i8], [0 x i32] } + +class WithFlexibleArray2 { + public: + char x[21]; + WithFlexibleArray1 flex1; // Don't insert padding after this field. +}; + +WithFlexibleArray2 with_flexible_array2; +// CHECK: %class.WithFlexibleArray2 = type { [21 x i8], [11 x i8], %class.WithFlexibleArray1 } + +class WithFlexibleArray3 { + public: + char x[13]; + WithFlexibleArray2 flex2; // Don't insert padding after this field. +}; + +WithFlexibleArray3 with_flexible_array3; + + +class Negative1 { + public: + Negative1() {} + int public1, public2; +}; +Negative1 negative1; +// CHECK: type { i32, i32 } + +class Negative2 { + public: + Negative2() {} + private: + int private1, private2; +}; +Negative2 negative2; +// CHECK: type { i32, i32 } + +union Negative3 { + char m1[8]; + long long m2; +}; + +Negative3 negative3; +// CHECK: type { i64 } + +class Negative4 { + public: + Negative4() {} + // No DTOR + int make_it_non_standard_layout; + private: + char private1; + int private2; +}; + +Negative4 negative4; +// CHECK: type { i32, i8, i32 } + +class __attribute__((packed)) Negative5 { + public: + Negative5() {} + ~Negative5() {} + int make_it_non_standard_layout; + private: + char private1; + int private2; +}; + +Negative5 negative5; +// CHECK: type <{ i32, i8, i32 }> + + +namespace SomeNamespace { +class BlacklistedByName { + public: + BlacklistedByName() {} + ~BlacklistedByName() {} + int make_it_non_standard_layout; + private: + char private1; + int private2; +}; +} // SomeNamespace + +SomeNamespace::BlacklistedByName blacklisted_by_name; + +extern "C" { +class ExternCStruct { + public: + ExternCStruct() {} + ~ExternCStruct() {} + int make_it_non_standard_layout; + private: + char private1; + int private2; +}; +} // extern "C" + +ExternCStruct extern_C_struct; + +// CTOR +// CHECK-LABEL: define {{.*}}Positive1C1Ev +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}15) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}8) +// CHECK-NOT: __asan_poison_intra_object_redzone +// CHECK: ret void +// +// DTOR +// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}15) +// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12) +// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}8) +// CHECK-NOT: __asan_unpoison_intra_object_redzone +// CHECK: ret void +// +// +// CHECK-LABEL: define linkonce_odr void @_ZN20ClassWithVirtualBaseC1Ev +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 12) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 9) +// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 15) +// CHECK-NOT: __asan_poison_intra_object_redzone +// CHECK: ret void +// + +struct WithVirtualDtor { + virtual ~WithVirtualDtor(); + int x, y; +}; +struct InheritsFrom_WithVirtualDtor: WithVirtualDtor { + int a, b; + InheritsFrom_WithVirtualDtor() {} + ~InheritsFrom_WithVirtualDtor() {} +}; + +void Create_InheritsFrom_WithVirtualDtor() { + InheritsFrom_WithVirtualDtor x; +} + + +// Make sure the dtor of InheritsFrom_WithVirtualDtor remains in the code, +// i.e. we ignore -mconstructor-aliases when field paddings are added +// because the paddings in InheritsFrom_WithVirtualDtor needs to be unpoisoned +// in the dtor. +// WITH_CTOR_ALIASES-LABEL: define void @_Z35Create_InheritsFrom_WithVirtualDtor +// WITH_CTOR_ALIASES-NOT: call void @_ZN15WithVirtualDtorD2Ev +// WITH_CTOR_ALIASES: call void @_ZN28InheritsFrom_WithVirtualDtorD2Ev +// WITH_CTOR_ALIASES: ret void + +// Make sure we don't emit memcpy for operator= if paddings are inserted. +struct ClassWithTrivialCopy { + ClassWithTrivialCopy(); + ~ClassWithTrivialCopy(); + void *a; + private: + void *c; +}; + +void MakeTrivialCopy(ClassWithTrivialCopy *s1, ClassWithTrivialCopy *s2) { + *s1 = *s2; + ClassWithTrivialCopy s3(*s2); +} + +// CHECK-LABEL: define void @_Z15MakeTrivialCopyP20ClassWithTrivialCopyS0_ +// CHECK-NOT: memcpy +// CHECK: ret void diff --git a/test/CodeGen/sanitize-init-order.cpp b/test/CodeGen/sanitize-init-order.cpp index 8c662dbe03439..ee53f7b0771eb 100644 --- a/test/CodeGen/sanitize-init-order.cpp +++ b/test/CodeGen/sanitize-init-order.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s // Test blacklist functionality. -// RUN: echo "global-init-src:%s" > %t-file.blacklist -// RUN: echo "global-init-type:struct.PODWithCtorAndDtor" > %t-type.blacklist +// RUN: echo "src:%s=init" > %t-file.blacklist +// RUN: echo "type:PODWithCtorAndDtor=init" > %t-type.blacklist +// RUN: echo "type:NS::PODWithCtor=init" >> %t-type.blacklist // RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-file.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST // RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-type.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST // REQUIRES: shell @@ -25,14 +26,25 @@ struct PODWithCtorAndDtor { }; PODWithCtorAndDtor s3; +namespace NS { +class PODWithCtor { +public: + PODWithCtor() {} +}; + +const volatile PODWithCtor array[5][5]; +} + // Check that ASan init-order checking ignores structs with trivial default // constructor. -// CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]]} -// CHECK: ![[GLOB_1]] = metadata !{%struct.PODStruct* {{.*}}, i1 false, i1 false} -// CHECK: ![[GLOB_2]] = metadata !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} -// CHECK: ![[GLOB_3]] = metadata !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false} - -// BLACKLIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]]} -// BLACKLIST: ![[GLOB_1]] = metadata !{%struct.PODStruct* {{.*}}, i1 false, i1 false} -// BLACKLIST: ![[GLOB_2]] = metadata !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} -// BLACKLIST: ![[GLOB_3]] = metadata !{%struct.PODWithCtorAndDtor* {{.*}}, i1 false, i1 false} +// CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]], ![[GLOB_4:[0-9]]]} +// CHECK: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} +// CHECK: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} +// CHECK: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false} +// CHECK: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 true, i1 false} + +// BLACKLIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]], ![[GLOB_4:[0-9]]]} +// BLACKLIST: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false} +// BLACKLIST: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false} +// BLACKLIST: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 false, i1 false} +// BLACKLIST: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 false, i1 false} diff --git a/test/CodeGen/sanitize-recover.c b/test/CodeGen/sanitize-recover.c index 3c9c89553813d..b263f51631813 100644 --- a/test/CodeGen/sanitize-recover.c +++ b/test/CodeGen/sanitize-recover.c @@ -1,6 +1,6 @@ -// 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 - +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow -fsanitize-recover=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=RECOVER +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=unsigned-integer-overflow %s -emit-llvm -o - | FileCheck %s --check-prefix=ABORT +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsanitize=null,object-size,alignment -fsanitize-recover=object-size %s -emit-llvm -o - | FileCheck %s --check-prefix=PARTIAL // RECOVER: @test // ABORT: @test @@ -15,3 +15,25 @@ void test() { // ABORT: unreachable x = y + z; } + +void foo() { + union { int i; } u; + u.i=1; + // PARTIAL: %[[CHECK0:.*]] = icmp ne {{.*}}* %[[PTR:.*]], null + + // PARTIAL: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) + // PARTIAL-NEXT: %[[CHECK1:.*]] = icmp uge i64 %[[SIZE]], 4 + + // PARTIAL: %[[MISALIGN:.*]] = and i64 {{.*}}, 3 + // PARTIAL-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 + + // PARTIAL: %[[CHECK02:.*]] = and i1 %[[CHECK0]], %[[CHECK2]] + // PARTIAL-NEXT: %[[CHECK012:.*]] = and i1 %[[CHECK02]], %[[CHECK1]] + + // PARTIAL: br i1 %[[CHECK012]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize + + // PARTIAL: br i1 %[[CHECK02]], {{.*}} + // PARTIAL: call void @__ubsan_handle_type_mismatch_abort( + // PARTIAL-NEXT: unreachable + // PARTIAL: call void @__ubsan_handle_type_mismatch( +} diff --git a/test/CodeGen/sections.c b/test/CodeGen/sections.c deleted file mode 100644 index 8d93fed480e1b..0000000000000 --- a/test/CodeGen/sections.c +++ /dev/null @@ -1,51 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm -fms-extensions -xc++ -o - < %s | FileCheck %s - -#ifdef __cplusplus -extern "C" { -#endif -#pragma const_seg(".my_const") -#pragma bss_seg(".my_bss") -int D = 1; -#pragma data_seg(".data") -int a = 1; -#pragma data_seg(push, label, ".data2") -extern const int b; -const int b = 1; -const char* s = "my string!"; -#pragma data_seg(push, ".my_seg") -int c = 1; -#pragma data_seg(pop, label) -int d = 1; -int e; -#pragma bss_seg(".c") -int f; -void g(void){} -#pragma code_seg(".my_code") -void h(void){} -#pragma bss_seg() -int i; -#pragma bss_seg(".bss1") -#pragma bss_seg(push, test, ".bss2") -#pragma bss_seg() -#pragma bss_seg() -int TEST1; -#pragma bss_seg(pop) -int TEST2; -#ifdef __cplusplus -} -#endif - -//CHECK: @D = global i32 1 -//CHECK: @a = global i32 1, section ".data" -//CHECK: @b = constant i32 1, section ".my_const" -//CHECK: @[[MYSTR:.*]] = {{.*}} unnamed_addr constant [11 x i8] c"my string!\00" -//CHECK: @s = global i8* getelementptr inbounds ([11 x i8]* @[[MYSTR]], i32 0, i32 0), section ".data2" -//CHECK: @c = global i32 1, section ".my_seg" -//CHECK: @d = global i32 1, section ".data" -//CHECK: @e = global i32 0, section ".my_bss" -//CHECK: @f = global i32 0, section ".c" -//CHECK: @i = global i32 0 -//CHECK: @TEST1 = global i32 0 -//CHECK: @TEST2 = global i32 0, section ".bss1" -//CHECK: define void @g() -//CHECK: define void @h() {{.*}} section ".my_code" diff --git a/test/CodeGen/sse-builtins.c b/test/CodeGen/sse-builtins.c index 238454bb92e94..34c2de7d331bc 100644 --- a/test/CodeGen/sse-builtins.c +++ b/test/CodeGen/sse-builtins.c @@ -255,3 +255,291 @@ __m128i test_blend_epi16(__m128i V1, __m128i V2) { // CHECK: shufflevector <8 x i16> %{{.*}}, <8 x i16> %{{.*}}, <8 x i32> <i32 0, i32 9, i32 2, i32 11, i32 4, i32 13, i32 6, i32 7> return _mm_blend_epi16(V1, V2, 42); } + +__m128 test_mm_cmpeq_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpeq_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 0) + return _mm_cmpeq_ss(__a, __b); +} + +__m128 test_mm_cmplt_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmplt_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 1) + return _mm_cmplt_ss(__a, __b); +} + +__m128 test_mm_cmple_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmple_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 2) + return _mm_cmple_ss(__a, __b); +} + +__m128 test_mm_cmpunord_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpunord_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 3) + return _mm_cmpunord_ss(__a, __b); +} + +__m128 test_mm_cmpneq_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpneq_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 4) + return _mm_cmpneq_ss(__a, __b); +} + +__m128 test_mm_cmpnlt_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnlt_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 5) + return _mm_cmpnlt_ss(__a, __b); +} + +__m128 test_mm_cmpnle_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnle_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 6) + return _mm_cmpnle_ss(__a, __b); +} + +__m128 test_mm_cmpord_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpord_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 7) + return _mm_cmpord_ss(__a, __b); +} + +__m128 test_mm_cmpgt_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpgt_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 1) + return _mm_cmpgt_ss(__a, __b); +} + +__m128 test_mm_cmpge_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpge_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 2) + return _mm_cmpge_ss(__a, __b); +} + +__m128 test_mm_cmpngt_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpngt_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 5) + return _mm_cmpngt_ss(__a, __b); +} + +__m128 test_mm_cmpnge_ss(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnge_ss + // CHECK: @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 6) + return _mm_cmpnge_ss(__a, __b); +} + +__m128 test_mm_cmpeq_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpeq_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 0) + return _mm_cmpeq_ps(__a, __b); +} + +__m128 test_mm_cmplt_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmplt_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 1) + return _mm_cmplt_ps(__a, __b); +} + +__m128 test_mm_cmple_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmple_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 2) + return _mm_cmple_ps(__a, __b); +} + +__m128 test_mm_cmpunord_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpunord_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 3) + return _mm_cmpunord_ps(__a, __b); +} + +__m128 test_mm_cmpneq_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpneq_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 4) + return _mm_cmpneq_ps(__a, __b); +} + +__m128 test_mm_cmpnlt_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnlt_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 5) + return _mm_cmpnlt_ps(__a, __b); +} + +__m128 test_mm_cmpnle_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnle_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 6) + return _mm_cmpnle_ps(__a, __b); +} + +__m128 test_mm_cmpord_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpord_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 7) + return _mm_cmpord_ps(__a, __b); +} + +__m128 test_mm_cmpgt_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpgt_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 1) + return _mm_cmpgt_ps(__a, __b); +} + +__m128 test_mm_cmpge_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpge_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 2) + return _mm_cmpge_ps(__a, __b); +} + +__m128 test_mm_cmpngt_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpngt_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 5) + return _mm_cmpngt_ps(__a, __b); +} + +__m128 test_mm_cmpnge_ps(__m128 __a, __m128 __b) { + // CHECK-LABEL: @test_mm_cmpnge_ps + // CHECK: @llvm.x86.sse.cmp.ps(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 6) + return _mm_cmpnge_ps(__a, __b); +} + +__m128d test_mm_cmpeq_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpeq_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 0) + return _mm_cmpeq_sd(__a, __b); +} + +__m128d test_mm_cmplt_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmplt_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 1) + return _mm_cmplt_sd(__a, __b); +} + +__m128d test_mm_cmple_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmple_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 2) + return _mm_cmple_sd(__a, __b); +} + +__m128d test_mm_cmpunord_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpunord_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 3) + return _mm_cmpunord_sd(__a, __b); +} + +__m128d test_mm_cmpneq_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpneq_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 4) + return _mm_cmpneq_sd(__a, __b); +} + +__m128d test_mm_cmpnlt_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnlt_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 5) + return _mm_cmpnlt_sd(__a, __b); +} + +__m128d test_mm_cmpnle_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnle_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 6) + return _mm_cmpnle_sd(__a, __b); +} + +__m128d test_mm_cmpord_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpord_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 7) + return _mm_cmpord_sd(__a, __b); +} + +__m128d test_mm_cmpgt_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpgt_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 1) + return _mm_cmpgt_sd(__a, __b); +} + +__m128d test_mm_cmpge_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpge_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 2) + return _mm_cmpge_sd(__a, __b); +} + +__m128d test_mm_cmpngt_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpngt_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 5) + return _mm_cmpngt_sd(__a, __b); +} + +__m128d test_mm_cmpnge_sd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnge_sd + // CHECK: @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 6) + return _mm_cmpnge_sd(__a, __b); +} + +__m128d test_mm_cmpeq_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpeq_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 0) + return _mm_cmpeq_pd(__a, __b); +} + +__m128d test_mm_cmplt_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmplt_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 1) + return _mm_cmplt_pd(__a, __b); +} + +__m128d test_mm_cmple_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmple_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 2) + return _mm_cmple_pd(__a, __b); +} + +__m128d test_mm_cmpunord_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpunord_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 3) + return _mm_cmpunord_pd(__a, __b); +} + +__m128d test_mm_cmpneq_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpneq_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 4) + return _mm_cmpneq_pd(__a, __b); +} + +__m128d test_mm_cmpnlt_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnlt_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 5) + return _mm_cmpnlt_pd(__a, __b); +} + +__m128d test_mm_cmpnle_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnle_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 6) + return _mm_cmpnle_pd(__a, __b); +} + +__m128d test_mm_cmpord_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpord_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 7) + return _mm_cmpord_pd(__a, __b); +} + +__m128d test_mm_cmpgt_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpgt_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 1) + return _mm_cmpgt_pd(__a, __b); +} + +__m128d test_mm_cmpge_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpge_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 2) + return _mm_cmpge_pd(__a, __b); +} + +__m128d test_mm_cmpngt_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpngt_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 5) + return _mm_cmpngt_pd(__a, __b); +} + +__m128d test_mm_cmpnge_pd(__m128d __a, __m128d __b) { + // CHECK-LABEL: @test_mm_cmpnge_pd + // CHECK: @llvm.x86.sse2.cmp.pd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 6) + return _mm_cmpnge_pd(__a, __b); +} diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c index 5153be9075ed1..d8e77c5352c29 100644 --- a/test/CodeGen/target-data.c +++ b/test/CodeGen/target-data.c @@ -68,7 +68,7 @@ // RUN: %clang_cc1 -triple arm-nacl-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARM-NACL -// ARM-NACL: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S128" +// ARM-NACL: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128" // RUN: %clang_cc1 -triple mipsel-nacl -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=MIPS-NACL @@ -118,7 +118,7 @@ // RUN: | FileCheck %s -check-prefix=R600D // R600D: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64" -// RUN: %clang_cc1 -triple r600-unknown -target-cpu hawaii -o - -emit-llvm %s \ +// RUN: %clang_cc1 -triple amdgcn-unknown -target-cpu hawaii -o - -emit-llvm %s \ // RUN: | FileCheck %s -check-prefix=R600SI // R600SI: target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64" @@ -128,15 +128,15 @@ // RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=THUMB -// THUMB: target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-v128:64:128-a:0:32-n32-S64" +// THUMB: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" // RUN: %clang_cc1 -triple arm-unknown-gnueabi -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=ARM -// ARM: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64" +// ARM: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" // RUN: %clang_cc1 -triple thumb-unknown -o - -emit-llvm -target-abi apcs-gnu \ // RUN: %s | FileCheck %s -check-prefix=THUMB-GNU -// THUMB-GNU: target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +// THUMB-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" // RUN: %clang_cc1 -triple arm-unknown -o - -emit-llvm -target-abi apcs-gnu \ // RUN: %s | FileCheck %s -check-prefix=ARM-GNU @@ -152,7 +152,7 @@ // RUN: %clang_cc1 -triple msp430-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=MSP430 -// MSP430: target datalayout = "e-m:e-p:16:16-i32:16:32-n8:16" +// MSP430: target datalayout = "e-m:e-p:16:16-i32:16:32-a:16-n8:16" // RUN: %clang_cc1 -triple tce-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=TCE diff --git a/test/CodeGen/tbaa-class.cpp b/test/CodeGen/tbaa-class.cpp index bdd155d450a90..a8005d6057245 100644 --- a/test/CodeGen/tbaa-class.cpp +++ b/test/CodeGen/tbaa-class.cpp @@ -198,31 +198,31 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { return b1->a.f32; } -// CHECK: [[TYPE_char:!.*]] = metadata !{metadata !"omnipotent char", metadata [[TAG_cxx_tbaa:!.*]], -// CHECK: [[TAG_cxx_tbaa]] = metadata !{metadata !"Simple C/C++ TBAA"} -// CHECK: [[TAG_i32]] = metadata !{metadata [[TYPE_i32:!.*]], metadata [[TYPE_i32]], i64 0} -// CHECK: [[TYPE_i32]] = metadata !{metadata !"int", metadata [[TYPE_char]], -// CHECK: [[TAG_i16]] = metadata !{metadata [[TYPE_i16:!.*]], metadata [[TYPE_i16]], i64 0} -// CHECK: [[TYPE_i16]] = metadata !{metadata !"short", metadata [[TYPE_char]], - -// PATH: [[TYPE_CHAR:!.*]] = metadata !{metadata !"omnipotent char", metadata -// PATH: [[TAG_i32]] = metadata !{metadata [[TYPE_INT:!.*]], metadata [[TYPE_INT]], i64 0} -// PATH: [[TYPE_INT]] = metadata !{metadata !"int", metadata [[TYPE_CHAR]] -// PATH: [[TAG_A_f32]] = metadata !{metadata [[TYPE_A:!.*]], metadata [[TYPE_INT]], i64 4} -// PATH: [[TYPE_A]] = metadata !{metadata !"_ZTS7StructA", metadata [[TYPE_SHORT:!.*]], i64 0, metadata [[TYPE_INT]], i64 4, metadata [[TYPE_SHORT]], i64 8, metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_SHORT:!.*]] = metadata !{metadata !"short", metadata [[TYPE_CHAR]] -// PATH: [[TAG_A_f16]] = metadata !{metadata [[TYPE_A]], metadata [[TYPE_SHORT]], i64 0} -// PATH: [[TAG_B_a_f32]] = metadata !{metadata [[TYPE_B:!.*]], metadata [[TYPE_INT]], i64 8} -// PATH: [[TYPE_B]] = metadata !{metadata !"_ZTS7StructB", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_A]], i64 4, metadata [[TYPE_INT]], i64 20} -// PATH: [[TAG_B_a_f16]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_SHORT]], i64 4} -// PATH: [[TAG_B_f32]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 20} -// PATH: [[TAG_B_a_f32_2]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 16} -// PATH: [[TAG_S_f32]] = metadata !{metadata [[TYPE_S:!.*]], metadata [[TYPE_INT]], i64 4} -// PATH: [[TYPE_S]] = metadata !{metadata !"_ZTS7StructS", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_INT]], i64 4} -// PATH: [[TAG_S_f16]] = metadata !{metadata [[TYPE_S]], metadata [[TYPE_SHORT]], i64 0} -// PATH: [[TAG_S2_f32_2]] = metadata !{metadata [[TYPE_S2:!.*]], metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_S2]] = metadata !{metadata !"_ZTS8StructS2", metadata [[TYPE_SHORT]], i64 8, metadata [[TYPE_INT]], i64 12} -// PATH: [[TAG_C_b_a_f32]] = metadata !{metadata [[TYPE_C:!.*]], metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_C]] = metadata !{metadata !"_ZTS7StructC", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_B]], i64 4, metadata [[TYPE_INT]], i64 28} -// PATH: [[TAG_D_b_a_f32]] = metadata !{metadata [[TYPE_D:!.*]], metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_D]] = metadata !{metadata !"_ZTS7StructD", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_B]], i64 4, metadata [[TYPE_INT]], i64 28, metadata [[TYPE_CHAR]], i64 32} +// CHECK: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_cxx_tbaa:!.*]], +// CHECK: [[TAG_cxx_tbaa]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// CHECK: [[TYPE_i32]] = !{!"int", [[TYPE_char]], +// CHECK: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0} +// CHECK: [[TYPE_i16]] = !{!"short", [[TYPE_char]], + +// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", ! +// PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} +// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]] +// PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4} +// PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} +// PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]] +// PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8} +// PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20} +// PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4} +// PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20} +// PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16} +// PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4} +// PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4} +// PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12} +// PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} +// PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12} +// PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28} +// PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12} +// PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32} diff --git a/test/CodeGen/tbaa-for-vptr.cpp b/test/CodeGen/tbaa-for-vptr.cpp index ded574ea93762..35e95a54dab21 100644 --- a/test/CodeGen/tbaa-for-vptr.cpp +++ b/test/CodeGen/tbaa-for-vptr.cpp @@ -30,6 +30,6 @@ void CallFoo(A *a, int (A::*fp)() const) { // CHECK-LABEL: @_ZN1AC2Ev // CHECK: store {{.*}} !tbaa ![[NUM]] // -// CHECK: [[NUM]] = metadata !{metadata [[TYPE:!.*]], metadata [[TYPE]], i64 0} -// CHECK: [[TYPE]] = metadata !{metadata !"vtable pointer", metadata !{{.*}} -// NOTBAA-NOT: = metadata !{metadata !"Simple C/C++ TBAA"} +// CHECK: [[NUM]] = !{[[TYPE:!.*]], [[TYPE]], i64 0} +// CHECK: [[TYPE]] = !{!"vtable pointer", !{{.*}} +// NOTBAA-NOT: = !{!"Simple C/C++ TBAA"} diff --git a/test/CodeGen/tbaa-ms-abi.cpp b/test/CodeGen/tbaa-ms-abi.cpp index 2a9e47e408104..878e1b610b59c 100644 --- a/test/CodeGen/tbaa-ms-abi.cpp +++ b/test/CodeGen/tbaa-ms-abi.cpp @@ -16,7 +16,7 @@ StructB::StructB() { // CHECK: store i32 42, i32* {{.*}}, !tbaa [[TAG_A_i32:!.*]] } -// CHECK: [[TYPE_INT:!.*]] = metadata !{metadata !"int", metadata [[TYPE_CHAR:!.*]], i64 0} -// CHECK: [[TYPE_CHAR]] = metadata !{metadata !"omnipotent char", metadata -// CHECK: [[TAG_A_i32]] = metadata !{metadata [[TYPE_A:!.*]], metadata [[TYPE_INT]], i64 0} -// CHECK: [[TYPE_A]] = metadata !{metadata !"?AUStructA@@", metadata [[TYPE_INT]], i64 0} +// CHECK: [[TYPE_INT:!.*]] = !{!"int", [[TYPE_CHAR:!.*]], i64 0} +// CHECK: [[TYPE_CHAR]] = !{!"omnipotent char", ! +// CHECK: [[TAG_A_i32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 0} +// CHECK: [[TYPE_A]] = !{!"?AUStructA@@", [[TYPE_INT]], i64 0} diff --git a/test/CodeGen/tbaa-struct.cpp b/test/CodeGen/tbaa-struct.cpp index 71d3ed11a173d..2623c42c9a3f5 100644 --- a/test/CodeGen/tbaa-struct.cpp +++ b/test/CodeGen/tbaa-struct.cpp @@ -62,14 +62,14 @@ void copy5(struct six *a, struct six *b) { } // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 6, i32 1, i1 false), !tbaa.struct [[TS5:!.*]] -// CHECK: [[TS]] = metadata !{i64 0, i64 2, metadata !{{.*}}, i64 4, i64 4, metadata !{{.*}}, i64 8, i64 1, metadata !{{.*}}, i64 12, i64 4, metadata !{{.*}}} -// CHECK: [[CHAR:!.*]] = metadata !{metadata !"omnipotent char", metadata !{{.*}}} -// CHECK: [[TAG_INT:!.*]] = metadata !{metadata [[INT:!.*]], metadata [[INT]], i64 0} -// CHECK: [[INT]] = metadata !{metadata !"int", metadata [[CHAR]] -// CHECK: [[TAG_CHAR:!.*]] = metadata !{metadata [[CHAR]], metadata [[CHAR]], i64 0} +// CHECK: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}} +// CHECK: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}} +// CHECK: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0} +// CHECK: [[INT]] = !{!"int", [[CHAR]] +// CHECK: [[TAG_CHAR:!.*]] = !{[[CHAR]], [[CHAR]], i64 0} // (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 {{.*}}} +// CHECK: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}} // (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 !{{.*}}} -// CHECK: [[TS4]] = metadata !{i64 0, i64 1, metadata [[TAG_CHAR]], i64 1, i64 4, metadata [[TAG_INT]], i64 1, i64 1, metadata [[TAG_CHAR]], i64 2, i64 1, metadata [[TAG_CHAR]]} -// CHECK: [[TS5]] = metadata !{i64 0, i64 1, metadata [[TAG_CHAR]], i64 4, i64 4, metadata [[TAG_INT]], i64 4, i64 1, metadata [[TAG_CHAR]], i64 5, i64 1, metadata [[TAG_CHAR]]} +// CHECK: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}} +// CHECK: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 4, [[TAG_INT]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]} +// CHECK: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 4, [[TAG_INT]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]} diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp index 92d31e5ae2938..4a723f100ecfd 100644 --- a/test/CodeGen/tbaa.cpp +++ b/test/CodeGen/tbaa.cpp @@ -236,37 +236,37 @@ uint32_t g15(StructS *S, StructS3 *S3, uint64_t count) { return S->f32; } -// CHECK: [[TYPE_char:!.*]] = metadata !{metadata !"omnipotent char", metadata [[TAG_cxx_tbaa:!.*]], -// CHECK: [[TAG_cxx_tbaa]] = metadata !{metadata !"Simple C/C++ TBAA"} -// CHECK: [[TAG_i32]] = metadata !{metadata [[TYPE_i32:!.*]], metadata [[TYPE_i32]], i64 0} -// CHECK: [[TYPE_i32]] = metadata !{metadata !"int", metadata [[TYPE_char]], -// CHECK: [[TAG_i16]] = metadata !{metadata [[TYPE_i16:!.*]], metadata [[TYPE_i16]], i64 0} -// CHECK: [[TYPE_i16]] = metadata !{metadata !"short", metadata [[TYPE_char]], -// CHECK: [[TAG_char]] = metadata !{metadata [[TYPE_char]], metadata [[TYPE_char]], i64 0} +// CHECK: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_cxx_tbaa:!.*]], +// CHECK: [[TAG_cxx_tbaa]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// CHECK: [[TYPE_i32]] = !{!"int", [[TYPE_char]], +// CHECK: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0} +// CHECK: [[TYPE_i16]] = !{!"short", [[TYPE_char]], +// CHECK: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0} -// PATH: [[TYPE_CHAR:!.*]] = metadata !{metadata !"omnipotent char", metadata -// PATH: [[TAG_i32]] = metadata !{metadata [[TYPE_INT:!.*]], metadata [[TYPE_INT]], i64 0} -// PATH: [[TYPE_INT]] = metadata !{metadata !"int", metadata [[TYPE_CHAR]] -// PATH: [[TAG_A_f32]] = metadata !{metadata [[TYPE_A:!.*]], metadata [[TYPE_INT]], i64 4} -// PATH: [[TYPE_A]] = metadata !{metadata !"_ZTS7StructA", metadata [[TYPE_SHORT:!.*]], i64 0, metadata [[TYPE_INT]], i64 4, metadata [[TYPE_SHORT]], i64 8, metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_SHORT:!.*]] = metadata !{metadata !"short", metadata [[TYPE_CHAR]] -// PATH: [[TAG_A_f16]] = metadata !{metadata [[TYPE_A]], metadata [[TYPE_SHORT]], i64 0} -// PATH: [[TAG_B_a_f32]] = metadata !{metadata [[TYPE_B:!.*]], metadata [[TYPE_INT]], i64 8} -// PATH: [[TYPE_B]] = metadata !{metadata !"_ZTS7StructB", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_A]], i64 4, metadata [[TYPE_INT]], i64 20} -// PATH: [[TAG_B_a_f16]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_SHORT]], i64 4} -// PATH: [[TAG_B_f32]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 20} -// PATH: [[TAG_B_a_f32_2]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 16} -// PATH: [[TAG_S_f32]] = metadata !{metadata [[TYPE_S:!.*]], metadata [[TYPE_INT]], i64 4} -// PATH: [[TYPE_S]] = metadata !{metadata !"_ZTS7StructS", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_INT]], i64 4} -// PATH: [[TAG_S_f16]] = metadata !{metadata [[TYPE_S]], metadata [[TYPE_SHORT]], i64 0} -// PATH: [[TAG_S2_f32]] = metadata !{metadata [[TYPE_S2:!.*]], metadata [[TYPE_INT]], i64 4} -// PATH: [[TYPE_S2]] = metadata !{metadata !"_ZTS8StructS2", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_INT]], i64 4} -// PATH: [[TAG_S2_f16]] = metadata !{metadata [[TYPE_S2]], metadata [[TYPE_SHORT]], i64 0} -// PATH: [[TAG_C_b_a_f32]] = metadata !{metadata [[TYPE_C:!.*]], metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_C]] = metadata !{metadata !"_ZTS7StructC", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_B]], i64 4, metadata [[TYPE_INT]], i64 28} -// PATH: [[TAG_D_b_a_f32]] = metadata !{metadata [[TYPE_D:!.*]], metadata [[TYPE_INT]], i64 12} -// PATH: [[TYPE_D]] = metadata !{metadata !"_ZTS7StructD", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_B]], i64 4, metadata [[TYPE_INT]], i64 28, metadata [[TYPE_CHAR]], i64 32} -// PATH: [[TAG_five_b]] = metadata !{metadata [[TYPE_five:!.*]], metadata [[TYPE_CHAR]], i64 1} -// PATH: [[TYPE_five]] = metadata !{metadata !"_ZTS4five", metadata [[TYPE_CHAR]], i64 0, metadata [[TYPE_INT]], i64 1, metadata [[TYPE_CHAR]], i64 1, metadata [[TYPE_CHAR]], i64 2} -// PATH: [[TAG_six_b]] = metadata !{metadata [[TYPE_six:!.*]], metadata [[TYPE_CHAR]], i64 4} -// PATH: [[TYPE_six]] = metadata !{metadata !"_ZTS3six", metadata [[TYPE_CHAR]], i64 0, metadata [[TYPE_INT]], i64 4, metadata [[TYPE_CHAR]], i64 4, metadata [[TYPE_CHAR]], i64 5} +// PATH: [[TYPE_CHAR:!.*]] = !{!"omnipotent char", ! +// PATH: [[TAG_i32]] = !{[[TYPE_INT:!.*]], [[TYPE_INT]], i64 0} +// PATH: [[TYPE_INT]] = !{!"int", [[TYPE_CHAR]] +// PATH: [[TAG_A_f32]] = !{[[TYPE_A:!.*]], [[TYPE_INT]], i64 4} +// PATH: [[TYPE_A]] = !{!"_ZTS7StructA", [[TYPE_SHORT:!.*]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} +// PATH: [[TYPE_SHORT:!.*]] = !{!"short", [[TYPE_CHAR]] +// PATH: [[TAG_A_f16]] = !{[[TYPE_A]], [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_B_a_f32]] = !{[[TYPE_B:!.*]], [[TYPE_INT]], i64 8} +// PATH: [[TYPE_B]] = !{!"_ZTS7StructB", [[TYPE_SHORT]], i64 0, [[TYPE_A]], i64 4, [[TYPE_INT]], i64 20} +// PATH: [[TAG_B_a_f16]] = !{[[TYPE_B]], [[TYPE_SHORT]], i64 4} +// PATH: [[TAG_B_f32]] = !{[[TYPE_B]], [[TYPE_INT]], i64 20} +// PATH: [[TAG_B_a_f32_2]] = !{[[TYPE_B]], [[TYPE_INT]], i64 16} +// PATH: [[TAG_S_f32]] = !{[[TYPE_S:!.*]], [[TYPE_INT]], i64 4} +// PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4} +// PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_S2_f32]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 4} +// PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4} +// PATH: [[TAG_S2_f16]] = !{[[TYPE_S2]], [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12} +// PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28} +// PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12} +// PATH: [[TYPE_D]] = !{!"_ZTS7StructD", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28, [[TYPE_CHAR]], i64 32} +// PATH: [[TAG_five_b]] = !{[[TYPE_five:!.*]], [[TYPE_CHAR]], i64 1} +// PATH: [[TYPE_five]] = !{!"_ZTS4five", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 1, [[TYPE_CHAR]], i64 1, [[TYPE_CHAR]], i64 2} +// PATH: [[TAG_six_b]] = !{[[TYPE_six:!.*]], [[TYPE_CHAR]], i64 4} +// PATH: [[TYPE_six]] = !{!"_ZTS3six", [[TYPE_CHAR]], i64 0, [[TYPE_INT]], i64 4, [[TYPE_CHAR]], i64 4, [[TYPE_CHAR]], i64 5} diff --git a/test/CodeGen/transparent-union.c b/test/CodeGen/transparent-union.c index 21040e4da05b3..2f00c2d21a05f 100644 --- a/test/CodeGen/transparent-union.c +++ b/test/CodeGen/transparent-union.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -o %t %s -// RUN: FileCheck < %t %s -// -// FIXME: Note that we don't currently get the ABI right here. f0() should be -// f0(i8*). +// RUN: %clang_cc1 -Werror -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Werror -triple i386-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Werror -triple armv7-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM +// RUN: %clang_cc1 -Werror -triple powerpc64le-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -Werror -triple aarch64-linux -emit-llvm -o - %s | FileCheck %s typedef union { void *f0; @@ -10,10 +10,15 @@ typedef union { void f0(transp_t0 obj); -// CHECK-LABEL: define void @f1_0(i32* %a0) -// CHECK: call void @f0(%union.transp_t0* byval align 4 %{{.*}}) +// CHECK-LABEL: define void @f1_0(i32* %a0) +// CHECK: call void @f0(i8* %{{.*}}) // CHECK: call void %{{.*}}(i8* %{{[a-z0-9]*}}) // CHECK: } + +// ARM-LABEL: define arm_aapcscc void @f1_0(i32* %a0) +// ARM: call arm_aapcscc void @f0(i8* %{{.*}}) +// ARM: call arm_aapcscc void %{{.*}}(i8* %{{[a-z0-9]*}}) +// ARM: } void f1_0(int *a0) { void (*f0p)(void *) = f0; f0(a0); diff --git a/test/CodeGen/ubsan-type-blacklist.cpp b/test/CodeGen/ubsan-type-blacklist.cpp index 7dc6fe159b514..b3137e7806c76 100644 --- a/test/CodeGen/ubsan-type-blacklist.cpp +++ b/test/CodeGen/ubsan-type-blacklist.cpp @@ -1,9 +1,7 @@ // Verify ubsan vptr does not check down-casts on blacklisted types. // RUN: echo "type:_ZTI3Foo" > %t-type.blacklist -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-blacklist=%t-type.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE - -// REQUIRES: shell +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-recover=vptr -fsanitize-blacklist=%t-type.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE class Bar { public: diff --git a/test/CodeGen/variadic-null-win64.c b/test/CodeGen/variadic-null-win64.c new file mode 100644 index 0000000000000..4f57e7b39f9f9 --- /dev/null +++ b/test/CodeGen/variadic-null-win64.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s --check-prefix=WINDOWS +// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-linux | FileCheck %s --check-prefix=LINUX + +// Make it possible to pass NULL through variadic functions on platforms where +// NULL has an integer type that is more narrow than a pointer. On such +// platforms we widen null pointer constants to a pointer-sized integer. + +#define NULL 0 + +void v(const char *f, ...); +void f(const char *f) { + v(f, 1, 2, 3, NULL); +} +// WINDOWS: define void @f(i8* %f) +// WINDOWS: call void (i8*, ...)* @v(i8* {{.*}}, i32 1, i32 2, i32 3, i64 0) +// LINUX: define void @f(i8* %f) +// LINUX: call void (i8*, ...)* @v(i8* {{.*}}, i32 1, i32 2, i32 3, i32 0) diff --git a/test/CodeGen/vectorcall.c b/test/CodeGen/vectorcall.c new file mode 100644 index 0000000000000..17927c7a3de48 --- /dev/null +++ b/test/CodeGen/vectorcall.c @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=X64 + +void __vectorcall v1(int a, int b) {} +// CHECK: define x86_vectorcallcc void @"\01v1@@8"(i32 inreg %a, i32 inreg %b) +// X64: define x86_vectorcallcc void @"\01v1@@16"(i32 %a, i32 %b) + +void __vectorcall v2(char a, char b) {} +// CHECK: define x86_vectorcallcc void @"\01v2@@8"(i8 inreg signext %a, i8 inreg signext %b) +// X64: define x86_vectorcallcc void @"\01v2@@16"(i8 %a, i8 %b) + +struct Small { int a; }; +void __vectorcall v3(int a, struct Small b, int c) {} +// CHECK: define x86_vectorcallcc void @"\01v3@@12"(i32 inreg %a, %struct.Small* byval align 4 %b, i32 inreg %c) +// X64: define x86_vectorcallcc void @"\01v3@@24"(i32 %a, i32 %b.coerce, i32 %c) + +struct Large { int a[5]; }; +void __vectorcall v4(int a, struct Large b, int c) {} +// CHECK: define x86_vectorcallcc void @"\01v4@@28"(i32 inreg %a, %struct.Large* byval align 4 %b, i32 inreg %c) +// X64: define x86_vectorcallcc void @"\01v4@@40"(i32 %a, %struct.Large* %b, i32 %c) + +struct HFA2 { double x, y; }; +struct HFA4 { double w, x, y, z; }; +struct HFA5 { double v, w, x, y, z; }; + +void __vectorcall hfa1(int a, struct HFA4 b, int c) {} +// CHECK: define x86_vectorcallcc void @"\01hfa1@@40"(i32 inreg %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 inreg %c) +// X64: define x86_vectorcallcc void @"\01hfa1@@48"(i32 %a, double %b.0, double %b.1, double %b.2, double %b.3, i32 %c) + +// HFAs that would require more than six total SSE registers are passed +// indirectly. Additional vector arguments can consume the rest of the SSE +// registers. +void __vectorcall hfa2(struct HFA4 a, struct HFA4 b, double c) {} +// CHECK: define x86_vectorcallcc void @"\01hfa2@@72"(double %a.0, double %a.1, double %a.2, double %a.3, %struct.HFA4* inreg %b, double %c) +// X64: define x86_vectorcallcc void @"\01hfa2@@72"(double %a.0, double %a.1, double %a.2, double %a.3, %struct.HFA4* align 8 %b, double %c) + +// Ensure that we pass builtin types directly while counting them against the +// SSE register usage. +void __vectorcall hfa3(double a, double b, double c, double d, double e, struct HFA2 f) {} +// CHECK: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* inreg %f) +// X64: define x86_vectorcallcc void @"\01hfa3@@56"(double %a, double %b, double %c, double %d, double %e, %struct.HFA2* align 8 %f) + +// Aggregates with more than four elements are not HFAs and are passed byval. +// Because they are not classified as homogeneous, they don't get special +// handling to ensure alignment. +void __vectorcall hfa4(struct HFA5 a) {} +// CHECK: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* byval align 4) +// X64: define x86_vectorcallcc void @"\01hfa4@@40"(%struct.HFA5* %a) + +// Return HFAs of 4 or fewer elements in registers. +static struct HFA2 g_hfa2; +struct HFA2 __vectorcall hfa5(void) { return g_hfa2; } +// CHECK: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"() +// X64: define x86_vectorcallcc %struct.HFA2 @"\01hfa5@@0"() + +typedef float __attribute__((vector_size(16))) v4f32; +struct HVA2 { v4f32 x, y; }; +struct HVA4 { v4f32 w, x, y, z; }; + +void __vectorcall hva1(int a, struct HVA4 b, int c) {} +// CHECK: define x86_vectorcallcc void @"\01hva1@@72"(i32 inreg %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 inreg %c) +// X64: define x86_vectorcallcc void @"\01hva1@@80"(i32 %a, <4 x float> %b.0, <4 x float> %b.1, <4 x float> %b.2, <4 x float> %b.3, i32 %c) + +void __vectorcall hva2(struct HVA4 a, struct HVA4 b, v4f32 c) {} +// CHECK: define x86_vectorcallcc void @"\01hva2@@144"(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, %struct.HVA4* inreg %b, <4 x float> %c) +// X64: define x86_vectorcallcc void @"\01hva2@@144"(<4 x float> %a.0, <4 x float> %a.1, <4 x float> %a.2, <4 x float> %a.3, %struct.HVA4* align 16 %b, <4 x float> %c) + +void __vectorcall hva3(v4f32 a, v4f32 b, v4f32 c, v4f32 d, v4f32 e, struct HVA2 f) {} +// CHECK: define x86_vectorcallcc void @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* inreg %f) +// X64: define x86_vectorcallcc void @"\01hva3@@112"(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, %struct.HVA2* align 16 %f) + +typedef float __attribute__((ext_vector_type(3))) v3f32; +struct OddSizeHVA { v3f32 x, y; }; + +void __vectorcall odd_size_hva(struct OddSizeHVA a) {} +// CHECK: define x86_vectorcallcc void @"\01odd_size_hva@@32"(<3 x float> %a.0, <3 x float> %a.1) +// X64: define x86_vectorcallcc void @"\01odd_size_hva@@32"(<3 x float> %a.0, <3 x float> %a.1) diff --git a/test/CodeGen/vlt_to_pointer.c b/test/CodeGen/vlt_to_pointer.c new file mode 100644 index 0000000000000..22c620aa64298 --- /dev/null +++ b/test/CodeGen/vlt_to_pointer.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +int c[1][3*2]; +// CHECK: @{{.+}} = {{.*}} global [1 x [6 x {{i[0-9]+}}]] zeroinitializer + +// CHECK-LABEL: @f +int f(int * const m, int (**v)[*m * 2]) +{ + return &(c[0][*m]) == &((*v)[0][*m]); + // CHECK: icmp + // CHECK: ret i{{[0-9]+}} +} + +// CHECK-LABEL: @test +int test(int n, int (*(*fn)(void))[n]) { + return (*fn())[0]; +} + +// CHECK-LABEL: @main +int main() +{ + int m = 3; + int (*d)[3*2] = c; + int (*fn[m])(void); + return f(&m, &d) + test(m, &fn); + + // CHECK: call {{.+}} @f( + // CHECK: ret i{{[0-9]+}} +} + diff --git a/test/CodeGen/wchar-const.c b/test/CodeGen/wchar-const.c index 34da249639eae..b461d605f6a92 100644 --- a/test/CodeGen/wchar-const.c +++ b/test/CodeGen/wchar-const.c @@ -7,9 +7,9 @@ typedef __WCHAR_TYPE__ wchar_t; #if defined(_WIN32) || defined(_M_IX86) || defined(__CYGWIN__) \ || defined(_M_X64) || defined(SHORT_WCHAR) #define WCHAR_T_TYPE unsigned short -#elif defined(__sun) || defined(__AuroraUX__) +#elif defined(__sun) #define WCHAR_T_TYPE long -#else /* Solaris or AuroraUX. */ +#else /* Solaris. */ #define WCHAR_T_TYPE int #endif diff --git a/test/CodeGen/windows-struct-abi.c b/test/CodeGen/windows-struct-abi.c new file mode 100644 index 0000000000000..4b4a6f1b5db31 --- /dev/null +++ b/test/CodeGen/windows-struct-abi.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple i686-windows-itanium -emit-llvm -o - %s | FileCheck %s + +struct f1 { + float f; +}; + +struct f1 return_f1(void) { while (1); } + +// CHECK: define i32 @return_f1() + +void receive_f1(struct f1 a0) { } + +// CHECK: define void @receive_f1(%struct.f1* byval align 4 %a0) + +struct f2 { + float f; + float g; +}; + +struct f2 return_f2(void) { while (1); } + +// CHECK: define i64 @return_f2() + +void receive_f2(struct f2 a0) { } + +// CHECK: define void @receive_f2(%struct.f2* byval align 4 %a0) + +struct f4 { + float f; + float g; + float h; + float i; +}; + +struct f4 return_f4(void) { while (1); } + +// CHECK: define void @return_f4(%struct.f4* noalias sret %agg.result) + +void receive_f4(struct f4 a0) { } + +// CHECK: define void @receive_f4(%struct.f4* byval align 4 %a0) + diff --git a/test/CodeGen/x86-atomic-long_double.c b/test/CodeGen/x86-atomic-long_double.c new file mode 100644 index 0000000000000..22c7bd4b89c59 --- /dev/null +++ b/test/CodeGen/x86-atomic-long_double.c @@ -0,0 +1,469 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu core2 %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu core2 %s -S -emit-llvm -o - | FileCheck -check-prefix=CHECK32 %s + +long double testinc(_Atomic long double *addr) { + // CHECK-LABEL: @testinc + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[INC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: ret x86_fp80 [[INC_VALUE]] + // CHECK32-LABEL: @testinc + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE:%.+]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: ret x86_fp80 [[INC_VALUE]] + + return ++*addr; +} + +long double testdec(_Atomic long double *addr) { + // CHECK-LABEL: @testdec + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[ORIG_LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: ret x86_fp80 [[ORIG_LD_VALUE]] + // CHECK32-LABEL: @testdec + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[ORIG_LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: ret x86_fp80 [[ORIG_LD_VALUE]] + + return (*addr)--; +} + +long double testcompassign(_Atomic long double *addr) { + *addr -= 25; + // CHECK-LABEL: @testcompassign + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[SUB_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[SUB_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 8 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VAL:%.+]] = load atomic i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK: [[INT_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i128* + // CHECK: store i128 [[INT_VAL]], i128* [[INT_LD_TEMP:%.+]], align 16 + // CHECK: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 16 + // CHECK: ret x86_fp80 [[RET_VAL]] + // CHECK32-LABEL: @testcompassign + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[INC_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 4 + // CHECK32: [[VOID_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[VOID_GET_ADDR:%.+]] = bitcast x86_fp80* [[GET_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_ADDR]], i8* [[VOID_GET_ADDR]], i32 5) + // CHECK32: [[RET_VAL:%.+]] = load x86_fp80* [[GET_ADDR]], align 4 + // CHECK32: ret x86_fp80 [[RET_VAL]] + return *addr; +} + +long double testassign(_Atomic long double *addr) { + // CHECK-LABEL: @testassign + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 16 + // CHECK: [[STORE_TEMP_INT_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i128* + // CHECK: [[STORE_TEMP_INT:%.+]] = load i128* [[STORE_TEMP_INT_PTR]], align 16 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: store atomic i128 [[STORE_TEMP_INT]], i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK32-LABEL: @testassign + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 4 + // CHECK32: [[ADDR_VOID:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i8* + // CHECK32: call void @__atomic_store(i32 12, i8* [[ADDR_VOID]], i8* [[STORE_TEMP_VOID_PTR]], i32 5) + *addr = 115; + // CHECK: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 8 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VAL:%.+]] = load atomic i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK: [[INT_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i128* + // CHECK: store i128 [[INT_VAL]], i128* [[INT_LD_TEMP:%.+]], align 16 + // CHECK: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 16 + // CHECK: ret x86_fp80 [[RET_VAL]] + // CHECK32: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 4 + // CHECK32: [[VOID_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[VOID_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_ADDR]], i8* [[VOID_LD_TEMP]], i32 5) + // CHECK32: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 4 + // CHECK32: ret x86_fp80 [[RET_VAL]] + + return *addr; +} + +long double test_volatile_inc(volatile _Atomic long double *addr) { + // CHECK-LABEL: @test_volatile_inc + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic volatile i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[INC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg volatile i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: ret x86_fp80 [[INC_VALUE]] + // CHECK32-LABEL: @test_volatile_inc + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[INC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: ret x86_fp80 [[INC_VALUE]] + return ++*addr; +} + +long double test_volatile_dec(volatile _Atomic long double *addr) { + // CHECK-LABEL: @test_volatile_dec + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic volatile i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[ORIG_LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg volatile i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: ret x86_fp80 [[ORIG_LD_VALUE]] + // CHECK32-LABEL: @test_volatile_dec + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[ORIG_LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[ORIG_LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[DEC_VALUE:%.+]] = fadd x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[DEC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: ret x86_fp80 [[ORIG_LD_VALUE]] + return (*addr)--; +} + +long double test_volatile_compassign(volatile _Atomic long double *addr) { + *addr -= 25; + // CHECK-LABEL: @test_volatile_compassign + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VALUE:%.+]] = load atomic volatile i128* [[INT_ADDR]] seq_cst, align 16 + // CHECK: [[INT_LOAD_ADDR:%.+]] = bitcast x86_fp80* [[LD_ADDR:%.+]] to i128* + // CHECK: store i128 [[INT_VALUE]], i128* [[INT_LOAD_ADDR]], align 16 + // CHECK: [[LD_VALUE:%.+]] = load x86_fp80* [[LD_ADDR]], align 16 + // CHECK: br label %[[ATOMIC_OP:.+]] + // CHECK: [[ATOMIC_OP]] + // CHECK: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK: [[SUB_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]], + // CHECK: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 16 + // CHECK: [[OLD_INT_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i128* + // CHECK: [[OLD_INT:%.+]] = load i128* [[OLD_INT_ADDR]], align 16 + // CHECK: [[NEW_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[NEW_VALUE_VOID_ADDR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 [[SUB_VALUE]], x86_fp80* [[NEW_VALUE_ADDR]], align 16 + // CHECK: [[NEW_INT_ADDR:%.+]] = bitcast x86_fp80* [[NEW_VALUE_ADDR]] to i128* + // CHECK: [[NEW_INT:%.+]] = load i128* [[NEW_INT_ADDR]], align 16 + // CHECK: [[OBJ_INT_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[RES:%.+]] = cmpxchg volatile i128* [[OBJ_INT_ADDR]], i128 [[OLD_INT]], i128 [[NEW_INT]] seq_cst seq_cst + // CHECK: [[OLD_VALUE:%.+]] = extractvalue { i128, i1 } [[RES]], 0 + // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i128, i1 } [[RES]], 1 + // CHECK: [[OLD_VALUE_RES_INT_PTR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_RES_PTR:%.+]] to i128* + // CHECK: store i128 [[OLD_VALUE]], i128* [[OLD_VALUE_RES_INT_PTR]], align 16 + // CHECK: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_RES_PTR]], align 16 + // CHECK: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK: [[ATOMIC_CONT]] + // CHECK: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 8 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VAL:%.+]] = load atomic volatile i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK: [[INT_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i128* + // CHECK: store i128 [[INT_VAL]], i128* [[INT_LD_TEMP:%.+]], align 16 + // CHECK: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 16 + // CHECK32-LABEL: @test_volatile_compassign + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[VOID_PTR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[TEMP_LD_PTR:%.+]] = bitcast x86_fp80* [[TEMP_LD_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_PTR]], i8* [[TEMP_LD_PTR]], i32 5) + // CHECK32: [[LD_VALUE:%.+]] = load x86_fp80* [[TEMP_LD_ADDR]], align 4 + // CHECK32: br label %[[ATOMIC_OP:.+]] + // CHECK32: [[ATOMIC_OP]] + // CHECK32: [[OLD_VALUE:%.+]] = phi x86_fp80 [ [[LD_VALUE]], %{{.+}} ], [ [[LD_VALUE:%.+]], %[[ATOMIC_OP]] ] + // CHECK32: [[INC_VALUE:%.+]] = fsub x86_fp80 [[OLD_VALUE]], + // CHECK32: [[OLD_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[OLD_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[OLD_VALUE]], x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: [[DESIRED_VALUE_VOID_ADDR:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[DESIRED_VALUE_VOID_ADDR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 [[INC_VALUE]], x86_fp80* [[DESIRED_VALUE_ADDR]], align 4 + // CHECK32: [[OBJ:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[EXPECTED:%.+]] = bitcast x86_fp80* [[OLD_VALUE_ADDR]] to i8* + // CHECK32: [[DESIRED:%.+]] = bitcast x86_fp80* [[DESIRED_VALUE_ADDR]] to i8* + // CHECK32: [[FAIL_SUCCESS:%.+]] = call zeroext i1 @__atomic_compare_exchange(i32 12, i8* [[OBJ]], i8* [[EXPECTED]], i8* [[DESIRED]], i32 7, i32 7) + // CHECK32: [[LD_VALUE]] = load x86_fp80* [[OLD_VALUE_ADDR]], align 4 + // CHECK32: br i1 [[FAIL_SUCCESS]], label %[[ATOMIC_CONT:.+]], label %[[ATOMIC_OP]] + // CHECK32: [[ATOMIC_CONT]] + // CHECK32: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 4 + // CHECK32: [[VOID_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[VOID_GET_ADDR:%.+]] = bitcast x86_fp80* [[GET_ADDR:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_ADDR]], i8* [[VOID_GET_ADDR]], i32 5) + // CHECK32: [[RET_VAL:%.+]] = load x86_fp80* [[GET_ADDR]], align 4 + // CHECK32: ret x86_fp80 [[RET_VAL]] + return *addr; +} + +long double test_volatile_assign(volatile _Atomic long double *addr) { + // CHECK-LABEL: @test_volatile_assign + // CHECK: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 8 + // CHECK: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 8 + // CHECK: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8* + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 16, i32 16, i1 false) + // CHECK: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 16 + // CHECK: [[STORE_TEMP_INT_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i128* + // CHECK: [[STORE_TEMP_INT:%.+]] = load i128* [[STORE_TEMP_INT_PTR]], align 16 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: store atomic volatile i128 [[STORE_TEMP_INT]], i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK32-LABEL: @test_volatile_assign + // CHECK32: store x86_fp80* %{{.+}}, x86_fp80** [[ADDR_ADDR:%.+]], align 4 + // CHECK32: [[ADDR:%.+]] = load x86_fp80** [[ADDR_ADDR]], align 4 + // CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR:%.+]] to i8* + // CHECK32: call void @llvm.memset.p0i8.i64(i8* [[STORE_TEMP_VOID_PTR]], i8 0, i64 12, i32 4, i1 false) + // CHECK32: store x86_fp80 {{.+}}, x86_fp80* [[STORE_TEMP_PTR]], align 4 + // CHECK32: [[ADDR_VOID:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[STORE_TEMP_VOID_PTR:%.+]] = bitcast x86_fp80* [[STORE_TEMP_PTR]] to i8* + // CHECK32: call void @__atomic_store(i32 12, i8* [[ADDR_VOID]], i8* [[STORE_TEMP_VOID_PTR]], i32 5) + *addr = 115; + // CHECK: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 8 + // CHECK: [[ADDR_INT:%.+]] = bitcast x86_fp80* [[ADDR]] to i128* + // CHECK: [[INT_VAL:%.+]] = load atomic volatile i128* [[ADDR_INT]] seq_cst, align 16 + // CHECK: [[INT_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i128* + // CHECK: store i128 [[INT_VAL]], i128* [[INT_LD_TEMP:%.+]], align 16 + // CHECK: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 16 + // CHECK: ret x86_fp80 [[RET_VAL]] + // CHECK32: [[ADDR:%.+]] = load x86_fp80** %{{.+}}, align 4 + // CHECK32: [[VOID_ADDR:%.+]] = bitcast x86_fp80* [[ADDR]] to i8* + // CHECK32: [[VOID_LD_TEMP:%.+]] = bitcast x86_fp80* [[LD_TEMP:%.+]] to i8* + // CHECK32: call void @__atomic_load(i32 12, i8* [[VOID_ADDR]], i8* [[VOID_LD_TEMP]], i32 5) + // CHECK32: [[RET_VAL:%.+]] = load x86_fp80* [[LD_TEMP]], align 4 + // CHECK32: ret x86_fp80 [[RET_VAL]] + + return *addr; +} diff --git a/test/CodeGen/x86_32-inline-asm.c b/test/CodeGen/x86_32-inline-asm.c index 473f78ebcae61..c1fba0eee942f 100644 --- a/test/CodeGen/x86_32-inline-asm.c +++ b/test/CodeGen/x86_32-inline-asm.c @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -verify %s +// RUN: %clang_cc1 -triple i386-apple-darwin9 -target-feature +avx -verify %s + // <rdar://problem/12415959> +// rdar://problem/11846140 +// rdar://problem/17476970 typedef unsigned int u_int32_t; typedef u_int32_t uint32_t; @@ -7,6 +11,14 @@ typedef u_int32_t uint32_t; typedef unsigned long long u_int64_t; typedef u_int64_t uint64_t; +typedef float __m128 __attribute__ ((vector_size (16))); +typedef float __m256 __attribute__ ((vector_size (32))); +typedef float __m512 __attribute__ ((vector_size (64))); + +__m128 val128; +__m256 val256; +__m512 val512; + int func1() { // Error out if size is > 32-bits. uint32_t msr = 0x8b; @@ -21,4 +33,40 @@ int func1() { unsigned char data; unsigned int port; __asm__ volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); // No error expected. + + __asm__ volatile("outb %0, %w1" : : "R" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'R'}} + __asm__ volatile("outb %0, %w1" : : "q" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'q'}} + __asm__ volatile("outb %0, %w1" : : "Q" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'Q'}} + __asm__ volatile("outb %0, %w1" : : "b" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'b'}} + __asm__ volatile("outb %0, %w1" : : "c" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'c'}} + __asm__ volatile("outb %0, %w1" : : "d" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'd'}} + __asm__ volatile("outb %0, %w1" : : "S" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'S'}} + __asm__ volatile("outb %0, %w1" : : "D" (val), "Nd" (port)); // expected-error {{invalid input size for constraint 'D'}} + __asm__ volatile("foo1 %0" : : "A" (val128)); // expected-error {{invalid input size for constraint 'A'}} + __asm__ volatile("foo1 %0" : : "f" (val256)); // expected-error {{invalid input size for constraint 'f'}} + __asm__ volatile("foo1 %0" : : "t" (val256)); // expected-error {{invalid input size for constraint 't'}} + __asm__ volatile("foo1 %0" : : "u" (val256)); // expected-error {{invalid input size for constraint 'u'}} + __asm__ volatile("foo1 %0" : : "x" (val512)); // expected-error {{invalid input size for constraint 'x'}} + + __asm__ volatile("foo1 %0" : "=R" (val)); // expected-error {{invalid output size for constraint '=R'}} + __asm__ volatile("foo1 %0" : "=q" (val)); // expected-error {{invalid output size for constraint '=q'}} + __asm__ volatile("foo1 %0" : "=Q" (val)); // expected-error {{invalid output size for constraint '=Q'}} + __asm__ volatile("foo1 %0" : "=a" (val)); // expected-error {{invalid output size for constraint '=a'}} + __asm__ volatile("foo1 %0" : "=b" (val)); // expected-error {{invalid output size for constraint '=b'}} + __asm__ volatile("foo1 %0" : "=c" (val)); // expected-error {{invalid output size for constraint '=c'}} + __asm__ volatile("foo1 %0" : "=d" (val)); // expected-error {{invalid output size for constraint '=d'}} + __asm__ volatile("foo1 %0" : "=S" (val)); // expected-error {{invalid output size for constraint '=S'}} + __asm__ volatile("foo1 %0" : "=D" (val)); // expected-error {{invalid output size for constraint '=D'}} + __asm__ volatile("foo1 %0" : "=A" (val128)); // expected-error {{invalid output size for constraint '=A'}} + __asm__ volatile("foo1 %0" : "=t" (val256)); // expected-error {{invalid output size for constraint '=t'}} + __asm__ volatile("foo1 %0" : "=u" (val256)); // expected-error {{invalid output size for constraint '=u'}} + __asm__ volatile("foo1 %0" : "=x" (val512)); // expected-error {{invalid output size for constraint '=x'}} + +#ifdef __AVX__ + __asm__ volatile("foo1 %0" : : "x" (val256)); // No error. + __asm__ volatile("foo1 %0" : "=x" (val256)); // No error. +#else + __asm__ volatile("foo1 %0" : : "x" (val256)); // expected-error {{invalid input size for constraint 'x'}} + __asm__ volatile("foo1 %0" : "=x" (val256)); // expected-error {{invalid output size for constraint '=x'}} +#endif } diff --git a/test/CodeGen/x86_64-arguments-win32.c b/test/CodeGen/x86_64-arguments-win32.c new file mode 100644 index 0000000000000..5aea7fc62368c --- /dev/null +++ b/test/CodeGen/x86_64-arguments-win32.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -w -triple x86_64-pc-win32 -emit-llvm -o - %s | FileCheck %s + +// To be ABI compatible with code generated by MSVC, there shouldn't be any +// sign/zero extensions on types smaller than 64bit. + +// CHECK-LABEL: define void @f1(i8 %a) +void f1(char a) {} + +// CHECK-LABEL: define void @f2(i8 %a) +void f2(unsigned char a) {} + +// CHECK-LABEL: define void @f3(i16 %a) +void f3(short a) {} + +// CHECK-LABEL: define void @f4(i16 %a) +void f4(unsigned short a) {} diff --git a/test/CodeGen/xcore-stringtype.c b/test/CodeGen/xcore-stringtype.c index 25589d5b2b214..1297ca0bb7336 100644 --- a/test/CodeGen/xcore-stringtype.c +++ b/test/CodeGen/xcore-stringtype.c @@ -5,19 +5,27 @@ // In the tests below, some types are not supported by the ABI (_Complex, // variable length arrays) and will thus emit no meta data. -// The 33 tests that do emit typestrings are gathered into '!xcore.typestrings' +// The 38 tests that do emit typestrings are gathered into '!xcore.typestrings' // Please see 'Tools Development Guide' section 2.16.2 for format details: // <https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf> -// CHECK: !xcore.typestrings = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, -// CHECK: !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, -// CHECK: !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38} +// CHECK: !xcore.typestrings = !{ +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, +// CHECK: !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}} +// CHECK-NOT: , !{{[0-9]+}} +// CHECK: } // test BuiltinType -// CHECK: !1 = metadata !{void (i1, i8, i8, i8, i16, i16, i16, i32, i32, i32, +// CHECK: !{{[0-9]+}} = !{void (i1, i8, i8, i8, i16, i16, i16, i32, i32, i32, // CHECK: i32, i32, i32, i64, i64, i64, float, double, double)* -// CHECK: @builtinType, metadata !"f{0}(b,uc,uc,sc,ss,us,ss,si,ui,si,sl, +// CHECK: @builtinType, !"f{0}(b,uc,uc,sc,ss,us,ss,si,ui,si,sl, // CHECK: ul,sl,sll,ull,sll,ft,d,ld)"} void builtinType(_Bool B, char C, unsigned char UC, signed char SC, short S, unsigned short US, signed short SS, int I, unsigned int UI, @@ -28,14 +36,14 @@ double _Complex Complex; // not supported // test FunctionType & Qualifiers -// CHECK: !2 = metadata !{void ()* @gI, metadata !"f{0}()"} -// CHECK: !3 = metadata !{void (...)* @eI, metadata !"f{0}()"} -// CHECK: !4 = metadata !{void ()* @gV, metadata !"f{0}(0)"} -// CHECK: !5 = metadata !{void ()* @eV, metadata !"f{0}(0)"} -// CHECK: !6 = metadata !{void (i32, ...)* @gVA, metadata !"f{0}(si,va)"} -// CHECK: !7 = metadata !{void (i32, ...)* @eVA, metadata !"f{0}(si,va)"} -// CHECK: !8 = metadata !{i32* (i32*)* @gQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"} -// CHECK: !9 = metadata !{i32* (i32*)* @eQ, metadata !"f{crv:p(cv:si)}(p(cv:si))"} +// CHECK: !{{[0-9]+}} = !{void ()* @gI, !"f{0}()"} +// CHECK: !{{[0-9]+}} = !{void (...)* @eI, !"f{0}()"} +// CHECK: !{{[0-9]+}} = !{void ()* @gV, !"f{0}(0)"} +// CHECK: !{{[0-9]+}} = !{void ()* @eV, !"f{0}(0)"} +// CHECK: !{{[0-9]+}} = !{void (i32, ...)* @gVA, !"f{0}(si,va)"} +// CHECK: !{{[0-9]+}} = !{void (i32, ...)* @eVA, !"f{0}(si,va)"} +// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @gQ, !"f{crv:p(cv:si)}(p(cv:si))"} +// CHECK: !{{[0-9]+}} = !{i32* (i32*)* @eQ, !"f{crv:p(cv:si)}(p(cv:si))"} extern void eI(); void gI() {eI();}; extern void eV(void); @@ -49,10 +57,10 @@ const volatile int* volatile restrict const // test PointerType -// CHECK: !10 = metadata !{i32* (i32*, i32* (i32*)*)* -// CHECK: @pointerType, metadata !"f{p(si)}(p(si),p(f{p(si)}(p(si))))"} -// CHECK: !11 = metadata !{i32** @EP, metadata !"p(si)"} -// CHECK: !12 = metadata !{i32** @GP, metadata !"p(si)"} +// CHECK: !{{[0-9]+}} = !{i32* (i32*, i32* (i32*)*)* +// CHECK: @pointerType, !"f{p(si)}(p(si),p(f{p(si)}(p(si))))"} +// CHECK: !{{[0-9]+}} = !{i32** @EP, !"p(si)"} +// CHECK: !{{[0-9]+}} = !{i32** @GP, !"p(si)"} extern int* EP; int* GP; int* pointerType(int *I, int * (*FP)(int *)) { @@ -60,19 +68,19 @@ int* pointerType(int *I, int * (*FP)(int *)) { } // test ArrayType -// CHECK: !13 = metadata !{[2 x i32]* (i32*, i32*, [2 x i32]*, [2 x i32]*, i32*)* -// CHECK: @arrayType, metadata !"f{p(a(2:si))}(p(si),p(cv:si),p(a(2:si)), +// CHECK: !{{[0-9]+}} = !{[2 x i32]* (i32*, i32*, [2 x i32]*, [2 x i32]*, i32*)* +// CHECK: @arrayType, !"f{p(a(2:si))}(p(si),p(cv:si),p(a(2:si)), // CHECK: p(a(2:si)),p(si))"} -// CHECK: !14 = metadata !{[0 x i32]* @EA1, metadata !"a(*:cv:si)"} -// CHECK: !15 = metadata !{[2 x i32]* @EA2, metadata !"a(2:si)"} -// CHECK: !16 = metadata !{[0 x [2 x i32]]* @EA3, metadata !"a(*:a(2:si))"} -// CHECK: !17 = metadata !{[3 x [2 x i32]]* @EA4, metadata !"a(3:a(2:si))"} -// CHECK: !18 = metadata !{[2 x i32]* @GA1, metadata !"a(2:cv:si)"} -// CHECK: !19 = metadata !{void ([2 x i32]*)* @arrayTypeVariable1, -// CHECK: metadata !"f{0}(p(a(2:si)))"} -// CHECK: !20 = metadata !{void (void ([2 x i32]*)*)* @arrayTypeVariable2, -// CHECK: metadata !"f{0}(p(f{0}(p(a(2:si)))))"} -// CHECK: !21 = metadata !{[3 x [2 x i32]]* @GA2, metadata !"a(3:a(2:si))"} +// CHECK: !{{[0-9]+}} = !{[0 x i32]* @EA1, !"a(*:cv:si)"} +// CHECK: !{{[0-9]+}} = !{[2 x i32]* @EA2, !"a(2:si)"} +// CHECK: !{{[0-9]+}} = !{[0 x [2 x i32]]* @EA3, !"a(*:a(2:si))"} +// CHECK: !{{[0-9]+}} = !{[3 x [2 x i32]]* @EA4, !"a(3:a(2:si))"} +// CHECK: !{{[0-9]+}} = !{[2 x i32]* @GA1, !"a(2:cv:si)"} +// CHECK: !{{[0-9]+}} = !{void ([2 x i32]*)* @arrayTypeVariable1, +// CHECK: !"f{0}(p(a(2:si)))"} +// CHECK: !{{[0-9]+}} = !{void (void ([2 x i32]*)*)* @arrayTypeVariable2, +// CHECK: !"f{0}(p(f{0}(p(a(2:si)))))"} +// CHECK: !{{[0-9]+}} = !{[3 x [2 x i32]]* @GA2, !"a(3:a(2:si))"} extern int GA2[3][2]; extern const volatile int EA1[]; extern int EA2[2]; @@ -100,16 +108,16 @@ RetType* arrayType(int A1[], int const volatile A2[2], int A3[][2], // test StructureType -// CHECK: !22 = metadata !{void (%struct.S1*)* @structureType1, metadata +// CHECK: !{{[0-9]+}} = !{void (%struct.S1*)* @structureType1, // CHECK: !"f{0}(s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){m(s1){s(S1){}}})}})}})"} -// CHECK: !23 = metadata !{void (%struct.S2*)* @structureType2, metadata +// CHECK: !{{[0-9]+}} = !{void (%struct.S2*)* @structureType2, // CHECK: !"f{0}(s(S2){m(ps3){p(s(S3){m(s1){s(S1){m(ps2){p(s(S2){})}}}})}})"} -// CHECK: !24 = metadata !{void (%struct.S3*)* @structureType3, metadata +// CHECK: !{{[0-9]+}} = !{void (%struct.S3*)* @structureType3, // CHECK: !"f{0}(s(S3){m(s1){s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){})}})}}}})"} -// CHECK: !25 = metadata !{void (%struct.S4*)* @structureType4, metadata +// CHECK: !{{[0-9]+}} = !{void (%struct.S4*)* @structureType4, // CHECK: !"f{0}(s(S4){m(s1){s(S1){m(ps2){p(s(S2){m(ps3){p(s(S3){m(s1){s(S1){}}})}})}}}})"} -// CHECK: !26 = metadata !{%struct.anon* @StructAnon, metadata !"s(){m(A){si}}"} -// CHECK: !27 = metadata !{i32 (%struct.SB*)* @structureTypeB, metadata +// CHECK: !{{[0-9]+}} = !{%struct.anon* @StructAnon, !"s(){m(A){si}}"} +// CHECK: !{{[0-9]+}} = !{i32 (%struct.SB*)* @structureTypeB, // CHECK: !"f{si}(s(SB){m(){b(4:si)},m(){b(2:si)},m(N4){b(4:si)}, // CHECK: m(N2){b(2:si)},m(){b(4:ui)},m(){b(4:si)},m(){b(4:c:si)}, // CHECK: m(){b(4:c:si)},m(){b(4:cv:si)}})"} @@ -130,16 +138,16 @@ int structureTypeB(struct SB sb){return StructAnon.A;} // test UnionType -// CHECK: !28 = metadata !{void (%union.U1*)* @unionType1, metadata +// CHECK: !{{[0-9]+}} = !{void (%union.U1*)* @unionType1, // CHECK: !"f{0}(u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){m(u1){u(U1){}}})}})}})"} -// CHECK: !29 = metadata !{void (%union.U2*)* @unionType2, metadata +// CHECK: !{{[0-9]+}} = !{void (%union.U2*)* @unionType2, // CHECK: !"f{0}(u(U2){m(pu3){p(u(U3){m(u1){u(U1){m(pu2){p(u(U2){})}}}})}})"} -// CHECK: !30 = metadata !{void (%union.U3*)* @unionType3, metadata +// CHECK: !{{[0-9]+}} = !{void (%union.U3*)* @unionType3, // CHECK: !"f{0}(u(U3){m(u1){u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){})}})}}}})"} -// CHECK: !31 = metadata !{void (%union.U4*)* @unionType4, metadata +// CHECK: !{{[0-9]+}} = !{void (%union.U4*)* @unionType4, // CHECK: !"f{0}(u(U4){m(u1){u(U1){m(pu2){p(u(U2){m(pu3){p(u(U3){m(u1){u(U1){}}})}})}}}})"} -// CHECK: !32 = metadata !{%union.anon* @UnionAnon, metadata !"u(){m(A){si}}"} -// CHECK: !33 = metadata !{i32 (%union.UB*)* @unionTypeB, metadata +// CHECK: !{{[0-9]+}} = !{%union.anon* @UnionAnon, !"u(){m(A){si}}"} +// CHECK: !{{[0-9]+}} = !{i32 (%union.UB*)* @unionTypeB, // CHECK: !"f{si}(u(UB){m(N2){b(2:si)},m(N4){b(4:si)},m(){b(2:si)}, // CHECK: m(){b(4:c:si)},m(){b(4:c:si)},m(){b(4:cv:si)},m(){b(4:si)}, // CHECK: m(){b(4:si)},m(){b(4:ui)}})"} @@ -160,17 +168,17 @@ int unionTypeB(union UB ub) {return UnionAnon.A;} // test EnumType -// CHECK: !34 = metadata !{i32* @EnumAnon, metadata !"e(){m(EA){3}}"} -// CHECK: !35 = metadata !{i32 (i32)* @enumType, metadata +// CHECK: !{{[0-9]+}} = !{i32* @EnumAnon, !"e(){m(EA){3}}"} +// CHECK: !{{[0-9]+}} = !{i32 (i32)* @enumType, // CHECK: !"f{si}(e(E){m(A){7},m(B){6},m(C){5},m(D){0}})"} enum E {D, C=5, B, A}; enum {EA=3} EnumAnon = EA; int enumType(enum E e) {return EnumAnon;} -// CHECK: !36 = metadata !{i32 ()* @testReDecl, metadata !"f{si}()"} -// CHECK: !37 = metadata !{[10 x i32]* @After, metadata !"a(10:si)"} -// CHECK: !38 = metadata !{[10 x i32]* @Before, metadata !"a(10:si)"} +// CHECK: !{{[0-9]+}} = !{i32 ()* @testReDecl, !"f{si}()"} +// CHECK: !{{[0-9]+}} = !{[10 x i32]* @After, !"a(10:si)"} +// CHECK: !{{[0-9]+}} = !{[10 x i32]* @Before, !"a(10:si)"} extern int After[]; extern int Before[10]; int testReDecl() {return After[0] + Before[0];} |