-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
[RISCV][FMV] Support target_clones #85786
Conversation
Inside the resolver function, a function named
|
The candidate function priority order is undefined. Currently, it base on declaration order. |
The warning occurs because the RISC-V target_clones syntax
Should we suppress this warning for RISC-V target? Or change the target_clones syntax? |
@llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-backend-risc-v Author: Piyou Chen (BeMg) ChangesThis patch enable the function multiversion(FMV) and It will emit the IFUNC resolver function to select appropriate function during runtime. Patch is 31.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85786.diff 12 Files Affected:
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 374595edd2ce4a..aa48596fbce07d 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1445,7 +1445,8 @@ class TargetInfo : public TransferrableTargetInfo,
/// Identify whether this target supports multiversioning of functions,
/// which requires support for cpu_supports and cpu_is functionality.
bool supportsMultiVersioning() const {
- return getTriple().isX86() || getTriple().isAArch64();
+ return getTriple().isX86() || getTriple().isAArch64() ||
+ getTriple().isRISCV();
}
/// Identify whether this target supports IFuncs.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 5a8fae76a43a4d..0fd75e0b36b123 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13636,6 +13636,15 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
+ } else if (Target->getTriple().isRISCV()) {
+ if (VersionStr != "default") {
+ ParsedTargetAttr ParsedAttr = Target->parseTargetAttr(VersionStr);
+ Features.insert(Features.begin(), ParsedAttr.Features.begin(),
+ ParsedAttr.Features.end());
+ }
+ Features.insert(Features.begin(),
+ Target->getTargetOpts().FeaturesAsWritten.begin(),
+ Target->getTargetOpts().FeaturesAsWritten.end());
} else {
if (VersionStr.starts_with("arch="))
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index a6d4af2b88111a..8e9132c9191a3c 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -257,7 +257,7 @@ bool RISCVTargetInfo::initFeatureMap(
// If a target attribute specified a full arch string, override all the ISA
// extension target features.
- const auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
+ const auto I = llvm::find(FeaturesVec, "+__RISCV_TargetAttrNeedOverride");
if (I != FeaturesVec.end()) {
std::vector<std::string> OverrideFeatures(std::next(I), FeaturesVec.end());
@@ -366,6 +366,12 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
return true;
}
+bool RISCVTargetInfo::isValidFeatureName(StringRef Feature) const {
+ if (Feature.starts_with("__RISCV_TargetAttrNeedOverride"))
+ return true;
+ return llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature);
+}
+
bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
bool Is64Bit = getTriple().isArch64Bit();
return llvm::RISCV::parseCPU(Name, Is64Bit);
@@ -390,7 +396,7 @@ void RISCVTargetInfo::fillValidTuneCPUList(
static void handleFullArchString(StringRef FullArchStr,
std::vector<std::string> &Features) {
- Features.push_back("__RISCV_TargetAttrNeedOverride");
+ Features.push_back("+__RISCV_TargetAttrNeedOverride");
auto RII = llvm::RISCVISAInfo::parseArchString(
FullArchStr, /* EnableExperimentalExtension */ true);
if (llvm::errorToBool(RII.takeError())) {
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index bfbdafb682c851..ef8f59185d753c 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -106,6 +106,8 @@ class RISCVTargetInfo : public TargetInfo {
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
+ bool isValidFeatureName(StringRef Feature) const override;
+
bool hasBitIntType() const override { return true; }
bool hasBFloat16Type() const override { return true; }
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 4a3ff49b0007a3..544c696376cd89 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2803,12 +2803,112 @@ void CodeGenFunction::EmitMultiVersionResolver(
case llvm::Triple::aarch64:
EmitAArch64MultiVersionResolver(Resolver, Options);
return;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ EmitRISCVMultiVersionResolver(Resolver, Options);
+ return;
default:
- assert(false && "Only implemented for x86 and AArch64 targets");
+ assert(false && "Only implemented for x86, AArch64 and RISC-V targets");
}
}
+void CodeGenFunction::EmitRISCVMultiVersionResolver(
+ llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
+
+ auto EmitIFUNCFeatureCheckFunc =
+ [&](std::string CurrFeatStr) -> llvm::Value * {
+ llvm::Constant *FeatStr = Builder.CreateGlobalString(CurrFeatStr);
+ llvm::Type *Args[] = {Int8PtrTy};
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(Builder.getInt1Ty(), Args, /*Variadic*/ false);
+ llvm::FunctionCallee Func =
+ CGM.CreateRuntimeFunction(FTy, "__riscv_ifunc_select");
+ cast<llvm::GlobalValue>(Func.getCallee())->setDSOLocal(true);
+ cast<llvm::GlobalValue>(Func.getCallee())
+ ->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ return Builder.CreateCall(Func, FeatStr);
+ };
+
+ llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
+ Builder.SetInsertPoint(CurBlock);
+
+ bool SupportsIFunc = getContext().getTargetInfo().supportsIFunc();
+ bool HasDefault = false;
+ int DefaultIndex = 0;
+ // Check the each candidate function.
+ for (unsigned Index = 0; Index < Options.size(); Index++) {
+
+ if (Options[Index].Conditions.Features[0].starts_with("default")) {
+ HasDefault = true;
+ DefaultIndex = Index;
+ continue;
+ }
+
+ Builder.SetInsertPoint(CurBlock);
+
+ std::vector<std::string> TargetAttrFeats =
+ getContext()
+ .getTargetInfo()
+ .parseTargetAttr(Options[Index].Conditions.Features[0])
+ .Features;
+
+ if (!TargetAttrFeats.empty()) {
+ // If this function doens't need override, then merge with module level
+ // target features. Otherwise, remain the current target features.
+ auto I = llvm::find(TargetAttrFeats, "+__RISCV_TargetAttrNeedOverride");
+ if (I == TargetAttrFeats.end())
+ TargetAttrFeats.insert(TargetAttrFeats.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.end());
+ else
+ TargetAttrFeats.erase(I);
+
+ // Only consider +<extension-feature>.
+ std::vector<std::string> PlusTargetAttrFeats;
+ for (StringRef Feat : TargetAttrFeats) {
+ if (!getContext().getTargetInfo().isValidFeatureName(
+ Feat.substr(1).str()))
+ continue;
+ if (Feat.starts_with("+"))
+ PlusTargetAttrFeats.push_back(Feat.substr(1).str());
+ }
+
+ // Join with ';' delimiter
+ std::string CurrFeatStr = std::accumulate(
+ std::begin(PlusTargetAttrFeats), std::end(PlusTargetAttrFeats),
+ std::string(), [](const std::string &a, const std::string &b) {
+ return a.empty() ? b : a + ";" + b;
+ });
+
+ llvm::Value *Condition = EmitIFUNCFeatureCheckFunc(CurrFeatStr);
+ llvm::BasicBlock *RetBlock =
+ createBasicBlock("resolver_return", Resolver);
+ CGBuilderTy RetBuilder(*this, RetBlock);
+ CreateMultiVersionResolverReturn(CGM, Resolver, RetBuilder,
+ Options[Index].Function, SupportsIFunc);
+ CurBlock = createBasicBlock("resolver_else", Resolver);
+ Builder.CreateCondBr(Condition, RetBlock, CurBlock);
+ }
+ }
+
+ // Finally, emit the default one.
+ if (HasDefault) {
+ Builder.SetInsertPoint(CurBlock);
+ CreateMultiVersionResolverReturn(
+ CGM, Resolver, Builder, Options[DefaultIndex].Function, SupportsIFunc);
+ return;
+ }
+
+ // If no generic/default, emit an unreachable.
+ Builder.SetInsertPoint(CurBlock);
+ llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+}
+
void CodeGenFunction::EmitAArch64MultiVersionResolver(
llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
assert(!Options.empty() && "No multiversion resolver options found");
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index e8f8aa601ed017..e62657de7b7323 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5013,6 +5013,9 @@ class CodeGenFunction : public CodeGenTypeCache {
void
EmitAArch64MultiVersionResolver(llvm::Function *Resolver,
ArrayRef<MultiVersionResolverOption> Options);
+ void
+ EmitRISCVMultiVersionResolver(llvm::Function *Resolver,
+ ArrayRef<MultiVersionResolverOption> Options);
private:
QualType getVarArgType(const Expr *Arg);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 8ceecff28cbc63..e571dbb384b78d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4161,6 +4161,8 @@ void CodeGenModule::emitMultiVersionFunctions() {
for (auto &CurFeat : VerFeats)
Feature.push_back(CurFeat.trim());
}
+ } else if (getTarget().getTriple().isRISCV()) {
+ Feature.push_back(Version);
} else {
if (Version.starts_with("arch="))
Architecture = Version.drop_front(sizeof("arch=") - 1);
diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp
index 9a79424c4612ce..30c10c35133161 100644
--- a/clang/lib/CodeGen/Targets/RISCV.cpp
+++ b/clang/lib/CodeGen/Targets/RISCV.cpp
@@ -63,9 +63,32 @@ class RISCVABIInfo : public DefaultABIInfo {
CharUnits Field2Off) const;
ABIArgInfo coerceVLSVector(QualType Ty) const;
+
+ using ABIInfo::appendAttributeMangling;
+ void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
+ raw_ostream &Out) const override;
+ void appendAttributeMangling(StringRef AttrStr,
+ raw_ostream &Out) const override;
};
} // end anonymous namespace
+void RISCVABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
+ unsigned Index,
+ raw_ostream &Out) const {
+ appendAttributeMangling(Attr->getFeatureStr(Index), Out);
+}
+
+void RISCVABIInfo::appendAttributeMangling(StringRef AttrStr,
+ raw_ostream &Out) const {
+ if (AttrStr == "default") {
+ Out << ".default";
+ return;
+ }
+
+ Out << '.';
+ Out << AttrStr;
+}
+
void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
QualType RetTy = FI.getReturnType();
if (!getCXXABI().classifyReturnType(FI))
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index ec00fdf3f88d9e..9e44e6a3b70734 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3626,6 +3626,28 @@ bool Sema::checkTargetClonesAttrString(
if (hasArmStreamingInterface(cast<FunctionDecl>(D)))
return Diag(LiteralLoc,
diag::err_sme_streaming_cannot_be_multiversioned);
+ } else if (TInfo.getTriple().isRISCV()) {
+ if (Str.starts_with("arch=")) {
+ // parseTargetAttr will parse full version string,
+ // the following split Cur string is no longer interesting.
+ if ((!Cur.starts_with("arch=")))
+ continue;
+
+ ParsedTargetAttr TargetAttr =
+ Context.getTargetInfo().parseTargetAttr(Str);
+ if (TargetAttr.Features.empty())
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str << TargetClones;
+ } else if (Str == "default") {
+ DefaultIsDupe = HasDefault;
+ HasDefault = true;
+ } else {
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Str << TargetClones;
+ }
+ if (llvm::is_contained(StringsBuffer, Str) || DefaultIsDupe)
+ Diag(CurLoc, diag::warn_target_clone_duplicate_options);
+ StringsBuffer.push_back(Str);
} else {
// Other targets ( currently X86 )
if (Cur.starts_with("arch=")) {
diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c
new file mode 100644
index 00000000000000..70b74befb54ffb
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-clones-riscv.c
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 -triple riscv64-linux-gnu -target-feature +i -S -emit-llvm -o - %s | FileCheck %s
+
+__attribute__((target_clones("default", "arch=rv64gc"))) int foo1(void) { return 1; }
+__attribute__((target_clones("default", "arch=+zbb"))) int foo2(void) { return 2; }
+__attribute__((target_clones("default", "arch=+zbb,+c"))) int foo3(void) { return 3; }
+__attribute__((target_clones("default", "arch=rv64gc", "arch=+zbb,+v"))) int foo4(void) { return 4; }
+__attribute__((target_clones("default"))) int foo5(void) { return 5; }
+
+int bar() {
+ return foo1() + foo2() + foo3() + foo4();
+}
+
+//.
+// CHECK: @[[GLOB0:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1
+// CHECK: @[[GLOB1:[0-9]+]] = private unnamed_addr constant [6 x i8] c"i;zbb\00", align 1
+// CHECK: @[[GLOB2:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;c\00", align 1
+// CHECK: @[[GLOB3:[0-9]+]] = private unnamed_addr constant [25 x i8] c"m;a;f;d;c;zicsr;zifencei\00", align 1
+// CHECK: @[[GLOB4:[0-9]+]] = private unnamed_addr constant [8 x i8] c"i;zbb;v\00", align 1
+// CHECK: @foo1.ifunc = weak_odr alias i32 (), ptr @foo1
+// CHECK: @foo2.ifunc = weak_odr alias i32 (), ptr @foo2
+// CHECK: @foo3.ifunc = weak_odr alias i32 (), ptr @foo3
+// CHECK: @foo4.ifunc = weak_odr alias i32 (), ptr @foo4
+// CHECK: @foo5.ifunc = weak_odr alias i32 (), ptr @foo5
+// CHECK: @foo1 = weak_odr ifunc i32 (), ptr @foo1.resolver
+// CHECK: @foo2 = weak_odr ifunc i32 (), ptr @foo2.resolver
+// CHECK: @foo3 = weak_odr ifunc i32 (), ptr @foo3.resolver
+// CHECK: @foo4 = weak_odr ifunc i32 (), ptr @foo4.resolver
+// CHECK: @foo5 = weak_odr ifunc i32 (), ptr @foo5.resolver
+//.
+// CHECK-LABEL: define dso_local signext i32 @foo1.default(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 1
+//
+//
+// CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB0]])
+// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @"foo1.arch=rv64gc"
+// CHECK: resolver_else:
+// CHECK-NEXT: ret ptr @foo1.default
+//
+//
+// CHECK-LABEL: define dso_local signext i32 @foo2.default(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 2
+//
+//
+// CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB1]])
+// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @"foo2.arch=+zbb"
+// CHECK: resolver_else:
+// CHECK-NEXT: ret ptr @foo2.default
+//
+//
+// CHECK-LABEL: define dso_local signext i32 @foo3.default(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 3
+//
+//
+// CHECK-LABEL: define weak_odr ptr @foo3.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB2]])
+// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @"foo3.arch=+zbb,+c"
+// CHECK: resolver_else:
+// CHECK-NEXT: ret ptr @foo3.default
+//
+//
+// CHECK-LABEL: define dso_local signext i32 @foo4.default(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 4
+//
+//
+// CHECK-LABEL: define weak_odr ptr @foo4.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB3]])
+// CHECK-NEXT: br i1 [[TMP0]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK: resolver_return:
+// CHECK-NEXT: ret ptr @"foo4.arch=rv64gc"
+// CHECK: resolver_else:
+// CHECK-NEXT: [[TMP1:%.*]] = call i1 @__riscv_ifunc_select(ptr @[[GLOB4]])
+// CHECK-NEXT: br i1 [[TMP1]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK: resolver_return1:
+// CHECK-NEXT: ret ptr @"foo4.arch=+zbb,+v"
+// CHECK: resolver_else2:
+// CHECK-NEXT: ret ptr @foo4.default
+//
+//
+// CHECK-LABEL: define dso_local signext i32 @foo5.default(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 5
+//
+//
+// CHECK-LABEL: define weak_odr ptr @foo5.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @foo5.default
+//
+//
+// CHECK-LABEL: define dso_local signext i32 @bar(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call signext i32 @foo1()
+// CHECK-NEXT: [[CALL1:%.*]] = call signext i32 @foo2()
+// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
+// CHECK-NEXT: [[CALL2:%.*]] = call signext i32 @foo3()
+// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]]
+// CHECK-NEXT: [[CALL4:%.*]] = call signext i32 @foo4()
+// CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[ADD3]], [[CALL4]]
+// CHECK-NEXT: ret i32 [[ADD5]]
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i" }
+// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" }
+// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+zbb" }
+// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "n...
[truncated]
|
The proposal can be found at the riscv-non-isa/riscv-c-api-doc#48. |
Can this land until #85790 lands? |
|
1767d49
to
ad2c9f3
Compare
Stack on #94440 |
ad2c9f3
to
aaa7017
Compare
ping |
A test case will crash, missing
|
…cv_fmv
Fixed and add new test. |
Rename and update the description of err_os_unsupport_riscv_target_clones because not only target clones trigger FMV. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, and I would prefer wait one more LGTM from Craig or Philip OR wait one more week to make sure no further comment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
__attribute__((target_clones("default", "arch=+zbb", "arch=+zba", "arch=+zbb,+zba"))) int foo7(void) { return 2; } | ||
__attribute__((target_clones("default", "arch=+zbb;priority=2", "arch=+zba;priority=1", "arch=+zbb,+zba;priority=3"))) int foo8(void) { return 2; } | ||
__attribute__((target_clones("default", "arch=+zbb;priority=1", "priority=2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo9(void) { return 2; } | ||
__attribute__((target_clones("default", "arch=+zbb;priority=-1", "priority=-2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo10(void) { return 2; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The grammar defined in riscv-non-isa/riscv-c-api-doc#85 does not allow for priority=-1
, as you're only allowed the digits 0-9 after priority=
. Was it intentional to support or not support negative priorities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing that out. I've updated the grammar to support negative priorities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
(I only did a quick pass on this version assuming mostly unchanged from prior. Wanted to explicitly chime in with support for the priority syntax.)
This patch enable `target_version` attribute for RISC-V target. The proposal of `target_version` syntax can be found at the riscv-non-isa/riscv-c-api-doc#48 (which has landed), as modified by the proposed riscv-non-isa/riscv-c-api-doc#85 (which adds the priority syntax). `target_version` attribute will trigger the function multi-versioning feature and act like `target_clones` attribute. See #85786 for the implementation of `target_clones`.
Fix the buildbot failure caused by heap use-after-free error. Origin message: This patch enable `target_version` attribute for RISC-V target. The proposal of `target_version` syntax can be found at the riscv-non-isa/riscv-c-api-doc#48 (which has landed), as modified by the proposed riscv-non-isa/riscv-c-api-doc#85 (which adds the priority syntax). `target_version` attribute will trigger the function multi-versioning feature and act like `target_clones` attribute. See #85786 for the implementation of `target_clones`.
This patch enable the function multiversion(FMV) and
target_clones
attribute for RISC-V target.The proposal of
target_clones
syntax can be found at the riscv-non-isa/riscv-c-api-doc#48 (which has landed), as modified by the proposed riscv-non-isa/riscv-c-api-doc#85 (which adds the priority syntax).It supports the
target_clones
function attribute and function multiversioning feature for RISC-V target. It will generate the ifunc resolver function for the function that declared with target_clones attribute.The resolver function will check the version support by runtime object
__riscv_feature_bits
.For example:
the corresponding resolver will be like: