BeMg updated this revision to Diff 557995.
BeMg added a comment.

1. remain else if by removing continue
2. Keep NonISAExtFeature after override
3. Update testcase with -target-feature +save-restore
4. Improve resolveTargetOverride function


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151730/new/

https://reviews.llvm.org/D151730

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Basic/Targets/RISCV.h
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c
  clang/test/CodeGen/RISCV/riscv-func-attr-target.c

Index: clang/test/CodeGen/RISCV/riscv-func-attr-target.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/riscv-func-attr-target.c
@@ -0,0 +1,46 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m \
+// RUN:  -target-feature +a -target-feature +save-restore \
+// 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: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei" }
+// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" "tune-cpu"="generic-rv64" }
+// CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" }
+// CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+save-restore,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" }
+// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei" }
+// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore" }
+// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" }
+// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore" }
+// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei" }
Index: clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c
@@ -0,0 +1,10 @@
+// REQUIRES: riscv-registered-target
+// RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \
+// RUN:  -emit-llvm %s 2>&1 | FileCheck %s
+
+// CHECK: error: duplicate 'arch=' in the 'target' attribute string;
+__attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {}
+// CHECK: error: duplicate 'cpu=' in the 'target' attribute string;
+__attribute__((target("cpu=sifive-u74;cpu=sifive-u54"))) void testMultiCpuSelectLast() {}
+// CHECK: error: duplicate 'tune=' in the 'target' attribute string;
+__attribute__((target("tune=sifive-u74;tune=sifive-u54"))) void testMultiTuneSelectLast() {}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3450,6 +3450,11 @@
     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
            << Unknown << Tune << ParsedAttrs.Tune << Target;
 
+  if (Context.getTargetInfo().getTriple().isRISCV() &&
+      ParsedAttrs.Duplicate != "")
+    return Diag(LiteralLoc, diag::err_duplicate_target_attribute)
+           << Duplicate << None << ParsedAttrs.Duplicate << Target;
+
   if (ParsedAttrs.Duplicate != "")
     return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
            << Duplicate << None << ParsedAttrs.Duplicate << Target;
Index: clang/lib/Basic/Targets/RISCV.h
===================================================================
--- clang/lib/Basic/Targets/RISCV.h
+++ clang/lib/Basic/Targets/RISCV.h
@@ -114,6 +114,8 @@
   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:
Index: clang/lib/Basic/Targets/RISCV.cpp
===================================================================
--- clang/lib/Basic/Targets/RISCV.cpp
+++ clang/lib/Basic/Targets/RISCV.cpp
@@ -224,6 +224,47 @@
                         clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
 }
 
+static std::vector<std::string>
+collectNonISAExtFeature(const std::vector<std::string> &FeaturesVec, int XLen) {
+  auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
+  auto FeatureNeedOveride = std::vector<std::string>(FeaturesVec.begin(), I);
+  auto ParseResult =
+      llvm::RISCVISAInfo::parseFeatures(XLen, FeatureNeedOveride);
+
+  if (!ParseResult) {
+    consumeError(ParseResult.takeError());
+    return std::vector<std::string>();
+  }
+
+  std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
+
+  std::vector<std::string> NonISAExtFeatureVec;
+
+  for (auto Feat : FeatureNeedOveride) {
+    if (!llvm::is_contained(ImpliedFeatures, Feat))
+      NonISAExtFeatureVec.push_back(Feat);
+  }
+
+  return NonISAExtFeatureVec;
+}
+
+static std::vector<std::string>
+resolveTargetAttrOverride(const std::vector<std::string> &FeaturesVec,
+                          int XLen) {
+  auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
+  if (I == FeaturesVec.end())
+    return FeaturesVec;
+
+  std::vector<std::string> NonISAExtFeature =
+      collectNonISAExtFeature(FeaturesVec, XLen);
+
+  auto ResolvedFeature = std::vector(++I, FeaturesVec.end());
+  ResolvedFeature.insert(ResolvedFeature.end(), NonISAExtFeature.begin(),
+                         NonISAExtFeature.end());
+
+  return ResolvedFeature;
+}
+
 bool RISCVTargetInfo::initFeatureMap(
     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
     const std::vector<std::string> &FeaturesVec) const {
@@ -237,7 +278,10 @@
     Features["32bit"] = true;
   }
 
-  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
+  std::vector<std::string> NewFeaturesVec =
+      resolveTargetAttrOverride(FeaturesVec, XLen);
+
+  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, NewFeaturesVec);
   if (!ParseResult) {
     std::string Buffer;
     llvm::raw_string_ostream OutputErrMsg(Buffer);
@@ -251,7 +295,7 @@
   // 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 +390,82 @@
   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();
+      if (FoundArch)
+        Ret.Duplicate = "arch=";
+      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);
+      }
+    } else if (Feature.startswith("cpu=")) {
+      if (!Ret.CPU.empty())
+        Ret.Duplicate = "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);
+        }
+      }
+    } else if (Feature.startswith("tune=")) {
+      if (!Ret.Tune.empty())
+        Ret.Duplicate = "tune=";
+
+      Ret.Tune = AttrString;
+    }
+  }
+  return Ret;
+}
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3143,6 +3143,10 @@
 def err_attribute_unsupported
     : Error<"%0 attribute is not supported on targets missing %1;"
             " specify an appropriate -march= or -mcpu=">;
+def err_duplicate_target_attribute
+    : Error<"%select{unsupported|duplicate|unknown}0%select{| CPU|"
+              " tune CPU}1 '%2' in the '%select{target|target_clones|target_version}3' "
+              "attribute string; ">;
 // The err_*_attribute_argument_not_int are separate because they're used by
 // VerifyIntegerConstantExpression.
 def err_aligned_attribute_argument_not_int : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to