BeMg created this revision.
Herald added subscribers: jobnoorman, luke, VincentWu, vkmr, frasercrmck, 
luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, 
PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, 
shiva0217, kito-cheng, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, 
hiraditya, arichardson.
Herald added a project: All.
BeMg requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, pcwang-thead, eopXD, 
MaskRay.
Herald added projects: clang, LLVM.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151730

Files:
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/Targets/RISCV.cpp
  clang/lib/Basic/Targets/RISCV.h
  clang/test/CodeGen/RISCV/riscv-func-attr-target.c
  llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Index: llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -34,6 +34,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
 
@@ -44,6 +45,10 @@
 STATISTIC(RISCVNumInstrsCompressed,
           "Number of RISC-V Compressed instructions emitted");
 
+namespace llvm {
+extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
+} // namespace llvm
+
 namespace {
 class RISCVAsmPrinter : public AsmPrinter {
   const RISCVSubtarget *STI;
@@ -82,6 +87,8 @@
   void emitEndOfAsmFile(Module &M) override;
 
   void emitFunctionEntryLabel() override;
+  void emitDirectiveOptionArch();
+  bool isSameAttribute();
 
 private:
   void emitAttributes();
@@ -232,11 +239,44 @@
   return false;
 }
 
+void RISCVAsmPrinter::emitDirectiveOptionArch() {
+  RISCVTargetStreamer &RTS =
+      static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
+  std::vector<StringRef> NeedEmitStdOption;
+  const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
+  for (auto Feature : RISCVFeatureKV) {
+    if (STI->hasFeature(Feature.Value) && !MCSTI.hasFeature(Feature.Value) &&
+        llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
+      NeedEmitStdOption.push_back(Feature.Key);
+  }
+
+  bool PrefixEmitted = false;
+  unsigned NeedEmitStdOptionSize = NeedEmitStdOption.size();
+  for (unsigned i = 0; i < NeedEmitStdOptionSize; i++) {
+    RTS.emitDirectiveOptionArchPlus(NeedEmitStdOption[i], PrefixEmitted,
+                                    i < NeedEmitStdOptionSize - 1);
+  }
+}
+
+bool RISCVAsmPrinter::isSameAttribute() {
+  const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
+  return MCSTI.getFeatureBits() == STI->getFeatureBits();
+}
+
 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   STI = &MF.getSubtarget<RISCVSubtarget>();
+  RISCVTargetStreamer &RTS =
+      static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
+  if (!isSameAttribute()) {
+    RTS.emitDirectiveOptionPush();
+    emitDirectiveOptionArch();
+  }
 
   SetupMachineFunction(MF);
   emitFunctionBody();
+
+  if (!isSameAttribute())
+    RTS.emitDirectiveOptionPop();
   return false;
 }
 
Index: clang/test/CodeGen/RISCV/riscv-func-attr-target.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/RISCV/riscv-func-attr-target.c
@@ -0,0 +1,35 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang -target riscv64 -march=rv64g -S %s -o - | FileCheck %s
+
+// clang-format off
+// CHECK: .option push
+// CHECK-NEXT: .option        arch,   +c, +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-LABEL: test1
+// CHECK: .option pop
+__attribute__((target("arch=rv64g+c+v"))) void test1 () {}
+
+// CHECK: .option push
+// CHECK-NEXT: .option        arch,   +c
+// CHECK-LABEL: test2
+// CHECK: .option pop
+__attribute__((target("arch=rv64gc"))) void test2 () {}
+
+// CHECK: .option push
+// CHECK-NEXT: .option        arch,   +c
+// CHECK-LABEL: test3
+// CHECK: .option pop
+__attribute__((target("arch=+c"))) void test3 () {}
+
+// CHECK: .option push
+// CHECK-NEXT: .option        arch,   +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-LABEL: test4
+// CHECK: .option pop
+__attribute__((target("arch=+v"))) void test4 () {}
+
+// CHECK: .option push
+// CHECK-NEXT: .option        arch,   +experimental-zihintntl
+// CHECK-LABEL: test5
+// CHECK: .option pop
+__attribute__((target("arch=+experimental-zihintntl"))) void test5 () {}
+
+// clang-format on
Index: clang/lib/Basic/Targets/RISCV.h
===================================================================
--- clang/lib/Basic/Targets/RISCV.h
+++ clang/lib/Basic/Targets/RISCV.h
@@ -109,6 +109,8 @@
   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
   bool isValidTuneCPUName(StringRef Name) const override;
   void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
+  bool validateCpuSupports(StringRef FeatureStr) const override;
+  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
@@ -250,12 +250,17 @@
 
   // RISCVISAInfo makes implications for ISA features
   std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
+  std::vector<std::string> UpdatedFeatures;
+
   // Add non-ISA features like `relax` and `save-restore` back
   for (const std::string &Feature : FeaturesVec)
     if (!llvm::is_contained(ImpliedFeatures, Feature))
-      ImpliedFeatures.push_back(Feature);
+      UpdatedFeatures.push_back(Feature);
+
+  for (const std::string &Feature : ImpliedFeatures)
+    UpdatedFeatures.push_back(Feature);
 
-  return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
+  return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeatures);
 }
 
 std::optional<std::pair<unsigned, unsigned>>
@@ -346,3 +351,78 @@
   bool Is64Bit = getTriple().isArch64Bit();
   llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
 }
+
+// Parse RISC-V Target attributes, which are a comma separated list of:
+//  "arch=<arch>" - parsed to features as per -march=..
+//  "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
+//  "tune=<cpu>" - TuneCPU set to <cpu>
+ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
+  ParsedTargetAttr Ret;
+  if (Features == "default")
+    return Ret;
+  SmallVector<StringRef, 1> AttrFeatures;
+  Features.split(AttrFeatures, ",");
+  bool FoundArch = false;
+
+  auto SplitAndAddFeatures = [](StringRef FeatString,
+                                std::vector<std::string> &Features) {
+    SmallVector<StringRef, 8> SplitFeatures;
+    FeatString.split(SplitFeatures, StringRef("+"), -1, false);
+    for (StringRef Feature : SplitFeatures) {
+      Features.push_back("+" + Feature.str());
+    }
+  };
+
+  for (auto &Feature : AttrFeatures) {
+    Feature = Feature.trim();
+    if (Feature.startswith("arch=")) {
+      if (FoundArch)
+        Ret.Duplicate = "arch=";
+      FoundArch = true;
+      std::pair<StringRef, StringRef> Split =
+          Feature.split("=").second.trim().split("+");
+
+      if (!Split.first.empty()) {
+        auto RII = llvm::RISCVISAInfo::parseArchString(
+            Split.first, /* EnableExperimentalExtension */ true);
+        if (!RII) {
+          std::string Buffer;
+          llvm::raw_string_ostream OutputErrMsg(Buffer);
+          handleAllErrors(RII.takeError(), [&](llvm::StringError &ErrMsg) {
+            OutputErrMsg << "invalid arch name '" << Split.first << "', "
+                        << ErrMsg.getMessage();
+          });        
+        }
+        std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
+        for (auto FeatString : FeatStrings)
+          Ret.Features.push_back(FeatString);
+      }
+
+      // Add any extra features, after the +
+      SplitAndAddFeatures(Split.second, Ret.Features);
+    } else if (Feature.startswith("cpu=")) {
+      if (!Ret.CPU.empty())
+        Ret.Duplicate = "cpu=";
+      else {
+        // Split the cpu string into "cpu=", "cortex-a710" and any remaining
+        // "+feat" features.
+        std::pair<StringRef, StringRef> Split =
+            Feature.split("=").second.trim().split("+");
+        Ret.CPU = Split.first;
+        SplitAndAddFeatures(Split.second, Ret.Features);
+      }
+    } else if (Feature.startswith("tune=")) {
+      if (!Ret.Tune.empty())
+        Ret.Duplicate = "tune=";
+      else
+        Ret.Tune = Feature.split("=").second.trim();
+    } else if (Feature.startswith("+")) {
+      SplitAndAddFeatures(Feature, Ret.Features);
+    }
+  }
+  return Ret;
+}
+
+bool RISCVTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+  return ISAInfo->isSupportedExtensionFeature(FeatureStr);
+}
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1397,7 +1397,8 @@
   /// 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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to