Skip to content

Commit 99d7433

Browse files
authored
[clang][fmv] Drop .ifunc from target_version's entrypoint's mangling (#81194)
Fixes: #81043
1 parent 935f7d6 commit 99d7433

File tree

6 files changed

+143
-105
lines changed

6 files changed

+143
-105
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,10 @@ class FunctionDecl : public DeclaratorDecl,
26192619
/// the target-clones functionality.
26202620
bool isTargetClonesMultiVersion() const;
26212621

2622+
/// True if this function is a multiversioned dispatch function as a part of
2623+
/// the target-version functionality.
2624+
bool isTargetVersionMultiVersion() const;
2625+
26222626
/// \brief Get the associated-constraints of this function declaration.
26232627
/// Currently, this will either be a vector of size 1 containing the
26242628
/// trailing-requires-clause or an empty vector.

clang/include/clang/Basic/AttrDocs.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,6 +2517,14 @@ function it instructs compiler to emit multiple function versions based on
25172517
priority and target features availability. One of the versions is always
25182518
( implicitly or explicitly ) the ``default`` (fallback). Attribute strings can
25192519
contain dependent features names joined by the "+" sign.
2520+
2521+
For targets that support the GNU indirect function (IFUNC) feature, dispatch
2522+
is performed by emitting an indirect function that is resolved to the appropriate
2523+
target clone at load time. The indirect function is given the name the
2524+
multiversioned function would have if it had been declared without the attribute.
2525+
For backward compatibility with earlier Clang releases, a function alias with an
2526+
``.ifunc`` suffix is also emitted. The ``.ifunc`` suffixed symbol is a deprecated
2527+
feature and support for it may be removed in the future.
25202528
}];
25212529
}
25222530

clang/lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3541,6 +3541,10 @@ bool FunctionDecl::isTargetClonesMultiVersion() const {
35413541
return isMultiVersion() && hasAttr<TargetClonesAttr>();
35423542
}
35433543

3544+
bool FunctionDecl::isTargetVersionMultiVersion() const {
3545+
return isMultiVersion() && hasAttr<TargetVersionAttr>();
3546+
}
3547+
35443548
void
35453549
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
35463550
redeclarable_base::setPreviousDecl(PrevDecl);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "clang/AST/ASTContext.h"
3131
#include "clang/AST/ASTLambda.h"
3232
#include "clang/AST/CharUnits.h"
33+
#include "clang/AST/Decl.h"
3334
#include "clang/AST/DeclCXX.h"
3435
#include "clang/AST/DeclObjC.h"
3536
#include "clang/AST/DeclTemplate.h"
@@ -4212,7 +4213,8 @@ void CodeGenModule::emitMultiVersionFunctions() {
42124213
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
42134214
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
42144215
ResolverConstant = IFunc->getResolver();
4215-
if (FD->isTargetClonesMultiVersion()) {
4216+
if (FD->isTargetClonesMultiVersion() ||
4217+
FD->isTargetVersionMultiVersion()) {
42164218
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
42174219
llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
42184220
std::string MangledName = getMangledNameImpl(
@@ -4393,8 +4395,18 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
43934395
// a separate resolver).
43944396
std::string ResolverName = MangledName;
43954397
if (getTarget().supportsIFunc()) {
4396-
if (!FD->isTargetClonesMultiVersion())
4398+
switch (FD->getMultiVersionKind()) {
4399+
case MultiVersionKind::None:
4400+
llvm_unreachable("unexpected MultiVersionKind::None for resolver");
4401+
case MultiVersionKind::Target:
4402+
case MultiVersionKind::CPUSpecific:
4403+
case MultiVersionKind::CPUDispatch:
43974404
ResolverName += ".ifunc";
4405+
break;
4406+
case MultiVersionKind::TargetClones:
4407+
case MultiVersionKind::TargetVersion:
4408+
break;
4409+
}
43984410
} else if (FD->isTargetMultiVersion()) {
43994411
ResolverName += ".resolver";
44004412
}

clang/test/CodeGen/attr-target-version.c

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,20 @@ int hoo(void) {
9090

9191
//.
9292
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
93-
// CHECK: @fmv.ifunc = weak_odr ifunc i32 (), ptr @fmv.resolver
94-
// CHECK: @fmv_one.ifunc = weak_odr ifunc i32 (), ptr @fmv_one.resolver
95-
// CHECK: @fmv_two.ifunc = weak_odr ifunc i32 (), ptr @fmv_two.resolver
96-
// CHECK: @fmv_e.ifunc = weak_odr ifunc i32 (), ptr @fmv_e.resolver
97-
// CHECK: @fmv_c.ifunc = weak_odr ifunc void (), ptr @fmv_c.resolver
98-
// CHECK: @fmv_inline.ifunc = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
99-
// CHECK: @fmv_d.ifunc = internal ifunc i32 (), ptr @fmv_d.resolver
93+
// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
94+
// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
95+
// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
96+
// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
97+
// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
98+
// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
99+
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
100+
// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
101+
// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
102+
// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
103+
// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
104+
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
105+
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
106+
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
100107
//.
101108
// CHECK: Function Attrs: noinline nounwind optnone
102109
// CHECK-LABEL: define {{[^@]+}}@fmv._MrngMflagmMfp16fml
@@ -105,6 +112,32 @@ int hoo(void) {
105112
// CHECK-NEXT: ret i32 1
106113
//
107114
//
115+
// CHECK: Function Attrs: noinline nounwind optnone
116+
// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64
117+
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
118+
// CHECK-NEXT: entry:
119+
// CHECK-NEXT: ret i32 1
120+
//
121+
//
122+
// CHECK: Function Attrs: noinline nounwind optnone
123+
// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp
124+
// CHECK-SAME: () #[[ATTR1]] {
125+
// CHECK-NEXT: entry:
126+
// CHECK-NEXT: ret i32 1
127+
//
128+
//
129+
// CHECK: Function Attrs: noinline nounwind optnone
130+
// CHECK-LABEL: define {{[^@]+}}@foo
131+
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
132+
// CHECK-NEXT: entry:
133+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv()
134+
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one()
135+
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
136+
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two()
137+
// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
138+
// CHECK-NEXT: ret i32 [[ADD3]]
139+
//
140+
//
108141
// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat {
109142
// CHECK-NEXT: resolver_entry:
110143
// CHECK-NEXT: call void @__init_cpu_features_resolver()
@@ -183,42 +216,16 @@ int hoo(void) {
183216
// CHECK-NEXT: ret ptr @fmv.default
184217
//
185218
//
186-
// CHECK: Function Attrs: noinline nounwind optnone
187-
// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64
188-
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
189-
// CHECK-NEXT: entry:
190-
// CHECK-NEXT: ret i32 1
191-
//
192-
//
193219
// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat {
194220
// CHECK-NEXT: resolver_entry:
195221
// CHECK-NEXT: ret ptr @fmv_one._MsimdMls64
196222
//
197223
//
198-
// CHECK: Function Attrs: noinline nounwind optnone
199-
// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp
200-
// CHECK-SAME: () #[[ATTR1]] {
201-
// CHECK-NEXT: entry:
202-
// CHECK-NEXT: ret i32 1
203-
//
204-
//
205224
// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat {
206225
// CHECK-NEXT: resolver_entry:
207226
// CHECK-NEXT: ret ptr @fmv_two._MsimdMfp16
208227
//
209228
//
210-
// CHECK: Function Attrs: noinline nounwind optnone
211-
// CHECK-LABEL: define {{[^@]+}}@foo
212-
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
213-
// CHECK-NEXT: entry:
214-
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv.ifunc()
215-
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one.ifunc()
216-
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
217-
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two.ifunc()
218-
// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
219-
// CHECK-NEXT: ret i32 [[ADD3]]
220-
//
221-
//
222229
// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat {
223230
// CHECK-NEXT: resolver_entry:
224231
// CHECK-NEXT: ret ptr @fmv_e._Mls64
@@ -238,28 +245,14 @@ int hoo(void) {
238245
// CHECK-NEXT: ret void
239246
//
240247
//
241-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
242-
// CHECK-NEXT: resolver_entry:
243-
// CHECK-NEXT: call void @__init_cpu_features_resolver()
244-
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
245-
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
246-
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
247-
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
248-
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
249-
// CHECK: resolver_return:
250-
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
251-
// CHECK: resolver_else:
252-
// CHECK-NEXT: ret ptr @fmv_c.default
253-
//
254-
//
255248
// CHECK: Function Attrs: noinline nounwind optnone
256249
// CHECK-LABEL: define {{[^@]+}}@goo
257250
// CHECK-SAME: () #[[ATTR2]] {
258251
// CHECK-NEXT: entry:
259-
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline.ifunc()
260-
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e.ifunc()
261-
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d.ifunc()
262-
// CHECK-NEXT: call void @fmv_c.ifunc()
252+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline()
253+
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e()
254+
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d()
255+
// CHECK-NEXT: call void @fmv_c()
263256
// CHECK-NEXT: [[CALL3:%.*]] = call i32 @fmv_default()
264257
// CHECK-NEXT: ret i32 [[CALL3]]
265258
//
@@ -412,6 +405,20 @@ int hoo(void) {
412405
// CHECK-NEXT: ret ptr @fmv_d.default
413406
//
414407
//
408+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
409+
// CHECK-NEXT: resolver_entry:
410+
// CHECK-NEXT: call void @__init_cpu_features_resolver()
411+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
412+
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
413+
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
414+
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
415+
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
416+
// CHECK: resolver_return:
417+
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
418+
// CHECK: resolver_else:
419+
// CHECK-NEXT: ret ptr @fmv_c.default
420+
//
421+
//
415422
// CHECK: Function Attrs: noinline nounwind optnone
416423
// CHECK-LABEL: define {{[^@]+}}@recur
417424
// CHECK-SAME: () #[[ATTR2]] {
@@ -437,9 +444,9 @@ int hoo(void) {
437444
// CHECK-NEXT: entry:
438445
// CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8
439446
// CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8
440-
// CHECK-NEXT: call void @f(ptr noundef @fmv.ifunc)
441-
// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP1]], align 8
442-
// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP2]], align 8
447+
// CHECK-NEXT: call void @f(ptr noundef @fmv)
448+
// CHECK-NEXT: store ptr @fmv, ptr [[FP1]], align 8
449+
// CHECK-NEXT: store ptr @fmv, ptr [[FP2]], align 8
443450
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FP1]], align 8
444451
// CHECK-NEXT: [[CALL:%.*]] = call i32 [[TMP0]]()
445452
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[FP2]], align 8
@@ -561,13 +568,6 @@ int hoo(void) {
561568
//
562569
//
563570
// CHECK: Function Attrs: noinline nounwind optnone
564-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
565-
// CHECK-SAME: () #[[ATTR2]] {
566-
// CHECK-NEXT: entry:
567-
// CHECK-NEXT: ret void
568-
//
569-
//
570-
// CHECK: Function Attrs: noinline nounwind optnone
571571
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msha1MpmullMf64mm
572572
// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
573573
// CHECK-NEXT: entry:
@@ -700,6 +700,13 @@ int hoo(void) {
700700
// CHECK-NEXT: ret i32 1
701701
//
702702
//
703+
// CHECK: Function Attrs: noinline nounwind optnone
704+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
705+
// CHECK-SAME: () #[[ATTR2]] {
706+
// CHECK-NEXT: entry:
707+
// CHECK-NEXT: ret void
708+
//
709+
//
703710
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
704711
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
705712
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {

0 commit comments

Comments
 (0)