Skip to content

[builtins][arm64] Build __init_cpu_features_resolver on Apple platforms #73685

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
49 commits
Select commit Hold shift + click to select a range
802e1c6
[𝘀𝗽𝗿] changes to main this commit is based on
jroelofs Nov 28, 2023
24f8f63
[𝘀𝗽𝗿] initial version
jroelofs Nov 28, 2023
de74c62
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 28, 2023
413e538
rebase
jroelofs Nov 28, 2023
a34d63c
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 28, 2023
9c8c292
rebase
jroelofs Nov 28, 2023
e5f65ac
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
44935a8
rebase
jroelofs Nov 29, 2023
eafbe06
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
b6a5fe0
rebase
jroelofs Nov 29, 2023
97e7926
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
63df438
review feedback
jroelofs Nov 29, 2023
b3ed2e9
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
ee558d7
rebase
jroelofs Nov 29, 2023
603983e
add a note about the dispatch_once block
jroelofs Nov 29, 2023
cbb1611
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Nov 29, 2023
9f6c80e
rebase
jroelofs Nov 29, 2023
501007c
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 1, 2023
38823b5
rebase
jroelofs Dec 1, 2023
672624d
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 1, 2023
7b66e1e
rebase
jroelofs Dec 1, 2023
67574eb
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 5, 2023
628255e
rebase
jroelofs Dec 5, 2023
a2380ad
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
08024c3
review feedback
jroelofs Dec 6, 2023
019fe15
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
2ff6200
rebase
jroelofs Dec 6, 2023
f9a3370
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
5611e8a
rebase
jroelofs Dec 6, 2023
2899456
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
707c1a8
rebase
jroelofs Dec 6, 2023
c1d65d5
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 6, 2023
eb72f78
rebase
jroelofs Dec 6, 2023
9995a6b
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
bd8f8ab
rebase
jroelofs Dec 8, 2023
a835c1a
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
106d60c
rebase
jroelofs Dec 8, 2023
d244734
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 8, 2023
cd9a7b8
rebase
jroelofs Dec 8, 2023
6fec737
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 9, 2023
ec3f949
rebase
jroelofs Dec 9, 2023
5f53abd
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
a19bab2
rebase
jroelofs Dec 14, 2023
75b5c7a
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
e0759d1
rebase
jroelofs Dec 14, 2023
e2d5847
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
a9d0337
rebase
jroelofs Dec 14, 2023
eefbffb
[𝘀𝗽𝗿] changes introduced through rebase
jroelofs Dec 14, 2023
310fe41
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