From 06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 18 Jan 2015 16:23:48 +0000 Subject: Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1): https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1@226102 --- test/CodeGen/2003-08-21-WideString.c | 4 +- .../CodeGen/2005-06-15-ExpandGotoInternalProblem.c | 2 +- test/CodeGen/2005-09-24-AsmUserPrefix.c | 2 +- test/CodeGen/2007-06-18-SextAttrAggregate.c | 4 +- ...2008-07-22-bitfield-init-after-zero-len-array.c | 3 +- test/CodeGen/2009-07-15-pad-wchar_t-array.c | 4 +- test/CodeGen/2009-10-20-GlobalDebug.c | 4 +- test/CodeGen/2010-02-15-DbgStaticVar.c | 3 +- test/CodeGen/2010-07-08-DeclDebugLineNo.c | 4 +- test/CodeGen/24-bit.c | 14 + test/CodeGen/Atomics.c | 43 ++ test/CodeGen/aarch64-fix-cortex-a53-835769.c | 27 ++ test/CodeGen/aarch64-poly64.c | 12 + test/CodeGen/aarch64-type-sizes.c | 2 +- test/CodeGen/aarch64-varargs.c | 2 +- test/CodeGen/adc-builtins.c | 33 ++ test/CodeGen/address-safety-attr.cpp | 70 ++- .../CodeGen/address-sanitizer-and-array-cookie.cpp | 55 +++ test/CodeGen/adx-builtins.c | 18 + test/CodeGen/alias.c | 7 +- test/CodeGen/align_value.cpp | 103 +++++ test/CodeGen/arm-aapcs-vfp.c | 25 +- test/CodeGen/arm-arguments.c | 9 +- test/CodeGen/arm-homogenous.c | 20 +- test/CodeGen/arm-metadata.c | 12 +- test/CodeGen/arm-neon-directed-rounding.c | 75 ++++ test/CodeGen/arm-neon-numeric-maxmin.c | 27 ++ test/CodeGen/arm64-aapcs-arguments.c | 15 +- test/CodeGen/arm64-arguments.c | 15 +- test/CodeGen/arm64-be-bitfield.c | 12 +- test/CodeGen/arm64-be-hfa-vararg.c | 2 +- test/CodeGen/arm64-lanes.c | 2 +- test/CodeGen/arm_acle.c | 155 ++++++- test/CodeGen/arm_neon_intrinsics.c | 168 ++++--- test/CodeGen/asan-globals.cpp | 45 +- test/CodeGen/asm.c | 14 + test/CodeGen/atomic-ops-libcall.c | 10 +- test/CodeGen/atomic-ops.c | 178 +++++++- test/CodeGen/atomic.c | 10 +- test/CodeGen/atomic_ops.c | 6 +- test/CodeGen/atomics-inlining.c | 24 +- test/CodeGen/attr-naked.c | 10 +- test/CodeGen/attr-optnone.c | 21 +- test/CodeGen/attributes.c | 2 +- test/CodeGen/avx2-builtins.c | 2 +- test/CodeGen/avx512bw-builtins.c | 27 ++ test/CodeGen/avx512f-builtins.c | 212 +++++++++ test/CodeGen/avx512vl-builtins.c | 51 +++ test/CodeGen/avx512vlbw-builtins.c | 51 +++ test/CodeGen/block-with-perdefinedexpr.c | 14 + test/CodeGen/bmi2-builtins.c | 6 +- test/CodeGen/bool_test.c | 2 +- test/CodeGen/builtin-assume-aligned.c | 67 +++ test/CodeGen/builtin-assume.c | 23 +- test/CodeGen/builtin-recursive.cc | 10 - test/CodeGen/builtin-recursive.cpp | 10 + test/CodeGen/builtins-arm-msvc-compat-error.c | 6 + test/CodeGen/builtins-arm-msvc-compat-only.c | 19 + test/CodeGen/builtins-arm.c | 18 + test/CodeGen/builtins-arm64.c | 14 + test/CodeGen/builtins-nvptx.c | 2 + test/CodeGen/builtins-ppc-altivec.c | 4 +- test/CodeGen/builtins-ppc-vsx.c | 116 +++++ test/CodeGen/builtins-x86.c | 2 +- test/CodeGen/builtins.c | 33 +- test/CodeGen/c11atomics-ios.c | 8 +- test/CodeGen/c11atomics.c | 14 +- test/CodeGen/captured-statements-nested.c | 74 ++-- test/CodeGen/captured-statements.c | 11 +- test/CodeGen/catch-undef-behavior.c | 417 ++++++++---------- test/CodeGen/complex-math.c | 481 +++++++++++++++++++++ test/CodeGen/complex.c | 16 + test/CodeGen/compound-assign-overflow.c | 2 +- test/CodeGen/const-init.c | 22 + test/CodeGen/debug-info-args.c | 4 +- test/CodeGen/debug-info-block-decl.c | 4 +- test/CodeGen/debug-info-block-out-return.c | 25 ++ test/CodeGen/debug-info-enum.c | 6 +- test/CodeGen/debug-info-line3.c | 2 +- test/CodeGen/debug-info-line4.c | 2 +- test/CodeGen/debug-info-scope-file.c | 4 +- test/CodeGen/debug-info-scope.c | 12 + test/CodeGen/debug-info-typedef.c | 4 +- test/CodeGen/debug-info-version.c | 4 +- test/CodeGen/debug-info-vla.c | 2 +- test/CodeGen/debug-info.c | 2 +- test/CodeGen/dependent-lib.c | 12 +- test/CodeGen/designated-initializers.c | 3 + test/CodeGen/dllimport.c | 56 ++- test/CodeGen/dwarf-version.c | 7 +- test/CodeGen/ext-vector-indexing.c | 14 + test/CodeGen/fp128_complex.c | 9 + test/CodeGen/fsgsbase-builtins.c | 54 +++ test/CodeGen/lineno-dbginfo.c | 7 +- test/CodeGen/linetable-endscope.c | 4 +- test/CodeGen/link-bitcode-file.c | 2 +- test/CodeGen/lzcnt-builtins.c | 12 + test/CodeGen/mangle-blocks.c | 23 + test/CodeGen/mangle-windows.c | 39 +- test/CodeGen/may-alias.c | 24 +- test/CodeGen/merge-statics.c | 5 +- test/CodeGen/microsoft-call-conv.c | 12 +- test/CodeGen/mips-constraint-regs.c | 6 +- test/CodeGen/mips-constraints-mem.c | 2 +- test/CodeGen/mips-inline-asm-modifiers.c | 6 +- test/CodeGen/mips-transparent-union.c | 27 ++ test/CodeGen/mips-varargs.c | 115 +++-- test/CodeGen/mmx-inline-asm-error.c | 6 +- test/CodeGen/mozilla-ms-inline-asm.c | 17 +- test/CodeGen/mrtd.c | 4 +- test/CodeGen/ms-align-tentative.c | 15 + test/CodeGen/ms-declspecs.c | 4 +- test/CodeGen/ms-inline-asm-functions.c | 60 +++ test/CodeGen/ms-inline-asm.c | 317 ++++++++------ test/CodeGen/ms-inline-asm.cpp | 46 +- test/CodeGen/ms-intrinsics.c | 59 ++- test/CodeGen/mult-alt-generic.c | 2 +- test/CodeGen/named_reg_global.c | 2 +- test/CodeGen/nonnull.c | 28 ++ test/CodeGen/nvptx-abi.c | 34 +- test/CodeGen/piclevels.c | 7 + test/CodeGen/ppc-signbit.c | 11 + test/CodeGen/ppc-varargs-struct.c | 112 +++++ test/CodeGen/ppc64-elf-abi.c | 40 ++ test/CodeGen/ppc64-varargs-struct.c | 30 -- test/CodeGen/ppc64le-aggregates.c | 6 +- test/CodeGen/pr5406.c | 2 +- test/CodeGen/pragma-comment.c | 20 +- test/CodeGen/pragma-detect_mismatch.c | 24 +- test/CodeGen/pragma-loop.cpp | 120 +++-- test/CodeGen/pragma-unroll.cpp | 24 +- test/CodeGen/pragma-weak.c | 20 +- test/CodeGen/predefined-expr.c | 4 +- test/CodeGen/sanitize-address-field-padding.cpp | 237 ++++++++++ test/CodeGen/sanitize-init-order.cpp | 34 +- test/CodeGen/sanitize-recover.c | 28 +- test/CodeGen/sections.c | 51 --- test/CodeGen/sse-builtins.c | 288 ++++++++++++ test/CodeGen/target-data.c | 12 +- test/CodeGen/tbaa-class.cpp | 56 +-- test/CodeGen/tbaa-for-vptr.cpp | 6 +- test/CodeGen/tbaa-ms-abi.cpp | 8 +- test/CodeGen/tbaa-struct.cpp | 18 +- test/CodeGen/tbaa.cpp | 66 +-- test/CodeGen/transparent-union.c | 19 +- test/CodeGen/ubsan-type-blacklist.cpp | 6 +- test/CodeGen/variadic-null-win64.c | 17 + test/CodeGen/vectorcall.c | 77 ++++ test/CodeGen/vlt_to_pointer.c | 30 ++ test/CodeGen/wchar-const.c | 4 +- test/CodeGen/windows-struct-abi.c | 42 ++ test/CodeGen/x86-atomic-long_double.c | 469 ++++++++++++++++++++ test/CodeGen/x86_32-inline-asm.c | 48 ++ test/CodeGen/x86_64-arguments-win32.c | 16 + test/CodeGen/xcore-stringtype.c | 102 +++-- 155 files changed, 5045 insertions(+), 1120 deletions(-) create mode 100644 test/CodeGen/24-bit.c create mode 100644 test/CodeGen/aarch64-fix-cortex-a53-835769.c create mode 100644 test/CodeGen/adc-builtins.c create mode 100644 test/CodeGen/address-sanitizer-and-array-cookie.cpp create mode 100644 test/CodeGen/adx-builtins.c create mode 100644 test/CodeGen/align_value.cpp create mode 100644 test/CodeGen/arm-neon-directed-rounding.c create mode 100644 test/CodeGen/arm-neon-numeric-maxmin.c create mode 100644 test/CodeGen/avx512bw-builtins.c create mode 100644 test/CodeGen/avx512f-builtins.c create mode 100644 test/CodeGen/avx512vl-builtins.c create mode 100644 test/CodeGen/avx512vlbw-builtins.c create mode 100644 test/CodeGen/block-with-perdefinedexpr.c create mode 100644 test/CodeGen/builtin-assume-aligned.c delete mode 100644 test/CodeGen/builtin-recursive.cc create mode 100644 test/CodeGen/builtin-recursive.cpp create mode 100644 test/CodeGen/builtins-arm-msvc-compat-error.c create mode 100644 test/CodeGen/builtins-arm-msvc-compat-only.c create mode 100644 test/CodeGen/builtins-ppc-vsx.c create mode 100644 test/CodeGen/complex-math.c create mode 100644 test/CodeGen/debug-info-block-out-return.c create mode 100644 test/CodeGen/ext-vector-indexing.c create mode 100644 test/CodeGen/fp128_complex.c create mode 100644 test/CodeGen/fsgsbase-builtins.c create mode 100644 test/CodeGen/mangle-blocks.c create mode 100644 test/CodeGen/mips-transparent-union.c create mode 100644 test/CodeGen/ms-align-tentative.c create mode 100644 test/CodeGen/ms-inline-asm-functions.c create mode 100644 test/CodeGen/piclevels.c create mode 100644 test/CodeGen/ppc-signbit.c create mode 100644 test/CodeGen/ppc-varargs-struct.c create mode 100644 test/CodeGen/ppc64-elf-abi.c delete mode 100644 test/CodeGen/ppc64-varargs-struct.c create mode 100644 test/CodeGen/sanitize-address-field-padding.cpp delete mode 100644 test/CodeGen/sections.c create mode 100644 test/CodeGen/variadic-null-win64.c create mode 100644 test/CodeGen/vectorcall.c create mode 100644 test/CodeGen/vlt_to_pointer.c create mode 100644 test/CodeGen/windows-struct-abi.c create mode 100644 test/CodeGen/x86-atomic-long_double.c create mode 100644 test/CodeGen/x86_64-arguments-win32.c (limited to 'test/CodeGen') 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 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 + +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 + +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 + +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 + +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 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 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"\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]+]], !"", 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 -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 __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 + +__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 + +__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> {{.*}} + 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> {{.*}} + 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> {{.*}} + 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> {{.*}} + 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> {{.*}} + 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 + +__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 + +__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.cc deleted file mode 100644 index 81e9b9a37c256..0000000000000 --- a/test/CodeGen/builtin-recursive.cc +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -nostdsysteminc -nobuiltininc -isystem Inputs -emit-llvm-only %s - -// This used to cause a read past the end of a global variable. - -#include - -void testcase(void) { - vprintf(0, 0); -} - diff --git a/test/CodeGen/builtin-recursive.cpp b/test/CodeGen/builtin-recursive.cpp new file mode 100644 index 0000000000000..7553a6e48f532 --- /dev/null +++ b/test/CodeGen/builtin-recursive.cpp @@ -0,0 +1,10 @@ +// 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. + +#include + +void testcase(void) { + vprintf(0, 0); +} + 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 . -// 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 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 + +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 " > %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 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::create - // 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 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 + +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 - -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(Tuner::Interleave)) +#pragma clang loop unroll_count(static_cast(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 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 +template 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 +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(List, Length, Value); - for_template_define_test(List, Length, Value); + for_template_define_test(List, Length, Value); + for_template_constant_expression_test(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(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> 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/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: // -// 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];} -- cgit v1.3