diff options
author | Alexandros Lamprineas <alexandros.lamprineas@arm.com> | 2025-06-02 11:04:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-02 11:04:00 +0100 |
commit | b3fd2ea88875e58c66dd67870ff822cedf2570cf (patch) | |
tree | c267a3575e52a159f224fe4ed465e1866a86ea38 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 68fd6f4eb86121d107dd4d0b282b11b48e82183b (diff) | |
download | llvm-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.cpp | 25 |
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()) { |