aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorPavel Iliin <Pavel.Iliin@arm.com>2021-12-15 02:12:37 +0000
committerPavel Iliin <Pavel.Iliin@arm.com>2022-12-20 15:42:25 +0000
commite43924a75145d2f9e722f74b673145c3e62bfd07 (patch)
treeb1e75d388206af5bf7a9c7a19951941a87136eb7 /clang/lib/CodeGen/CodeGenFunction.cpp
parentdaa022ca5707d8ddde987d3c8c2aea6bd9954e3f (diff)
downloadllvm-e43924a75145d2f9e722f74b673145c3e62bfd07.zip
llvm-e43924a75145d2f9e722f74b673145c3e62bfd07.tar.gz
llvm-e43924a75145d2f9e722f74b673145c3e62bfd07.tar.bz2
[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
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp88
1 files changed, 83 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 874a083..4125730 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2627,8 +2627,22 @@ void CodeGenFunction::EmitKCFIOperandBundle(
Bundles.emplace_back("kcfi", CGM.CreateKCFITypeId(FP->desugar()));
}
-llvm::Value *
-CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) {
+llvm::Value *CodeGenFunction::FormAArch64ResolverCondition(
+ const MultiVersionResolverOption &RO) {
+ llvm::SmallVector<StringRef, 8> CondFeatures;
+ for (const StringRef &Feature : RO.Conditions.Features) {
+ // Form condition for features which are not yet enabled in target
+ if (!getContext().getTargetInfo().hasFeature(Feature))
+ CondFeatures.push_back(Feature);
+ }
+ if (!CondFeatures.empty()) {
+ return EmitAArch64CpuSupports(CondFeatures);
+ }
+ return nullptr;
+}
+
+llvm::Value *CodeGenFunction::FormX86ResolverCondition(
+ const MultiVersionResolverOption &RO) {
llvm::Value *Condition = nullptr;
if (!RO.Conditions.Architecture.empty())
@@ -2666,8 +2680,72 @@ static void CreateMultiVersionResolverReturn(CodeGenModule &CGM,
void CodeGenFunction::EmitMultiVersionResolver(
llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
- assert(getContext().getTargetInfo().getTriple().isX86() &&
- "Only implemented for x86 targets");
+
+ llvm::Triple::ArchType ArchType =
+ getContext().getTargetInfo().getTriple().getArch();
+
+ switch (ArchType) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ EmitX86MultiVersionResolver(Resolver, Options);
+ return;
+ case llvm::Triple::aarch64:
+ EmitAArch64MultiVersionResolver(Resolver, Options);
+ return;
+
+ default:
+ assert(false && "Only implemented for x86 and AArch64 targets");
+ }
+}
+
+void CodeGenFunction::EmitAArch64MultiVersionResolver(
+ llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
+ assert(!Options.empty() && "No multiversion resolver options found");
+ assert(Options.back().Conditions.Features.size() == 0 &&
+ "Default case must be last");
+ bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
+ assert(SupportsIFunc &&
+ "Multiversion resolver requires target IFUNC support");
+ bool AArch64CpuInitialized = false;
+ llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
+
+ for (const MultiVersionResolverOption &RO : Options) {
+ Builder.SetInsertPoint(CurBlock);
+ llvm::Value *Condition = FormAArch64ResolverCondition(RO);
+
+ // The 'default' or 'all features enabled' case.
+ if (!Condition) {
+ CreateMultiVersionResolverReturn(CGM, Resolver, Builder, RO.Function,
+ SupportsIFunc);
+ return;
+ }
+
+ if (!AArch64CpuInitialized) {
+ Builder.SetInsertPoint(CurBlock, CurBlock->begin());
+ EmitAArch64CpuInit();
+ AArch64CpuInitialized = true;
+ Builder.SetInsertPoint(CurBlock);
+ }
+
+ llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
+ CGBuilderTy RetBuilder(*this, RetBlock);
+ CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder, RO.Function,
+ SupportsIFunc);
+ CurBlock = createBasicBlock("resolver_else", Resolver);
+ Builder.CreateCondBr(Condition, RetBlock, CurBlock);
+ }
+
+ // If no default, emit an unreachable.
+ Builder.SetInsertPoint(CurBlock);
+ llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+}
+
+void CodeGenFunction::EmitX86MultiVersionResolver(
+ llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
@@ -2678,7 +2756,7 @@ void CodeGenFunction::EmitMultiVersionResolver(
for (const MultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock);
- llvm::Value *Condition = FormResolverCondition(RO);
+ llvm::Value *Condition = FormX86ResolverCondition(RO);
// The 'default' or 'generic' case.
if (!Condition) {