Skip to content

[FMV] Allow mixing target_version with target_clones. #86493

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
merged 1 commit into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3088,6 +3088,20 @@ def TargetClones : InheritableAttr {
StringRef getFeatureStr(unsigned Index) const {
return *(featuresStrs_begin() + Index);
}
bool isDefaultVersion(unsigned Index) const {
return getFeatureStr(Index) == "default";
}
void getFeatures(llvm::SmallVectorImpl<StringRef> &Out,
unsigned Index) const {
if (isDefaultVersion(Index)) return;
StringRef Features = getFeatureStr(Index);
SmallVector<StringRef, 8> AttrFeatures;
Features.split(AttrFeatures, "+");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
Out.push_back(Feature);
}
}
// Given an index into the 'featuresStrs' sequence, compute a unique
// ID to be used with function name mangling for the associated variant.
// This mapping is necessary due to a requirement that the mangling ID
Expand Down
15 changes: 6 additions & 9 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13676,22 +13676,19 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
std::vector<std::string> Features;
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (Target->getTriple().isAArch64()) {
// TargetClones for AArch64
if (VersionStr != "default") {
SmallVector<StringRef, 1> VersionFeatures;
VersionStr.split(VersionFeatures, "+");
for (auto &VFeature : VersionFeatures) {
VFeature = VFeature.trim();
llvm::SmallVector<StringRef, 8> Feats;
TC->getFeatures(Feats, GD.getMultiVersionIndex());
for (StringRef Feat : Feats)
if (Target->validateCpuSupports(Feat.str()))
// Use '?' to mark features that came from AArch64 TargetClones.
Features.push_back((StringRef{"?"} + VFeature).str());
}
}
Features.push_back("?" + Feat.str());
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
} else {
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (VersionStr.starts_with("arch="))
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
else if (VersionStr != "default")
Expand Down
105 changes: 50 additions & 55 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3712,7 +3712,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
if (!FD->doesDeclarationForceExternallyVisibleDefinition() &&
!FD->isTargetVersionMultiVersion())
(!FD->isMultiVersion() ||
!FD->getASTContext().getTargetInfo().getTriple().isAArch64()))
return;

StringRef MangledName = getMangledName(GD);
Expand Down Expand Up @@ -3994,10 +3995,11 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
auto *Spec = FD->getAttr<CPUSpecificAttr>();
for (unsigned I = 0; I < Spec->cpus_size(); ++I)
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
} else if (FD->isTargetClonesMultiVersion()) {
auto *Clone = FD->getAttr<TargetClonesAttr>();
for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I)
if (Clone->isFirstOfVersion(I))
} 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))
EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
// Ensure that the resolver function is also emitted.
GetOrCreateMultiVersionResolver(GD);
Expand Down Expand Up @@ -4137,57 +4139,49 @@ void CodeGenModule::emitMultiVersionFunctions() {
};

bool HasDefaultDecl = !FD->isTargetVersionMultiVersion();
bool ShouldEmitResolver = !FD->isTargetVersionMultiVersion();
bool ShouldEmitResolver =
!getContext().getTargetInfo().getTriple().isAArch64();
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
if (FD->isTargetMultiVersion()) {
getContext().forEachMultiversionedFunctionVersion(
FD, [&](const FunctionDecl *CurFD) {
llvm::SmallVector<StringRef, 8> Feats;
llvm::Function *Func = createFunction(CurFD);

if (const auto *TA = CurFD->getAttr<TargetAttr>()) {
TA->getAddedFeatures(Feats);
Options.emplace_back(Func, TA->getArchitecture(), Feats);
} else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) {
bool HasDefaultDef = TVA->isDefaultVersion() &&
CurFD->doesThisDeclarationHaveABody();
HasDefaultDecl |= TVA->isDefaultVersion();
ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef);
TVA->getFeatures(Feats);
Options.emplace_back(Func, /*Architecture*/ "", Feats);
} else
llvm_unreachable("unexpected MultiVersionKind");
});
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) {
if (!TC->isFirstOfVersion(I))
continue;
getContext().forEachMultiversionedFunctionVersion(
FD, [&](const FunctionDecl *CurFD) {
llvm::SmallVector<StringRef, 8> Feats;

llvm::Function *Func = createFunction(FD, I);
StringRef Version = TC->getFeatureStr(I);
StringRef Architecture;
llvm::SmallVector<StringRef, 1> Feature;

if (getTarget().getTriple().isAArch64()) {
if (Version != "default") {
llvm::SmallVector<StringRef, 8> VerFeats;
Version.split(VerFeats, "+");
for (auto &CurFeat : VerFeats)
Feature.push_back(CurFeat.trim());
}
} else {
if (Version.starts_with("arch="))
Architecture = Version.drop_front(sizeof("arch=") - 1);
else if (Version != "default")
Feature.push_back(Version);
}

Options.emplace_back(Func, Architecture, Feature);
}
} else {
assert(0 && "Expected a target or target_clones multiversion function");
continue;
}
if (const auto *TA = CurFD->getAttr<TargetAttr>()) {
TA->getAddedFeatures(Feats);
llvm::Function *Func = createFunction(CurFD);
Options.emplace_back(Func, TA->getArchitecture(), Feats);
} else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) {
bool HasDefaultDef = TVA->isDefaultVersion() &&
CurFD->doesThisDeclarationHaveABody();
HasDefaultDecl |= TVA->isDefaultVersion();
ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef);
TVA->getFeatures(Feats);
llvm::Function *Func = createFunction(CurFD);
Options.emplace_back(Func, /*Architecture*/ "", Feats);
} else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) {
ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody();
for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) {
if (!TC->isFirstOfVersion(I))
continue;

llvm::Function *Func = createFunction(CurFD, I);
StringRef Architecture;
Feats.clear();
if (getTarget().getTriple().isAArch64())
TC->getFeatures(Feats, I);
else {
StringRef Version = TC->getFeatureStr(I);
if (Version.starts_with("arch="))
Architecture = Version.drop_front(sizeof("arch=") - 1);
else if (Version != "default")
Feats.push_back(Version);
}
Options.emplace_back(Func, Architecture, Feats);
}
} else
llvm_unreachable("unexpected MultiVersionKind");
});

if (!ShouldEmitResolver)
continue;
Expand Down Expand Up @@ -4378,7 +4372,7 @@ void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
assert(FD && "Not a FunctionDecl?");

if (FD->isTargetVersionMultiVersion()) {
if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) {
std::string MangledName =
getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
if (!DeferredResolversToEmit.insert(MangledName).second)
Expand Down Expand Up @@ -4489,7 +4483,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(

if (FD->isMultiVersion()) {
UpdateMultiVersionNames(GD, FD, MangledName);
if (FD->isTargetVersionMultiVersion() && !FD->isUsed())
if (FD->getASTContext().getTargetInfo().getTriple().isAArch64() &&
!FD->isUsed())
AddDeferredMultiVersionResolverToEmit(GD);
else if (!IsForDefinition)
return GetOrCreateMultiVersionResolver(GD);
Expand Down
Loading