[AArch64] FMV support and necessary target features dependencies.
This is Function Multi Versioning (FMV) implementation for AArch64 target in accordance with Beta Arm C Language Extensions specification https://github.com/ARM-software/acle/blob/main/main/acle.md#function-multi-versioning It supports new "target_version" function attribute and extends existing "target_clones" one. Also missing dependencies for target features were added. Differential Revision: https://reviews.llvm.org/D127812
This commit is contained in:
@@ -1337,6 +1337,20 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
|
||||
Out << ".resolver";
|
||||
}
|
||||
|
||||
static void AppendTargetVersionMangling(const CodeGenModule &CGM,
|
||||
const TargetVersionAttr *Attr,
|
||||
raw_ostream &Out) {
|
||||
if (Attr->isDefaultVersion())
|
||||
return;
|
||||
Out << "._";
|
||||
llvm::SmallVector<StringRef, 8> Feats;
|
||||
Attr->getFeatures(Feats);
|
||||
for (const auto &Feat : Feats) {
|
||||
Out << 'M';
|
||||
Out << Feat;
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendTargetMangling(const CodeGenModule &CGM,
|
||||
const TargetAttr *Attr, raw_ostream &Out) {
|
||||
if (Attr->isDefaultVersion())
|
||||
@@ -1382,14 +1396,27 @@ static void AppendTargetClonesMangling(const CodeGenModule &CGM,
|
||||
const TargetClonesAttr *Attr,
|
||||
unsigned VersionIndex,
|
||||
raw_ostream &Out) {
|
||||
Out << '.';
|
||||
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
|
||||
if (FeatureStr.startswith("arch="))
|
||||
Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
|
||||
else
|
||||
Out << FeatureStr;
|
||||
if (CGM.getTarget().getTriple().isAArch64()) {
|
||||
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
|
||||
if (FeatureStr == "default")
|
||||
return;
|
||||
Out << "._";
|
||||
SmallVector<StringRef, 8> Features;
|
||||
FeatureStr.split(Features, "+");
|
||||
for (auto &Feat : Features) {
|
||||
Out << 'M';
|
||||
Out << Feat;
|
||||
}
|
||||
} else {
|
||||
Out << '.';
|
||||
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
|
||||
if (FeatureStr.startswith("arch="))
|
||||
Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
|
||||
else
|
||||
Out << FeatureStr;
|
||||
|
||||
Out << '.' << Attr->getMangledIndex(VersionIndex);
|
||||
Out << '.' << Attr->getMangledIndex(VersionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
|
||||
@@ -1445,6 +1472,9 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
|
||||
case MultiVersionKind::Target:
|
||||
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
|
||||
break;
|
||||
case MultiVersionKind::TargetVersion:
|
||||
AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
|
||||
break;
|
||||
case MultiVersionKind::TargetClones:
|
||||
AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
|
||||
GD.getMultiVersionIndex(), Out);
|
||||
@@ -2166,10 +2196,12 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
|
||||
const auto *FD = dyn_cast_or_null<FunctionDecl>(GD.getDecl());
|
||||
FD = FD ? FD->getMostRecentDecl() : FD;
|
||||
const auto *TD = FD ? FD->getAttr<TargetAttr>() : nullptr;
|
||||
const auto *TV = FD ? FD->getAttr<TargetVersionAttr>() : nullptr;
|
||||
assert((!TD || !TV) && "both target_version and target specified");
|
||||
const auto *SD = FD ? FD->getAttr<CPUSpecificAttr>() : nullptr;
|
||||
const auto *TC = FD ? FD->getAttr<TargetClonesAttr>() : nullptr;
|
||||
bool AddedAttr = false;
|
||||
if (TD || SD || TC) {
|
||||
if (TD || TV || SD || TC) {
|
||||
llvm::StringMap<bool> FeatureMap;
|
||||
getContext().getFunctionFeatureMap(FeatureMap, GD);
|
||||
|
||||
@@ -3623,12 +3655,18 @@ static unsigned
|
||||
TargetMVPriority(const TargetInfo &TI,
|
||||
const CodeGenFunction::MultiVersionResolverOption &RO) {
|
||||
unsigned Priority = 0;
|
||||
for (StringRef Feat : RO.Conditions.Features)
|
||||
unsigned NumFeatures = 0;
|
||||
for (StringRef Feat : RO.Conditions.Features) {
|
||||
Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
|
||||
NumFeatures++;
|
||||
}
|
||||
|
||||
if (!RO.Conditions.Architecture.empty())
|
||||
Priority = std::max(
|
||||
Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
|
||||
|
||||
Priority += TI.multiVersionFeatureCost() * NumFeatures;
|
||||
|
||||
return Priority;
|
||||
}
|
||||
|
||||
@@ -3673,13 +3711,19 @@ void CodeGenModule::emitMultiVersionFunctions() {
|
||||
}
|
||||
assert(Func && "This should have just been created");
|
||||
}
|
||||
|
||||
const auto *TA = CurFD->getAttr<TargetAttr>();
|
||||
llvm::SmallVector<StringRef, 8> Feats;
|
||||
TA->getAddedFeatures(Feats);
|
||||
|
||||
Options.emplace_back(cast<llvm::Function>(Func),
|
||||
TA->getArchitecture(), Feats);
|
||||
if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) {
|
||||
const auto *TA = CurFD->getAttr<TargetAttr>();
|
||||
llvm::SmallVector<StringRef, 8> Feats;
|
||||
TA->getAddedFeatures(Feats);
|
||||
Options.emplace_back(cast<llvm::Function>(Func),
|
||||
TA->getArchitecture(), Feats);
|
||||
} else {
|
||||
const auto *TVA = CurFD->getAttr<TargetVersionAttr>();
|
||||
llvm::SmallVector<StringRef, 8> Feats;
|
||||
TVA->getFeatures(Feats);
|
||||
Options.emplace_back(cast<llvm::Function>(Func),
|
||||
/*Architecture*/ "", Feats);
|
||||
}
|
||||
});
|
||||
} else if (FD->isTargetClonesMultiVersion()) {
|
||||
const auto *TC = FD->getAttr<TargetClonesAttr>();
|
||||
@@ -3709,10 +3753,19 @@ void CodeGenModule::emitMultiVersionFunctions() {
|
||||
StringRef Architecture;
|
||||
llvm::SmallVector<StringRef, 1> Feature;
|
||||
|
||||
if (Version.startswith("arch="))
|
||||
Architecture = Version.drop_front(sizeof("arch=") - 1);
|
||||
else if (Version != "default")
|
||||
Feature.push_back(Version);
|
||||
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.startswith("arch="))
|
||||
Architecture = Version.drop_front(sizeof("arch=") - 1);
|
||||
else if (Version != "default")
|
||||
Feature.push_back(Version);
|
||||
}
|
||||
|
||||
Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user