Skip to content

[clang] Function Multi Versioning supports IFunc lowerings on Darwin platforms #73688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7ce327e
[𝘀𝗽𝗿] changes to main this commit is based on
jroelofs Nov 28, 2023
60bbb99
[𝘀𝗽𝗿] initial version
jroelofs Nov 28, 2023
fac7c3d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 28, 2023
7695f68
rebase
jroelofs Nov 28, 2023
9375c35
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 28, 2023
27dccd2
rebase
jroelofs Nov 28, 2023
c67ce7f
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
dd44429
rebase
jroelofs Nov 29, 2023
0041d6d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
d0c0b86
adjust tests per review feedback
jroelofs Nov 29, 2023
ecbfa04
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
6329152
review feedback
jroelofs Nov 29, 2023
2b76795
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
ad2f207
rebase
jroelofs Nov 29, 2023
212063d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
71fc16e
rebase
jroelofs Nov 29, 2023
ca23e96
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 1, 2023
9d89b03
rebase
jroelofs Dec 1, 2023
4a03437
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 1, 2023
b215b63
rebase
jroelofs Dec 1, 2023
6592f01
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 5, 2023
b2893cc
rebase
jroelofs Dec 5, 2023
5b2d795
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
b8ad533
rebase
jroelofs Dec 6, 2023
d12868d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
4432daa
rebase
jroelofs Dec 6, 2023
c515a9d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
54f4d55
rebase
jroelofs Dec 6, 2023
90adaa8
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
a9a7b40
rebase
jroelofs Dec 6, 2023
2bf3df5
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
a2ebde0
rebase
jroelofs Dec 6, 2023
600fe74
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
5790316
rebase
jroelofs Dec 8, 2023
3adbbaf
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
d0f9444
rebase
jroelofs Dec 8, 2023
53b3c9b
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
fe1dfa1
rebase
jroelofs Dec 8, 2023
5cf8cc5
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 9, 2023
0b9142b
rebase
jroelofs Dec 9, 2023
1619e4c
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
1e90475
apply maskray's review feedback
jroelofs Dec 14, 2023
cfded50
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
31e479a
rebase
jroelofs Dec 14, 2023
cdcfb6a
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
4b9cca3
rebase
jroelofs Dec 14, 2023
aa4d547
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
649b0f8
rebase
jroelofs Dec 14, 2023
6752566
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
b716a70
rebase
jroelofs Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,9 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch6
def TargetELF : TargetSpec {
let ObjectFormats = ["ELF"];
}
def TargetELFOrMachO : TargetSpec {
let ObjectFormats = ["ELF", "MachO"];
}

def TargetSupportsInitPriority : TargetSpec {
let CustomCode = [{ !Target.getTriple().isOSzOS() }];
Expand Down Expand Up @@ -1665,7 +1668,7 @@ def IBOutletCollection : InheritableAttr {
let Documentation = [Undocumented];
}

def IFunc : Attr, TargetSpecificAttr<TargetELF> {
def IFunc : Attr, TargetSpecificAttr<TargetELFOrMachO> {
let Spellings = [GCC<"ifunc">];
let Args = [StringArgument<"Resolver">];
let Subjects = SubjectList<[Function]>;
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -5535,7 +5535,9 @@ considered inline.
Not all targets support this attribute. ELF target support depends on both the
linker and runtime linker, and is available in at least lld 4.0 and later,
binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later.
Non-ELF targets currently do not support this attribute.
Mach-O targets support it, but with slightly different semantics: the resolver
is run at first call, instead of at load time by the runtime linker. Targets
other than ELF and Mach-O currently do not support this attribute.
}];
}

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,8 @@ class TargetInfo : public TransferrableTargetInfo,

/// Identify whether this target supports IFuncs.
bool supportsIFunc() const {
if (getTriple().isOSBinFormatMachO())
return true;
return getTriple().isOSBinFormatELF() &&
((getTriple().isOSLinux() && !getTriple().isMusl()) ||
getTriple().isOSFreeBSD());
Expand Down
1 change: 1 addition & 0 deletions clang/test/CodeGen/attr-cpuspecific.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS

#ifdef _WIN64
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CodeGen/attr-ifunc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only -DCHECK_ALIASES %s
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s

#if defined(_WIN32)
void foo(void) {}
Expand Down Expand Up @@ -36,6 +37,25 @@ void *f6_resolver(void) __attribute__((ifunc("f6_resolver_resolver")));
void f6(void) __attribute__((ifunc("f6_resolver")));
// expected-error@-1 {{ifunc must point to a defined function}}

#elif defined(__APPLE__)

// NOTE: aliases are not supported on Darwin, so the above tests are not relevant.

#define STR2(X) #X
#define STR(X) STR2(X)
#define PREFIX STR(__USER_LABEL_PREFIX__)

void f1a(void) __asm("f1");
void f1a(void) {}
// expected-note@-1 {{previous definition is here}}
void f1(void) __attribute__((ifunc(PREFIX "f1_ifunc"))) __asm("f1");
// expected-error@-1 {{definition with same mangled name '<U+0001>f1' as another definition}}
void *f1_ifunc(void) { return 0; }

void *f6_ifunc(int i);
void __attribute__((ifunc(PREFIX "f6_ifunc"))) f6(void) {}
// expected-error@-1 {{definition 'f6' cannot also be an ifunc}}

#else
void f1a(void) __asm("f1");
void f1a(void) {}
Expand Down
4 changes: 4 additions & 0 deletions clang/test/CodeGen/attr-ifunc.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify -emit-llvm-only %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s

void *f1_ifunc(void) { return nullptr; }
void f1(void) __attribute__((ifunc("f1_ifunc")));
Expand Down
81 changes: 81 additions & 0 deletions clang/test/CodeGen/attr-target-clones.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LINUX,CHECK
// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=DARWIN,CHECK
// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefixes=WINDOWS,CHECK

// LINUX: $foo.resolver = comdat any
Expand All @@ -7,6 +8,8 @@
// LINUX: $foo_inline.resolver = comdat any
// LINUX: $foo_inline2.resolver = comdat any

// DARWIN-NOT: comdat any

// WINDOWS: $foo = comdat any
// WINDOWS: $foo_dupes = comdat any
// WINDOWS: $unused = comdat any
Expand All @@ -16,6 +19,9 @@
// LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
// LINUX: @__cpu_features2 = external dso_local global [3 x i32]

// DARWIN: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
// DARWIN: @__cpu_features2 = external dso_local global [3 x i32]

// LINUX: @internal.ifunc = internal alias i32 (), ptr @internal
// LINUX: @foo.ifunc = weak_odr alias i32 (), ptr @foo
// LINUX: @foo_dupes.ifunc = weak_odr alias void (), ptr @foo_dupes
Expand All @@ -34,10 +40,12 @@
// LINUX: @foo_used_no_defn = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver
// LINUX: @isa_level = weak_odr ifunc i32 (i32), ptr @isa_level.resolver


static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }
int use(void) { return internal(); }
/// Internal linkage resolvers do not use comdat.
// LINUX: define internal ptr @internal.resolver() {
// DARWIN: define internal ptr @internal.resolver() {
// WINDOWS: define internal i32 @internal() {

int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
Expand All @@ -47,6 +55,12 @@ int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
// LINUX: ret ptr @foo.sse4.2.0
// LINUX: ret ptr @foo.default.1

// DARWIN: define {{.*}}i32 @foo.sse4.2.0()
// DARWIN: define {{.*}}i32 @foo.default.1()
// DARWIN: define weak_odr ptr @foo.resolver() {
// DARWIN: ret ptr @foo.sse4.2.0
// DARWIN: ret ptr @foo.default.1

// WINDOWS: define dso_local i32 @foo.sse4.2.0()
// WINDOWS: define dso_local i32 @foo.default.1()
// WINDOWS: define weak_odr dso_local i32 @foo() comdat
Expand All @@ -60,6 +74,12 @@ __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {
// LINUX: ret ptr @foo_dupes.sse4.2.0
// LINUX: ret ptr @foo_dupes.default.1

// DARWIN: define {{.*}}void @foo_dupes.default.1()
// DARWIN: define {{.*}}void @foo_dupes.sse4.2.0()
// DARWIN: define weak_odr ptr @foo_dupes.resolver() {
// DARWIN: ret ptr @foo_dupes.sse4.2.0
// DARWIN: ret ptr @foo_dupes.default.1

// WINDOWS: define dso_local void @foo_dupes.default.1()
// WINDOWS: define dso_local void @foo_dupes.sse4.2.0()
// WINDOWS: define weak_odr dso_local void @foo_dupes() comdat
Expand All @@ -68,17 +88,21 @@ __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {

void bar2(void) {
// LINUX: define {{.*}}void @bar2()
// DARWIN: define {{.*}}void @bar2()
// WINDOWS: define dso_local void @bar2()
foo_dupes();
// LINUX: call void @foo_dupes()
// DARWIN: call void @foo_dupes()
// WINDOWS: call void @foo_dupes()
}

int bar(void) {
// LINUX: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]
// DARWIN: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]
// WINDOWS: define dso_local i32 @bar() #[[DEF:[0-9]+]]
return foo();
// LINUX: call i32 @foo()
// DARWIN: call i32 @foo()
// WINDOWS: call i32 @foo()
}

Expand All @@ -89,6 +113,12 @@ void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}
// LINUX: ret ptr @unused.arch_ivybridge.0
// LINUX: ret ptr @unused.default.1

// DARWIN: define {{.*}}void @unused.default.1()
// DARWIN: define {{.*}}void @unused.arch_ivybridge.0()
// DARWIN: define weak_odr ptr @unused.resolver() {
// DARWIN: ret ptr @unused.arch_ivybridge.0
// DARWIN: ret ptr @unused.default.1

// WINDOWS: define dso_local void @unused.default.1()
// WINDOWS: define dso_local void @unused.arch_ivybridge.0()
// WINDOWS: define weak_odr dso_local void @unused() comdat
Expand All @@ -103,10 +133,13 @@ foo_inline2(void);

int bar3(void) {
// LINUX: define {{.*}}i32 @bar3()
// DARWIN: define {{.*}}i32 @bar3()
// WINDOWS: define dso_local i32 @bar3()
return foo_inline() + foo_inline2();
// LINUX: call i32 @foo_inline()
// LINUX: call i32 @foo_inline2()
// DARWIN: call i32 @foo_inline()
// DARWIN: call i32 @foo_inline2()
// WINDOWS: call i32 @foo_inline()
// WINDOWS: call i32 @foo_inline2()
}
Expand All @@ -116,6 +149,11 @@ int bar3(void) {
// LINUX: ret ptr @foo_inline.sse4.2.1
// LINUX: ret ptr @foo_inline.default.2

// DARWIN: define weak_odr ptr @foo_inline.resolver() {
// DARWIN: ret ptr @foo_inline.arch_sandybridge.0
// DARWIN: ret ptr @foo_inline.sse4.2.1
// DARWIN: ret ptr @foo_inline.default.2

// WINDOWS: define weak_odr dso_local i32 @foo_inline() comdat
// WINDOWS: musttail call i32 @foo_inline.arch_sandybridge.0
// WINDOWS: musttail call i32 @foo_inline.sse4.2.1
Expand All @@ -128,6 +166,11 @@ foo_inline2(void){ return 0; }
// LINUX: ret ptr @foo_inline2.sse4.2.1
// LINUX: ret ptr @foo_inline2.default.2

// DARWIN: define weak_odr ptr @foo_inline2.resolver() {
// DARWIN: ret ptr @foo_inline2.arch_sandybridge.0
// DARWIN: ret ptr @foo_inline2.sse4.2.1
// DARWIN: ret ptr @foo_inline2.default.2

// WINDOWS: define weak_odr dso_local i32 @foo_inline2() comdat
// WINDOWS: musttail call i32 @foo_inline2.arch_sandybridge.0
// WINDOWS: musttail call i32 @foo_inline2.sse4.2.1
Expand All @@ -142,9 +185,11 @@ foo_used_no_defn(void);

int test_foo_used_no_defn(void) {
// LINUX: define {{.*}}i32 @test_foo_used_no_defn()
// DARWIN: define {{.*}}i32 @test_foo_used_no_defn()
// WINDOWS: define dso_local i32 @test_foo_used_no_defn()
return foo_used_no_defn();
// LINUX: call i32 @foo_used_no_defn()
// DARWIN: call i32 @foo_used_no_defn()
// WINDOWS: call i32 @foo_used_no_defn()
}

Expand All @@ -153,6 +198,10 @@ int test_foo_used_no_defn(void) {
// LINUX: ret ptr @foo_used_no_defn.sse4.2.0
// LINUX: ret ptr @foo_used_no_defn.default.1

// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver() {
// DARWIN: ret ptr @foo_used_no_defn.sse4.2.0
// DARWIN: ret ptr @foo_used_no_defn.default.1

// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() comdat
// WINDOWS: musttail call i32 @foo_used_no_defn.sse4.2.0
// WINDOWS: musttail call i32 @foo_used_no_defn.default.1
Expand Down Expand Up @@ -180,12 +229,37 @@ int isa_level(int) { return 0; }
// LINUX: ret ptr @isa_level.arch_x86-64.0
// LINUX: ret ptr @isa_level.default.4

// DARWIN: define{{.*}} i32 @isa_level.default.4(
// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64.0(
// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
// DARWIN: define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
// DARWIN: define weak_odr ptr @isa_level.resolver() {
// DARWIN: call void @__cpu_indicator_init()
// DARWIN-NEXT: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
// DARWIN-NEXT: and i32 %[[#]], 4
// DARWIN: ret ptr @isa_level.arch_x86-64-v4.3
// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
// DARWIN-NEXT: and i32 %[[#]], 2
// DARWIN: ret ptr @isa_level.arch_x86-64-v3.2
// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
// DARWIN-NEXT: and i32 %[[#]], 1
// DARWIN: ret ptr @isa_level.arch_x86-64-v2.1
// DARWIN: load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1)
// DARWIN-NEXT: and i32 %[[#]], -2147483648
// DARWIN: ret ptr @isa_level.arch_x86-64.0
// DARWIN: ret ptr @isa_level.default.4

// Deferred emission of inline definitions.

// LINUX: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
// LINUX: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]
// LINUX: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]

// DARWIN: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
// DARWIN: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]
// DARWIN: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]

// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.default.2() #[[DEF]]
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]
Expand All @@ -195,6 +269,10 @@ int isa_level(int) { return 0; }
// LINUX: define linkonce i32 @foo_inline2.default.2() #[[DEF]]
// LINUX: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]

// DARWIN: define linkonce i32 @foo_inline2.arch_sandybridge.0() #[[SB]]
// DARWIN: define linkonce i32 @foo_inline2.default.2() #[[DEF]]
// DARWIN: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]

// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.arch_sandybridge.0() #[[SB]]
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.default.2() #[[DEF]]
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.sse4.2.1() #[[SSE42]]
Expand All @@ -203,6 +281,9 @@ int isa_level(int) { return 0; }
// LINUX: declare i32 @foo_used_no_defn.default.1()
// LINUX: declare i32 @foo_used_no_defn.sse4.2.0()

// DARWIN: declare i32 @foo_used_no_defn.default.1()
// DARWIN: declare i32 @foo_used_no_defn.sse4.2.0()

// WINDOWS: declare dso_local i32 @foo_used_no_defn.default.1()
// WINDOWS: declare dso_local i32 @foo_used_no_defn.sse4.2.0()

Expand Down
1 change: 1 addition & 0 deletions clang/test/CodeGen/attr-target-mv-func-ptrs.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
int __attribute__((target("sse4.2"))) foo(int i) { return 0; }
int __attribute__((target("arch=sandybridge"))) foo(int);
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CodeGen/attr-target-mv-va-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefixes=NO-IFUNC,WINDOWS
// RUN: %clang_cc1 -triple x86_64-linux-musl -emit-llvm %s -o - | FileCheck %s --check-prefixes=NO-IFUNC,NO-IFUNC-ELF
// RUN: %clang_cc1 -triple x86_64-fuchsia -emit-llvm %s -o - | FileCheck %s --check-prefixes=NO-IFUNC,NO-IFUNC-ELF
// RUN: %clang_cc1 -triple x86_64-apple-macho -emit-llvm %s -o - | FileCheck %s --check-prefix=IFUNC-MACHO
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;}
Expand Down Expand Up @@ -30,6 +31,24 @@ int bar(void) {
// IFUNC-ELF: ret ptr @foo
// IFUNC-ELF: declare i32 @foo.arch_sandybridge(i32 noundef, ...)

// IFUNC-MACHO: @foo.ifunc = weak_odr ifunc i32 (i32, ...), ptr @foo.resolver
// IFUNC-MACHO: define{{.*}} i32 @foo.sse4.2(i32 noundef %i, ...)
// IFUNC-MACHO: ret i32 0
// IFUNC-MACHO: define{{.*}} i32 @foo.arch_ivybridge(i32 noundef %i, ...)
// IFUNC-MACHO: ret i32 1
// IFUNC-MACHO: define{{.*}} i32 @foo(i32 noundef %i, ...)
// IFUNC-MACHO: ret i32 2
// IFUNC-MACHO: define{{.*}} i32 @bar()
// IFUNC-MACHO: call i32 (i32, ...) @foo.ifunc(i32 noundef 1, i32 noundef 97, double
// IFUNC-MACHO: call i32 (i32, ...) @foo.ifunc(i32 noundef 2, double noundef 2.2{{[0-9Ee+]+}}, ptr noundef

// IFUNC-MACHO: define weak_odr ptr @foo.resolver()
// IFUNC-MACHO: ret ptr @foo.arch_sandybridge
// IFUNC-MACHO: ret ptr @foo.arch_ivybridge
// IFUNC-MACHO: ret ptr @foo.sse4.2
// IFUNC-MACHO: ret ptr @foo
// IFUNC-MACHO: declare i32 @foo.arch_sandybridge(i32 noundef, ...)

// NO-IFUNC: define dso_local i32 @foo.sse4.2(i32 noundef %i, ...)
// NO-IFUNC: ret i32 0
// NO-IFUNC: define dso_local i32 @foo.arch_ivybridge(i32 noundef %i, ...)
Expand Down
Loading