[clang] [RISCV] Support target attribute for function (PR #65948)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 11 04:32:57 PDT 2023
llvmbot wrote:
@llvm/pr-subscribers-clang
<details>
<summary>Changes</summary>
The spec of RISC-V target feature is https://github.com/riscv-non-isa/riscv-c-api-doc/pull/35.
---
This patch implements target attribute for RISC-V.
--
Full diff: https://github.com/llvm/llvm-project/pull/65948.diff
3 Files Affected:
- (modified) clang/lib/Basic/Targets/RISCV.cpp (+95-2)
- (modified) clang/lib/Basic/Targets/RISCV.h (+2)
- (added) clang/test/CodeGen/RISCV/riscv-func-attr-target.c (+55)
<pre>
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index d55ab76395c8271..e132e3bfc9f5b75 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -224,6 +224,21 @@ ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
+static std::vector<std::string>
+resolveTargetAttrOverride(const std::vector<std::string> &FeaturesVec) {
+ if (!llvm::is_contained(FeaturesVec, "__RISCV_TargetAttrNeedOverride"))
+ return FeaturesVec;
+
+ auto VecPtr = FeaturesVec.begin();
+
+ while (*VecPtr != "__RISCV_TargetAttrNeedOverride")
+ VecPtr++;
+
+ VecPtr++;
+
+ return std::vector(VecPtr, FeaturesVec.end());
+}
+
bool RISCVTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
@@ -237,7 +252,10 @@ bool RISCVTargetInfo::initFeatureMap(
Features["32bit"] = true;
}
- auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
+ std::vector<std::string> NewFeaturesVec =
+ resolveTargetAttrOverride(FeaturesVec);
+
+ auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, NewFeaturesVec);
if (!ParseResult) {
std::string Buffer;
llvm::raw_string_ostream OutputErrMsg(Buffer);
@@ -251,7 +269,7 @@ bool RISCVTargetInfo::initFeatureMap(
// RISCVISAInfo makes implications for ISA features
std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
// Add non-ISA features like `relax` and `save-restore` back
- for (const std::string &Feature : FeaturesVec)
+ for (const std::string &Feature : NewFeaturesVec)
if (!llvm::is_contained(ImpliedFeatures, Feature))
ImpliedFeatures.push_back(Feature);
@@ -346,3 +364,78 @@ void RISCVTargetInfo::fillValidTuneCPUList(
bool Is64Bit = getTriple().isArch64Bit();
llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
}
+
+static void handleFullArchString(StringRef FullArchStr,
+ std::vector<std::string> &Features) {
+ Features.push_back("__RISCV_TargetAttrNeedOverride");
+ auto RII = llvm::RISCVISAInfo::parseArchString(
+ FullArchStr, /* EnableExperimentalExtension */ true);
+ if (!RII) {
+ consumeError(RII.takeError());
+ // Forward the invalid FullArchStr.
+ Features.push_back("+" + FullArchStr.str());
+ } else {
+ std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
+ for (auto FeatString : FeatStrings)
+ Features.push_back(FeatString);
+ }
+}
+
+ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
+ ParsedTargetAttr Ret;
+ if (Features == "default")
+ return Ret;
+ SmallVector<StringRef, 1> AttrFeatures;
+ Features.split(AttrFeatures, ";");
+ bool FoundArch = false;
+
+ for (auto &Feature : AttrFeatures) {
+ Feature = Feature.trim();
+ StringRef AttrString = Feature.split("=").second.trim();
+
+ if (Feature.startswith("arch=")) {
+ // Override last features
+ Ret.Features.clear();
+ FoundArch = true;
+
+ if (AttrString.startswith("+")) {
+ // EXTENSION like arch=+v,+zbb
+ SmallVector<StringRef, 1> Exts;
+ AttrString.split(Exts, ",");
+ for (auto Ext : Exts) {
+ if (Ext.empty())
+ continue;
+
+ StringRef ExtName = Ext.substr(1);
+ std::string TargetFeature =
+ llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
+ if (!TargetFeature.empty())
+ Ret.Features.push_back(Ext.front() + TargetFeature);
+ else
+ Ret.Features.push_back(Ext.str());
+ }
+ } else {
+ // full-arch-string like arch=rv64gcv
+ handleFullArchString(AttrString, Ret.Features);
+ }
+ continue;
+ } else if (Feature.startswith("cpu=")) {
+ Ret.CPU = AttrString;
+
+ if (!FoundArch) {
+ // Update Features with CPU's features
+ StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
+ if (MarchFromCPU != "") {
+ Ret.Features.clear();
+ handleFullArchString(MarchFromCPU, Ret.Features);
+ }
+ }
+
+ continue;
+ } else if (Feature.startswith("tune=")) {
+ Ret.Tune = AttrString;
+ continue;
+ }
+ }
+ return Ret;
+}
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 6be0e49ca2f5525..c1892870de24c40 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -114,6 +114,8 @@ class RISCVTargetInfo : public TargetInfo {
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool isValidTuneCPUName(StringRef Name) const override;
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
+ bool supportsTargetAttributeTune() const override { return true; }
+ ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c
new file mode 100644
index 000000000000000..e75cd3d64ad91ad
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c
@@ -0,0 +1,55 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \
+// RUN: -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: define dso_local void @testDefault
+// CHECK-SAME: () #0 {
+void testDefault() {}
+// CHECK-LABEL: define dso_local void @testMultiAttrStr
+// CHECK-SAME: () #1 {
+__attribute__((target("cpu=rocket-rv64;tune=generic-rv64;arch=+v"))) void
+testMultiAttrStr() {}
+// CHECK-LABEL: define dso_local void @testSingleExtension
+// CHECK-SAME: () #2 {
+__attribute__((target("arch=+zbb"))) void testSingleExtension() {}
+// CHECK-LABEL: define dso_local void @testMultiExtension
+// CHECK-SAME: () #3 {
+__attribute__((target("arch=+zbb,+v,+zicond"))) void testMultiExtension() {}
+// CHECK-LABEL: define dso_local void @testFullArch
+// CHECK-SAME: () #4 {
+__attribute__((target("arch=rv64gc_zbb"))) void testFullArch() {}
+// CHECK-LABEL: define dso_local void @testFullArchButSmallThanCmdArch
+// CHECK-SAME: () #5 {
+__attribute__((target("arch=rv64im"))) void testFullArchButSmallThanCmdArch() {}
+// CHECK-LABEL: define dso_local void @testAttrArchAndAttrCpu
+// CHECK-SAME: () #6 {
+__attribute__((target("cpu=sifive-u54;arch=+zbb"))) void
+testAttrArchAndAttrCpu() {}
+// CHECK-LABEL: define dso_local void @testAttrFullArchAndAttrCpu
+// CHECK-SAME: () #7 {
+__attribute__((target("cpu=sifive-u54;arch=rv64im"))) void
+testAttrFullArchAndAttrCpu() {}
+// CHECK-LABEL: define dso_local void @testAttrCpuOnly
+// CHECK-SAME: () #8 {
+__attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {}
+// CHECK-LABEL: define dso_local void @testMultiArchSelectLast
+// CHECK-SAME: () #4 {
+__attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {}
+// CHECK-LABEL: define dso_local void @testMultiCpuSelectLast
+// CHECK-SAME: () #8 {
+__attribute__((target("cpu=sifive-u74;cpu=sifive-u54"))) void testMultiCpuSelectLast() {}
+// CHECK-LABEL: define dso_local void @testMultiTuneSelectLast
+// CHECK-SAME: () #9 {
+__attribute__((target("tune=sifive-u74;tune=sifive-u54"))) void testMultiTuneSelectLast() {}
+
+//.
+// CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+zifencei" }
+// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" "tune-cpu"="generic-rv64" }
+// CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+zbb,+zifencei" }
+// CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" }
+// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+zbb,+zicsr,+zifencei" }
+// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m" }
+// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+zbb,+zifencei" }
+// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m" }
+// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+zicsr,+zifencei" }
+// CHECK: attributes #9 = { {{.*}}"target-features"="+64bit,+a,+m,+zifencei" "tune-cpu"="sifive-u54" }
</pre>
</details>
https://github.com/llvm/llvm-project/pull/65948
More information about the cfe-commits
mailing list