diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGen/attr-target-mv-func-ptrs.c | 32 | ||||
| -rw-r--r-- | clang/test/CodeGen/attr-target-mv-va-args.c | 26 | ||||
| -rw-r--r-- | clang/test/CodeGen/attr-target-mv.c | 79 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp | 54 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp | 45 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp | 137 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-modules.cpp | 29 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp | 39 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/attr-target-mv-overloads.cpp | 50 | ||||
| -rw-r--r-- | clang/test/Sema/attr-target-mv-bad-target.c | 10 | ||||
| -rw-r--r-- | clang/test/Sema/attr-target-mv.c | 103 | ||||
| -rw-r--r-- | clang/test/SemaCXX/attr-target-mv.cpp | 178 |
12 files changed, 782 insertions, 0 deletions
diff --git a/clang/test/CodeGen/attr-target-mv-func-ptrs.c b/clang/test/CodeGen/attr-target-mv-func-ptrs.c new file mode 100644 index 00000000000..5df9a927cf8 --- /dev/null +++ b/clang/test/CodeGen/attr-target-mv-func-ptrs.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +int __attribute__((target("sse4.2"))) foo(int i) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int i) {return 1;} +int __attribute__((target("default"))) foo(int i) { return 2; } + +typedef int (*FuncPtr)(int); +void func(FuncPtr); + +int bar() { + func(foo); + FuncPtr Free = &foo; + FuncPtr Free2 = foo; + + return 0; + return Free(1) + Free(2); +} + +// CHECK: @foo.ifunc = ifunc i32 (i32), i32 (i32)* ()* @foo.resolver +// CHECK: define i32 @foo.sse4.2( +// CHECK: ret i32 0 +// CHECK: define i32 @foo.arch_ivybridge( +// CHECK: ret i32 1 +// CHECK: define i32 @foo( +// CHECK: ret i32 2 + +// CHECK: define i32 @bar() +// CHECK: call void @func(i32 (i32)* @foo.ifunc) +// CHECK: store i32 (i32)* @foo.ifunc +// CHECK: store i32 (i32)* @foo.ifunc + +// CHECK: declare i32 @foo.arch_sandybridge( diff --git a/clang/test/CodeGen/attr-target-mv-va-args.c b/clang/test/CodeGen/attr-target-mv-va-args.c new file mode 100644 index 00000000000..c5d92dbfadc --- /dev/null +++ b/clang/test/CodeGen/attr-target-mv-va-args.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +int __attribute__((target("sse4.2"))) foo(int i, ...) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int i, ...); +int __attribute__((target("arch=ivybridge"))) foo(int i, ...) {return 1;} +int __attribute__((target("default"))) foo(int i, ...) { return 2; } + +int bar() { + return foo(1, 'a', 1.1) + foo(2, 2.2, "asdf"); +} + +// CHECK: @foo.ifunc = ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver +// CHECK: define i32 @foo.sse4.2(i32 %i, ...) +// CHECK: ret i32 0 +// CHECK: define i32 @foo.arch_ivybridge(i32 %i, ...) +// CHECK: ret i32 1 +// CHECK: define i32 @foo(i32 %i, ...) +// CHECK: ret i32 2 +// CHECK: define i32 @bar() +// CHECK: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double +// CHECK: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds +// CHECK: define i32 (i32, ...)* @foo.resolver() +// CHECK: ret i32 (i32, ...)* @foo.arch_sandybridge +// CHECK: ret i32 (i32, ...)* @foo.arch_ivybridge +// CHECK: ret i32 (i32, ...)* @foo.sse4.2 +// CHECK: ret i32 (i32, ...)* @foo +// CHECK: declare i32 @foo.arch_sandybridge(i32, ...) diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c new file mode 100644 index 00000000000..a877fd6e8d4 --- /dev/null +++ b/clang/test/CodeGen/attr-target-mv.c @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +int __attribute__((target("sse4.2"))) foo(void) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(void); +int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;} +int __attribute__((target("default"))) foo(void) { return 2; } + +int bar() { + return foo(); +} + +inline int __attribute__((target("sse4.2"))) foo_inline(void) { return 0; } +inline int __attribute__((target("arch=sandybridge"))) foo_inline(void); +inline int __attribute__((target("arch=ivybridge"))) foo_inline(void) {return 1;} +inline int __attribute__((target("default"))) foo_inline(void) { return 2; } + +int bar2() { + return foo_inline(); +} + +inline __attribute__((target("default"))) void foo_decls(void); +inline __attribute__((target("sse4.2"))) void foo_decls(void); +void bar3() { + foo_decls(); +} +inline __attribute__((target("default"))) void foo_decls(void) {} +inline __attribute__((target("sse4.2"))) void foo_decls(void) {} + +// CHECK: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver +// CHECK: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver +// CHECK: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver + +// CHECK: define i32 @foo.sse4.2() +// CHECK: ret i32 0 +// CHECK: define i32 @foo.arch_ivybridge() +// CHECK: ret i32 1 +// CHECK: define i32 @foo() +// CHECK: ret i32 2 +// CHECK: define i32 @bar() +// CHECK: call i32 @foo.ifunc() + +// CHECK: define i32 ()* @foo.resolver() +// CHECK: call void @__cpu_indicator_init() +// CHECK: ret i32 ()* @foo.arch_sandybridge +// CHECK: ret i32 ()* @foo.arch_ivybridge +// CHECK: ret i32 ()* @foo.sse4.2 +// CHECK: ret i32 ()* @foo + +// CHECK: define i32 @bar2() +// CHECK: call i32 @foo_inline.ifunc() + +// CHECK: define i32 ()* @foo_inline.resolver() +// CHECK: call void @__cpu_indicator_init() +// CHECK: ret i32 ()* @foo_inline.arch_sandybridge +// CHECK: ret i32 ()* @foo_inline.arch_ivybridge +// CHECK: ret i32 ()* @foo_inline.sse4.2 +// CHECK: ret i32 ()* @foo_inline + +// CHECK: define void @bar3() +// CHECK: call void @foo_decls.ifunc() + +// CHECK: define void ()* @foo_decls.resolver() +// CHECK: ret void ()* @foo_decls.sse4.2 +// CHECK: ret void ()* @foo_decls + +// CHECK: declare i32 @foo.arch_sandybridge() + +// CHECK: define available_externally i32 @foo_inline.sse4.2() +// CHECK: ret i32 0 + +// CHECK: declare i32 @foo_inline.arch_sandybridge() +// +// CHECK: define available_externally i32 @foo_inline.arch_ivybridge() +// CHECK: ret i32 1 +// CHECK: define available_externally i32 @foo_inline() +// CHECK: ret i32 2 + +// CHECK: define available_externally void @foo_decls() +// CHECK: define available_externally void @foo_decls.sse4.2() + diff --git a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp new file mode 100644 index 00000000000..1852750e469 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +// Test ensures that this properly differentiates between types in different +// namespaces. +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } + +namespace ns { +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } +} + +int bar() { + return foo(1) + ns::foo(2); +} + +// CHECK: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver +// CHECK: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver + +// CHECK: define i32 @_Z3fooi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_Z3fooi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_Z3fooi(i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_ZN2ns3fooEi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_ZN2ns3fooEi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_ZN2ns3fooEi(i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_Z3barv() +// CHECK: call i32 @_Z3fooi.ifunc(i32 1) +// CHECK: call i32 @_ZN2ns3fooEi.ifunc(i32 2) + +// CHECK: define i32 (i32)* @_Z3fooi.resolver() +// CHECK: ret i32 (i32)* @_Z3fooi.arch_sandybridge +// CHECK: ret i32 (i32)* @_Z3fooi.arch_ivybridge +// CHECK: ret i32 (i32)* @_Z3fooi.sse4.2 +// CHECK: ret i32 (i32)* @_Z3fooi +// +// CHECK: define i32 (i32)* @_ZN2ns3fooEi.resolver() +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2 +// CHECK: ret i32 (i32)* @_ZN2ns3fooEi + +// CHECK: declare i32 @_Z3fooi.arch_sandybridge(i32) +// CHECK: declare i32 @_ZN2ns3fooEi.arch_sandybridge(i32) diff --git a/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp new file mode 100644 index 00000000000..290d6b5c648 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +void temp(); +void temp(int); +using FP = void(*)(int); +void b() { + FP f = temp; +} + +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } + +struct S { +int __attribute__((target("sse4.2"))) foo(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo(int); +int __attribute__((target("arch=ivybridge"))) foo(int) {return 1;} +int __attribute__((target("default"))) foo(int) { return 2; } +}; + +using FuncPtr = int (*)(int); +using MemFuncPtr = int (S::*)(int); + +void f(FuncPtr, MemFuncPtr); + +int bar() { + FuncPtr Free = &foo; + MemFuncPtr Member = &S::foo; + S s; + f(foo, &S::foo); + return Free(1) + (s.*Member)(2); +} + + +// CHECK: @_Z3fooi.ifunc +// CHECK: @_ZN1S3fooEi.ifunc + +// CHECK: define i32 @_Z3barv() +// Store to Free of ifunc +// CHECK: store i32 (i32)* @_Z3fooi.ifunc +// Store to Member of ifunc +// CHECK: store { i64, i64 } { i64 ptrtoint (i32 (%struct.S*, i32)* @_ZN1S3fooEi.ifunc to i64), i64 0 }, { i64, i64 }* [[MEMBER:%[a-z]+]] + +// Call to 'f' with the ifunc +// CHECK: call void @_Z1fPFiiEM1SFiiE(i32 (i32)* @_Z3fooi.ifunc diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp new file mode 100644 index 00000000000..2c201c5d529 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s + +struct S { + int __attribute__((target("sse4.2"))) foo(int) { return 0; } + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; } + int __attribute__((target("default"))) foo(int) { return 2; } + + S &__attribute__((target("arch=ivybridge"))) operator=(const S &) { + return *this; + } + S &__attribute__((target("default"))) operator=(const S &) { + return *this; + } +}; + +struct ConvertTo { + __attribute__((target("arch=ivybridge"))) operator S() const { + return S{}; + } + __attribute__((target("default"))) operator S() const { + return S{}; + } +}; + +int bar() { + S s; + S s2; + s2 = s; + + ConvertTo C; + s2 = static_cast<S>(C); + + return s.foo(0); +} + +struct S2 { + int __attribute__((target("sse4.2"))) foo(int); + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int); + int __attribute__((target("default"))) foo(int); +}; + +int bar2() { + S2 s; + return s.foo(0); +} + +int __attribute__((target("sse4.2"))) S2::foo(int) { return 0; } +int __attribute__((target("arch=ivybridge"))) S2::foo(int) { return 1; } +int __attribute__((target("default"))) S2::foo(int) { return 2; } + +template<typename T> +struct templ { + int __attribute__((target("sse4.2"))) foo(int) { return 0; } + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int) { return 1; } + int __attribute__((target("default"))) foo(int) { return 2; } +}; + +int templ_use() { + templ<int> a; + templ<double> b; + return a.foo(1) + b.foo(2); +} + +// CHECK: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver +// CHECK: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver +// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver +// CHECK: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver +// Templates: +// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver +// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver + +// CHECK: define i32 @_Z3barv() +// CHECK: %s = alloca %struct.S, align 1 +// CHECK: %s2 = alloca %struct.S, align 1 +// CHECK: %C = alloca %struct.ConvertTo, align 1 +// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// CHECK: call void @_ZNK9ConvertTocv1SEv.ifunc(%struct.ConvertTo* %C) +// CHECK: call dereferenceable(1) %struct.S* @_ZN1SaSERKS_.ifunc(%struct.S* %s2 +// CHECK: call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// CHECK: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() +// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge +// CHECK: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_ + +// CHECK: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() +// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge +// CHECK: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv + +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// CHECK: define i32 @_Z4bar2v() +// CHECK:call i32 @_ZN2S23fooEi.ifunc +// define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2 +// CHECK: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi + +// CHECK: define i32 @_ZN2S23fooEi.sse4.2(%struct.S2* %this, i32) +// CHECK: define i32 @_ZN2S23fooEi.arch_ivybridge(%struct.S2* %this, i32) +// CHECK: define i32 @_ZN2S23fooEi(%struct.S2* %this, i32) + +// CHECK: define i32 @_Z9templ_usev() +// CHECK: call i32 @_ZN5templIiE3fooEi.ifunc +// CHECK: call i32 @_ZN5templIdE3fooEi.ifunc + + +// CHECK: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2 +// CHECK: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi +// +// CHECK: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2 +// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// CHECK: ret i32 0 + +// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// CHECK: ret i32 1 + +// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// CHECK: ret i32 2 + diff --git a/clang/test/CodeGenCXX/attr-target-mv-modules.cpp b/clang/test/CodeGenCXX/attr-target-mv-modules.cpp new file mode 100644 index 00000000000..6ff2046831e --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-modules.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fmodules -emit-llvm %s -o - | FileCheck %s +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +__attribute__((target("default"))) void f(); +__attribute__((target("sse4.2"))) void f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +__attribute__((target("default"))) void f(); +__attribute__((target("sse4.2"))) void f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import A +#pragma clang module import B +void g() { f(); } + +// Negative tests to validate that the resolver only calls each 1x. +// CHECK: define void ()* @_Z1fv.resolver +// CHECK: ret void ()* @_Z1fv.sse4.2 +// CHECK-NOT: ret void ()* @_Z1fv.sse4.2 +// CHECK: ret void ()* @_Z1fv +// CHECK-NOT: ret void ()* @_Z1fv diff --git a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp new file mode 100644 index 00000000000..7072dec5031 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s +struct S { + int __attribute__((target("sse4.2"))) foo(int); + int __attribute__((target("arch=sandybridge"))) foo(int); + int __attribute__((target("arch=ivybridge"))) foo(int); + int __attribute__((target("default"))) foo(int); +}; + +int __attribute__((target("default"))) S::foo(int) { return 2; } +int __attribute__((target("sse4.2"))) S::foo(int) { return 0; } +int __attribute__((target("arch=ivybridge"))) S::foo(int) { return 1; } + +int bar() { + S s; + return s.foo(0); +} + +// CHECK: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver + +// CHECK: define i32 @_ZN1S3fooEi(%struct.S* %this, i32) +// CHECK: ret i32 2 + +// CHECK: define i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32) +// CHECK: ret i32 0 + +// CHECK: define i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32) +// CHECK: ret i32 1 + +// CHECK: define i32 @_Z3barv() +// CHECK: %s = alloca %struct.S, align 1 +// CHECK: %call = call i32 @_ZN1S3fooEi.ifunc(%struct.S* %s, i32 0) + +// CHECK: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2 +// CHECK: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi + +// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32) diff --git a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp new file mode 100644 index 00000000000..a1b12c304e1 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s + +int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo_overload(int); +int __attribute__((target("arch=ivybridge"))) foo_overload(int) {return 1;} +int __attribute__((target("default"))) foo_overload(int) { return 2; } +int __attribute__((target("sse4.2"))) foo_overload(void) { return 0; } +int __attribute__((target("arch=sandybridge"))) foo_overload(void); +int __attribute__((target("arch=ivybridge"))) foo_overload(void) {return 1;} +int __attribute__((target("default"))) foo_overload(void) { return 2; } + +int bar2() { + return foo_overload() + foo_overload(1); +} + +// CHECK: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver +// CHECK: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver + + +// CHECK: define i32 @_Z12foo_overloadi.sse4.2(i32) +// CHECK: ret i32 0 +// CHECK: define i32 @_Z12foo_overloadi.arch_ivybridge(i32) +// CHECK: ret i32 1 +// CHECK: define i32 @_Z12foo_overloadi(i32) +// CHECK: ret i32 2 +// CHECK: define i32 @_Z12foo_overloadv.sse4.2() +// CHECK: ret i32 0 +// CHECK: define i32 @_Z12foo_overloadv.arch_ivybridge() +// CHECK: ret i32 1 +// CHECK: define i32 @_Z12foo_overloadv() +// CHECK: ret i32 2 + +// CHECK: define i32 @_Z4bar2v() +// CHECK: call i32 @_Z12foo_overloadv.ifunc() +// CHECK: call i32 @_Z12foo_overloadi.ifunc(i32 1) + +// CHECK: define i32 ()* @_Z12foo_overloadv.resolver() +// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge +// CHECK: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge +// CHECK: ret i32 ()* @_Z12foo_overloadv.sse4.2 +// CHECK: ret i32 ()* @_Z12foo_overloadv + +// CHECK: define i32 (i32)* @_Z12foo_overloadi.resolver() +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge +// CHECK: ret i32 (i32)* @_Z12foo_overloadi.sse4.2 +// CHECK: ret i32 (i32)* @_Z12foo_overloadi + +// CHECK: declare i32 @_Z12foo_overloadv.arch_sandybridge() +// CHECK: declare i32 @_Z12foo_overloadi.arch_sandybridge(i32) diff --git a/clang/test/Sema/attr-target-mv-bad-target.c b/clang/test/Sema/attr-target-mv-bad-target.c new file mode 100644 index 00000000000..9cf3c5e10a6 --- /dev/null +++ b/clang/test/Sema/attr-target-mv-bad-target.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple x86_64-windows-pc -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple arm-none-eabi -fsyntax-only -verify %s + +int __attribute__((target("sse4.2"))) redecl1(void) { return 1; } +//expected-error@+2 {{function multiversioning is not supported on the current target}} +//expected-note@-2 {{previous declaration is here}} +int __attribute__((target("avx"))) redecl1(void) { return 2; } + +//expected-error@+1 {{function multiversioning is not supported on the current target}} +int __attribute__((target("default"))) with_def(void) { return 1;} diff --git a/clang/test/Sema/attr-target-mv.c b/clang/test/Sema/attr-target-mv.c new file mode 100644 index 00000000000..671adff5b04 --- /dev/null +++ b/clang/test/Sema/attr-target-mv.c @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s + +void __attribute__((target("sse4.2"))) no_default(void); +void __attribute__((target("arch=sandybridge"))) no_default(void); + +void use1(void){ + // expected-error@+1 {{no matching function for call to 'no_default'}} + no_default(); +} + +void __attribute__((target("sse4.2"))) has_def(void); +void __attribute__((target("default"))) has_def(void); + +void use2(void){ + // expected-error@+2 {{reference to overloaded function could not be resolved; did you mean to call it?}} + // expected-note@-4 {{possible target for call}} + +has_def; +} + +int __attribute__((target("sse4.2"))) no_proto(); +// expected-error@-1 {{multiversioned function must have a prototype}} +// expected-note@+1 {{function multiversioning caused by this declaration}} +int __attribute__((target("arch=sandybridge"))) no_proto(); + +// The following should all be legal, since they are just redeclarations. +int __attribute__((target("sse4.2"))) redecl1(void); +int __attribute__((target("sse4.2"))) redecl1(void) { return 1; } +int __attribute__((target("arch=sandybridge"))) redecl1(void) { return 2; } + +int __attribute__((target("sse4.2"))) redecl2(void) { return 1; } +int __attribute__((target("sse4.2"))) redecl2(void); +int __attribute__((target("arch=sandybridge"))) redecl2(void) { return 2; } + +int __attribute__((target("sse4.2"))) redecl3(void) { return 0; } +int __attribute__((target("arch=ivybridge"))) redecl3(void) { return 1; } +int __attribute__((target("arch=sandybridge"))) redecl3(void); +int __attribute__((target("arch=sandybridge"))) redecl3(void) { return 2; } + +int __attribute__((target("sse4.2"))) redecl4(void) { return 1; } +int __attribute__((target("arch=sandybridge"))) redecl4(void) { return 2; } +int __attribute__((target("arch=sandybridge"))) redecl4(void); + +int __attribute__((target("sse4.2"))) redef(void) { return 1; } +int __attribute__((target("arch=ivybridge"))) redef(void) { return 1; } +int __attribute__((target("arch=sandybridge"))) redef(void) { return 2; } +// expected-error@+2 {{redefinition of 'redef'}} +// expected-note@-2 {{previous definition is here}} +int __attribute__((target("arch=sandybridge"))) redef(void) { return 2; } + +int __attribute__((target("default"))) redef2(void) { return 1;} +// expected-error@+2 {{redefinition of 'redef2'}} +// expected-note@-2 {{previous definition is here}} +int __attribute__((target("default"))) redef2(void) { return 1;} + +int __attribute__((target("sse4.2"))) mv_after_use(void) { return 1; } +int use3(void) { + return mv_after_use(); +} + +// expected-error@+1 {{function declaration cannot become a multiversioned function after first usage}} +int __attribute__((target("arch=sandybridge"))) mv_after_use(void) { return 2; } + +int __attribute__((target("sse4.2,arch=sandybridge"))) mangle(void) { return 1; } +//expected-error@+2 {{multiversioned function redeclarations require identical target attributes}} +//expected-note@-2 {{previous declaration is here}} +int __attribute__((target("arch=sandybridge,sse4.2"))) mangle(void) { return 2; } + +int prev_no_target(void); +int __attribute__((target("arch=sandybridge"))) prev_no_target(void) { return 2; } +// expected-error@-2 {{function declaration is missing 'target' attribute in a multiversioned function}} +// expected-note@+1 {{function multiversioning caused by this declaration}} +int __attribute__((target("arch=ivybridge"))) prev_no_target(void) { return 2; } + +int __attribute__((target("arch=sandybridge"))) prev_no_target2(void); +int prev_no_target2(void); +// expected-error@-1 {{function declaration is missing 'target' attribute in a multiversioned function}} +// expected-note@+1 {{function multiversioning caused by this declaration}} +int __attribute__((target("arch=ivybridge"))) prev_no_target2(void); + +void __attribute__((target("sse4.2"))) addtl_attrs(void); +//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}} +void __attribute__((used,target("arch=sandybridge"))) addtl_attrs(void); + +//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}} +void __attribute__((target("default"), used)) addtl_attrs2(void); + +//expected-error@+2 {{attribute 'target' multiversioning cannot be combined}} +//expected-note@+2 {{function multiversioning caused by this declaration}} +void __attribute__((used,target("sse4.2"))) addtl_attrs3(void); +void __attribute__((target("arch=sandybridge"))) addtl_attrs3(void); + +void __attribute__((target("sse4.2"))) addtl_attrs4(void); +void __attribute__((target("arch=sandybridge"))) addtl_attrs4(void); +//expected-error@+1 {{attribute 'target' multiversioning cannot be combined}} +void __attribute__((used,target("arch=ivybridge"))) addtl_attrs4(void); + +int __attribute__((target("sse4.2"))) diff_cc(void); +// expected-error@+1 {{multiversioned function declaration has a different calling convention}} +__vectorcall int __attribute__((target("arch=sandybridge"))) diff_cc(void); + +int __attribute__((target("sse4.2"))) diff_ret(void); +// expected-error@+1 {{multiversioned function declaration has a different return type}} +short __attribute__((target("arch=sandybridge"))) diff_ret(void); diff --git a/clang/test/SemaCXX/attr-target-mv.cpp b/clang/test/SemaCXX/attr-target-mv.cpp new file mode 100644 index 00000000000..18ec1bf7ca5 --- /dev/null +++ b/clang/test/SemaCXX/attr-target-mv.cpp @@ -0,0 +1,178 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++14 +void __attribute__((target("sse4.2"))) no_default(void); +void __attribute__((target("arch=sandybridge"))) no_default(void); + +void use1(void){ + // expected-error@+1 {{no matching function for call to 'no_default'}} + no_default(); +} +constexpr int __attribute__((target("sse4.2"))) foo(void) { return 0; } +constexpr int __attribute__((target("arch=sandybridge"))) foo(void); +//expected-error@+1 {{multiversioned function declaration has a different constexpr specification}} +int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;} +constexpr int __attribute__((target("default"))) foo(void) { return 2; } + +int __attribute__((target("sse4.2"))) foo2(void) { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different constexpr specification}} +constexpr int __attribute__((target("arch=sandybridge"))) foo2(void); +int __attribute__((target("arch=ivybridge"))) foo2(void) {return 1;} +int __attribute__((target("default"))) foo2(void) { return 2; } + +static int __attribute__((target("sse4.2"))) bar(void) { return 0; } +static int __attribute__((target("arch=sandybridge"))) bar(void); +//expected-error@+1 {{multiversioned function declaration has a different storage class}} +int __attribute__((target("arch=ivybridge"))) bar(void) {return 1;} +static int __attribute__((target("default"))) bar(void) { return 2; } + +int __attribute__((target("sse4.2"))) bar2(void) { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different storage class}} +static int __attribute__((target("arch=sandybridge"))) bar2(void); +int __attribute__((target("arch=ivybridge"))) bar2(void) {return 1;} +int __attribute__((target("default"))) bar2(void) { return 2; } + + +inline int __attribute__((target("sse4.2"))) baz(void) { return 0; } +inline int __attribute__((target("arch=sandybridge"))) baz(void); +//expected-error@+1 {{multiversioned function declaration has a different inline specification}} +int __attribute__((target("arch=ivybridge"))) baz(void) {return 1;} +inline int __attribute__((target("default"))) baz(void) { return 2; } + +int __attribute__((target("sse4.2"))) baz2(void) { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different inline specification}} +inline int __attribute__((target("arch=sandybridge"))) baz2(void); +int __attribute__((target("arch=ivybridge"))) baz2(void) {return 1;} +int __attribute__((target("default"))) baz2(void) { return 2; } + +float __attribute__((target("sse4.2"))) bock(void) { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different return type}} +int __attribute__((target("arch=sandybridge"))) bock(void); +//expected-error@+1 {{multiversioned function declaration has a different return type}} +int __attribute__((target("arch=ivybridge"))) bock(void) {return 1;} +//expected-error@+1 {{multiversioned function declaration has a different return type}} +int __attribute__((target("default"))) bock(void) { return 2; } + +int __attribute__((target("sse4.2"))) bock2(void) { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different return type}} +float __attribute__((target("arch=sandybridge"))) bock2(void); +int __attribute__((target("arch=ivybridge"))) bock2(void) {return 1;} +int __attribute__((target("default"))) bock2(void) { return 2; } + +auto __attribute__((target("sse4.2"))) bock3(void) -> int { return 0; } +//expected-error@+1 {{multiversioned function declaration has a different return type}} +auto __attribute__((target("arch=sandybridge"))) bock3(void) -> short { return (short)0;} + +int __attribute__((target("sse4.2"))) bock4(void) noexcept(false) { return 0; } +//expected-error@+2 {{exception specification in declaration does not match previous declaration}} +//expected-note@-2 {{previous declaration is here}} +int __attribute__((target("arch=sandybridge"))) bock4(void) noexcept(true) { return 1;} + +// FIXME: Add support for templates and virtual functions! +template<typename T> +int __attribute__((target("sse4.2"))) foo(T) { return 0; } +// expected-error@+2 {{multiversioned functions do not yet support function templates}} +template<typename T> +int __attribute__((target("arch=sandybridge"))) foo(T); + +// expected-error@+2 {{multiversioned functions do not yet support function templates}} +template<typename T> +int __attribute__((target("default"))) foo(T) { return 2; } + +struct S { + template<typename T> + int __attribute__((target("sse4.2"))) foo(T) { return 0; } + // expected-error@+2 {{multiversioned functions do not yet support function templates}} + template<typename T> + int __attribute__((target("arch=sandybridge"))) foo(T); + + // expected-error@+2 {{multiversioned functions do not yet support function templates}} + template<typename T> + int __attribute__((target("default"))) foo(T) { return 2; } + + // expected-error@+1 {{multiversioned functions do not yet support virtual functions}} + virtual void __attribute__((target("default"))) virt(); +}; + +extern "C" { +int __attribute__((target("sse4.2"))) diff_mangle(void) { return 0; } +} +//expected-error@+1 {{multiversioned function declaration has a different linkage}} +int __attribute__((target("arch=sandybridge"))) diff_mangle(void) { return 0; } + +// expected-error@+1 {{multiversioned functions do not yet support deduced return types}} +auto __attribute__((target("default"))) deduced_return(void) { return 0; } +// expected-error@-1 {{cannot initialize return object of type 'auto' with an rvalue of type 'int'}} + +auto __attribute__((target("default"))) trailing_return(void)-> int { return 0; } + +__attribute__((target("default"))) void DiffDecl(); +namespace N { +using ::DiffDecl; +// expected-error@+3 {{declaration conflicts with target of using declaration already in scope}} +// expected-note@-4 {{target of using declaration}} +// expected-note@-3 {{using declaration}} +__attribute__((target("arch=sandybridge"))) void DiffDecl(); +} // namespace N + +struct SpecialFuncs { + // expected-error@+1 {{multiversioned functions do not yet support constructors}} + __attribute__((target("default"))) SpecialFuncs(); + // expected-error@+1 {{multiversioned functions do not yet support destructors}} + __attribute__((target("default"))) ~SpecialFuncs(); + + // expected-error@+1 {{multiversioned functions do not yet support defaulted functions}} + SpecialFuncs& __attribute__((target("default"))) operator=(const SpecialFuncs&) = default; + // expected-error@+1 {{multiversioned functions do not yet support deleted functions}} + SpecialFuncs& __attribute__((target("default"))) operator=(SpecialFuncs&&) = delete; +}; + +class Secret { + int i = 0; + __attribute__((target("default"))) + friend int SecretAccessor(Secret &s); + __attribute__((target("arch=sandybridge"))) + friend int SecretAccessor(Secret &s); +}; + +__attribute__((target("default"))) +int SecretAccessor(Secret &s) { + return s.i; +} + +__attribute__((target("arch=sandybridge"))) +int SecretAccessor(Secret &s) { + return s.i + 2; +} + +__attribute__((target("arch=ivybridge"))) +int SecretAccessor(Secret &s) { + //expected-error@+2{{'i' is a private member of 'Secret'}} + //expected-note@-20{{implicitly declared private here}} + return s.i + 3; +} + +constexpr int __attribute__((target("sse4.2"))) constexpr_foo(void) { + return 0; +} +constexpr int __attribute__((target("arch=sandybridge"))) constexpr_foo(void); +constexpr int __attribute__((target("arch=ivybridge"))) constexpr_foo(void) { + return 1; +} +constexpr int __attribute__((target("default"))) constexpr_foo(void) { + return 2; +} + +void constexpr_test() { + static_assert(foo() == 2, "Should call 'default' in a constexpr context"); +} + +struct BadOutOfLine { + int __attribute__((target("sse4.2"))) foo(int); + int __attribute__((target("default"))) foo(int); +}; + +int __attribute__((target("sse4.2"))) BadOutOfLine::foo(int) { return 0; } +int __attribute__((target("default"))) BadOutOfLine::foo(int) { return 1; } +// expected-error@+3 {{out-of-line definition of 'foo' does not match any declaration in 'BadOutOfLine'}} +// expected-note@-3 {{member declaration nearly matches}} +// expected-note@-3 {{member declaration nearly matches}} +int __attribute__((target("arch=atom"))) BadOutOfLine::foo(int) { return 1; } |

