aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorAlexandros Lamprineas <alexandros.lamprineas@arm.com>2025-06-02 11:04:00 +0100
committerGitHub <noreply@github.com>2025-06-02 11:04:00 +0100
commitb3fd2ea88875e58c66dd67870ff822cedf2570cf (patch)
treec267a3575e52a159f224fe4ed465e1866a86ea38 /clang/lib/CodeGen/CodeGenModule.cpp
parent68fd6f4eb86121d107dd4d0b282b11b48e82183b (diff)
downloadllvm-b3fd2ea88875e58c66dd67870ff822cedf2570cf.zip
llvm-b3fd2ea88875e58c66dd67870ff822cedf2570cf.tar.gz
llvm-b3fd2ea88875e58c66dd67870ff822cedf2570cf.tar.bz2
[Clang][FMV] Stop emitting implicit default version using target_clones. (#141808)
With the current behavior the following example yields a linker error: "multiple definition of `foo.default'" // Translation Unit 1 __attribute__((target_clones("dotprod, sve"))) int foo(void) { return 1; } // Translation Unit 2 int foo(void) { return 0; } __attribute__((target_version("dotprod"))) int foo(void); __attribute__((target_version("sve"))) int foo(void); int bar(void) { return foo(); } That is because foo.default is generated twice. As a user I don't find this particularly intuitive. If I wanted the default to be generated in TU1 I'd rather write target_clones("dotprod, sve", "default") explicitly. When changing the code I noticed that the RISC-V target defers the resolver emission when encountering a target_version definition. This seems accidental since it only makes sense for AArch64, where we only emit a resolver once we've processed the entire TU, and only if the default version is present. I've changed this so that RISC-V immediately emmits the resolver. I adjusted the codegen tests since the functions now appear in a different order. Implements https://github.com/ARM-software/acle/pull/377
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp25
1 files changed, 12 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 6d2c705..9383c57 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4237,19 +4237,19 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
} else if (auto *TC = FD->getAttr<TargetClonesAttr>()) {
for (unsigned I = 0; I < TC->featuresStrs_size(); ++I)
- // AArch64 favors the default target version over the clone if any.
- if ((!TC->isDefaultVersion(I) || !getTarget().getTriple().isAArch64()) &&
- TC->isFirstOfVersion(I))
+ if (TC->isFirstOfVersion(I))
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
- // Ensure that the resolver function is also emitted.
- GetOrCreateMultiVersionResolver(GD);
} else
EmitGlobalFunctionDefinition(GD, GV);
- // Defer the resolver emission until we can reason whether the TU
- // contains a default target version implementation.
- if (FD->isTargetVersionMultiVersion())
- AddDeferredMultiVersionResolverToEmit(GD);
+ // Ensure that the resolver function is also emitted.
+ if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) {
+ // On AArch64 defer the resolver emission until the entire TU is processed.
+ if (getTarget().getTriple().isAArch64())
+ AddDeferredMultiVersionResolverToEmit(GD);
+ else
+ GetOrCreateMultiVersionResolver(GD);
+ }
}
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
@@ -4351,7 +4351,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
};
// For AArch64, a resolver is only emitted if a function marked with
- // target_version("default")) or target_clones() is present and defined
+ // target_version("default")) or target_clones("default") is defined
// in this TU. For other architectures it is always emitted.
bool ShouldEmitResolver = !getTarget().getTriple().isAArch64();
SmallVector<CodeGenFunction::FMVResolverOption, 10> Options;
@@ -4374,12 +4374,11 @@ void CodeGenModule::emitMultiVersionFunctions() {
TVA->getFeatures(Feats, Delim);
Options.emplace_back(Func, Feats);
} else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) {
- if (IsDefined)
- ShouldEmitResolver = true;
for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) {
if (!TC->isFirstOfVersion(I))
continue;
-
+ if (TC->isDefaultVersion(I) && IsDefined)
+ ShouldEmitResolver = true;
llvm::Function *Func = createFunction(CurFD, I);
Feats.clear();
if (getTarget().getTriple().isX86()) {