| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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( |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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;} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; } |