Skip to content

Commit 61ec04c

Browse files
committed
[clang][fmv] Drop .ifunc from target_version's entrypoint's mangling (llvm#81194)
Fixes: llvm#81043
1 parent 6982ea8 commit 61ec04c

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
@@ -2577,6 +2577,10 @@ class FunctionDecl : public DeclaratorDecl,
25772577
/// the target-clones functionality.
25782578
bool isTargetClonesMultiVersion() const;
25792579

2580+
/// True if this function is a multiversioned dispatch function as a part of
2581+
/// the target-version functionality.
2582+
bool isTargetVersionMultiVersion() const;
2583+
25802584
/// \brief Get the associated-constraints of this function declaration.
25812585
/// Currently, this will either be a vector of size 1 containing the
25822586
/// 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
@@ -2620,6 +2620,14 @@ function it instructs compiler to emit multiple function versions based on
26202620
priority and target features availability. One of the versions is always
26212621
( implicitly or explicitly ) the ``default`` (fallback). Attribute strings can
26222622
contain dependent features names joined by the "+" sign.
2623+
2624+
For targets that support the GNU indirect function (IFUNC) feature, dispatch
2625+
is performed by emitting an indirect function that is resolved to the appropriate
2626+
target clone at load time. The indirect function is given the name the
2627+
multiversioned function would have if it had been declared without the attribute.
2628+
For backward compatibility with earlier Clang releases, a function alias with an
2629+
``.ifunc`` suffix is also emitted. The ``.ifunc`` suffixed symbol is a deprecated
2630+
feature and support for it may be removed in the future.
26232631
}];
26242632
}
26252633

clang/lib/AST/Decl.cpp

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

3491+
bool FunctionDecl::isTargetVersionMultiVersion() const {
3492+
return isMultiVersion() && hasAttr<TargetVersionAttr>();
3493+
}
3494+
34913495
void
34923496
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
34933497
redeclarable_base::setPreviousDecl(PrevDecl);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "TargetInfo.h"
3030
#include "clang/AST/ASTContext.h"
3131
#include "clang/AST/CharUnits.h"
32+
#include "clang/AST/Decl.h"
3233
#include "clang/AST/DeclCXX.h"
3334
#include "clang/AST/DeclObjC.h"
3435
#include "clang/AST/DeclTemplate.h"
@@ -4055,7 +4056,8 @@ void CodeGenModule::emitMultiVersionFunctions() {
40554056
llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
40564057
if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) {
40574058
ResolverConstant = IFunc->getResolver();
4058-
if (FD->isTargetClonesMultiVersion()) {
4059+
if (FD->isTargetClonesMultiVersion() ||
4060+
FD->isTargetVersionMultiVersion()) {
40594061
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
40604062
llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
40614063
std::string MangledName = getMangledNameImpl(
@@ -4235,8 +4237,18 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
42354237
// a separate resolver).
42364238
std::string ResolverName = MangledName;
42374239
if (getTarget().supportsIFunc()) {
4238-
if (!FD->isTargetClonesMultiVersion())
4240+
switch (FD->getMultiVersionKind()) {
4241+
case MultiVersionKind::None:
4242+
llvm_unreachable("unexpected MultiVersionKind::None for resolver");
4243+
case MultiVersionKind::Target:
4244+
case MultiVersionKind::CPUSpecific:
4245+
case MultiVersionKind::CPUDispatch:
42394246
ResolverName += ".ifunc";
4247+
break;
4248+
case MultiVersionKind::TargetClones:
4249+
case MultiVersionKind::TargetVersion:
4250+
break;
4251+
}
42404252
} else if (FD->isTargetMultiVersion()) {
42414253
ResolverName += ".resolver";
42424254
}

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

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

8787
//.
8888
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
89-
// CHECK: @fmv.ifunc = weak_odr ifunc i32 (), ptr @fmv.resolver
90-
// CHECK: @fmv_one.ifunc = weak_odr ifunc i32 (), ptr @fmv_one.resolver
91-
// CHECK: @fmv_two.ifunc = weak_odr ifunc i32 (), ptr @fmv_two.resolver
92-
// CHECK: @fmv_e.ifunc = weak_odr ifunc i32 (), ptr @fmv_e.resolver
93-
// CHECK: @fmv_c.ifunc = weak_odr ifunc void (), ptr @fmv_c.resolver
94-
// CHECK: @fmv_inline.ifunc = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
95-
// CHECK: @fmv_d.ifunc = internal ifunc i32 (), ptr @fmv_d.resolver
89+
// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
90+
// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
91+
// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
92+
// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
93+
// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
94+
// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
95+
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
96+
// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
97+
// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
98+
// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
99+
// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
100+
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
101+
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
102+
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
96103
//.
97104
// CHECK: Function Attrs: noinline nounwind optnone
98105
// CHECK-LABEL: define {{[^@]+}}@fmv._MrngMflagmMfp16fml
@@ -101,6 +108,32 @@ int hoo(void) {
101108
// CHECK-NEXT: ret i32 1
102109
//
103110
//
111+
// CHECK: Function Attrs: noinline nounwind optnone
112+
// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64
113+
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
114+
// CHECK-NEXT: entry:
115+
// CHECK-NEXT: ret i32 1
116+
//
117+
//
118+
// CHECK: Function Attrs: noinline nounwind optnone
119+
// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp
120+
// CHECK-SAME: () #[[ATTR1]] {
121+
// CHECK-NEXT: entry:
122+
// CHECK-NEXT: ret i32 1
123+
//
124+
//
125+
// CHECK: Function Attrs: noinline nounwind optnone
126+
// CHECK-LABEL: define {{[^@]+}}@foo
127+
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
128+
// CHECK-NEXT: entry:
129+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv()
130+
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one()
131+
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
132+
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two()
133+
// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
134+
// CHECK-NEXT: ret i32 [[ADD3]]
135+
//
136+
//
104137
// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat {
105138
// CHECK-NEXT: resolver_entry:
106139
// CHECK-NEXT: call void @__init_cpu_features_resolver()
@@ -179,42 +212,16 @@ int hoo(void) {
179212
// CHECK-NEXT: ret ptr @fmv.default
180213
//
181214
//
182-
// CHECK: Function Attrs: noinline nounwind optnone
183-
// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64
184-
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
185-
// CHECK-NEXT: entry:
186-
// CHECK-NEXT: ret i32 1
187-
//
188-
//
189215
// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat {
190216
// CHECK-NEXT: resolver_entry:
191217
// CHECK-NEXT: ret ptr @fmv_one._MsimdMls64
192218
//
193219
//
194-
// CHECK: Function Attrs: noinline nounwind optnone
195-
// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp
196-
// CHECK-SAME: () #[[ATTR1]] {
197-
// CHECK-NEXT: entry:
198-
// CHECK-NEXT: ret i32 1
199-
//
200-
//
201220
// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat {
202221
// CHECK-NEXT: resolver_entry:
203222
// CHECK-NEXT: ret ptr @fmv_two._MsimdMfp16
204223
//
205224
//
206-
// CHECK: Function Attrs: noinline nounwind optnone
207-
// CHECK-LABEL: define {{[^@]+}}@foo
208-
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
209-
// CHECK-NEXT: entry:
210-
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv.ifunc()
211-
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one.ifunc()
212-
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
213-
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_two.ifunc()
214-
// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
215-
// CHECK-NEXT: ret i32 [[ADD3]]
216-
//
217-
//
218225
// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat {
219226
// CHECK-NEXT: resolver_entry:
220227
// CHECK-NEXT: ret ptr @fmv_e._Mls64
@@ -234,28 +241,14 @@ int hoo(void) {
234241
// CHECK-NEXT: ret void
235242
//
236243
//
237-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
238-
// CHECK-NEXT: resolver_entry:
239-
// CHECK-NEXT: call void @__init_cpu_features_resolver()
240-
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
241-
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
242-
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
243-
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
244-
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
245-
// CHECK: resolver_return:
246-
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
247-
// CHECK: resolver_else:
248-
// CHECK-NEXT: ret ptr @fmv_c.default
249-
//
250-
//
251244
// CHECK: Function Attrs: noinline nounwind optnone
252245
// CHECK-LABEL: define {{[^@]+}}@goo
253246
// CHECK-SAME: () #[[ATTR2]] {
254247
// CHECK-NEXT: entry:
255-
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline.ifunc()
256-
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e.ifunc()
257-
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d.ifunc()
258-
// CHECK-NEXT: call void @fmv_c.ifunc()
248+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline()
249+
// CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e()
250+
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @fmv_d()
251+
// CHECK-NEXT: call void @fmv_c()
259252
// CHECK-NEXT: [[CALL3:%.*]] = call i32 @fmv_default()
260253
// CHECK-NEXT: ret i32 [[CALL3]]
261254
//
@@ -376,6 +369,20 @@ int hoo(void) {
376369
// CHECK-NEXT: ret ptr @fmv_d.default
377370
//
378371
//
372+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
373+
// CHECK-NEXT: resolver_entry:
374+
// CHECK-NEXT: call void @__init_cpu_features_resolver()
375+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
376+
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
377+
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
378+
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
379+
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
380+
// CHECK: resolver_return:
381+
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
382+
// CHECK: resolver_else:
383+
// CHECK-NEXT: ret ptr @fmv_c.default
384+
//
385+
//
379386
// CHECK: Function Attrs: noinline nounwind optnone
380387
// CHECK-LABEL: define {{[^@]+}}@recur
381388
// CHECK-SAME: () #[[ATTR2]] {
@@ -401,9 +408,9 @@ int hoo(void) {
401408
// CHECK-NEXT: entry:
402409
// CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8
403410
// CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8
404-
// CHECK-NEXT: call void @f(ptr noundef @fmv.ifunc)
405-
// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP1]], align 8
406-
// CHECK-NEXT: store ptr @fmv.ifunc, ptr [[FP2]], align 8
411+
// CHECK-NEXT: call void @f(ptr noundef @fmv)
412+
// CHECK-NEXT: store ptr @fmv, ptr [[FP1]], align 8
413+
// CHECK-NEXT: store ptr @fmv, ptr [[FP2]], align 8
407414
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FP1]], align 8
408415
// CHECK-NEXT: [[CALL:%.*]] = call i32 [[TMP0]]()
409416
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[FP2]], align 8
@@ -525,13 +532,6 @@ int hoo(void) {
525532
//
526533
//
527534
// CHECK: Function Attrs: noinline nounwind optnone
528-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
529-
// CHECK-SAME: () #[[ATTR2]] {
530-
// CHECK-NEXT: entry:
531-
// CHECK-NEXT: ret void
532-
//
533-
//
534-
// CHECK: Function Attrs: noinline nounwind optnone
535535
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msha1MpmullMf64mm
536536
// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
537537
// CHECK-NEXT: entry:
@@ -636,6 +636,13 @@ int hoo(void) {
636636
// CHECK-NEXT: ret i32 1
637637
//
638638
//
639+
// CHECK: Function Attrs: noinline nounwind optnone
640+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
641+
// CHECK-SAME: () #[[ATTR2]] {
642+
// CHECK-NEXT: entry:
643+
// CHECK-NEXT: ret void
644+
//
645+
//
639646
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
640647
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
641648
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {

0 commit comments

Comments
 (0)