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

update


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/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,114 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang -target riscv64 -march=rv64g -S %s -o - | FileCheck %s --check-prefix=CHECK-ASM
+// RUN: %clang -target riscv64 -march=rv64g -emit-llvm -S %s -o - | FileCheck %s --check-prefix=CHECK-IR
+
+// clang-format off
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c, +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test1
+// CHECK-ASM: .option pop
+__attribute__((target("arch=rv64g,+c,+v"))) void test1 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c
+// CHECK-ASM-LABEL: test2
+// CHECK-ASM: .option pop
+__attribute__((target("arch=rv64gc"))) void test2 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c
+// CHECK-ASM-LABEL: test3
+// CHECK-ASM: .option pop
+__attribute__((target("arch=+c"))) void test3 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test4
+// CHECK-ASM: .option pop
+__attribute__((target("arch=+v"))) void test4 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +experimental-zihintntl
+// CHECK-ASM-LABEL: test5
+// CHECK-ASM: .option pop
+__attribute__((target("arch=+experimental-zihintntl"))) void test5 () {}
+
+// CHECK-ASM-LABEL: test7
+// CHECK-ASM-NOT: .option pop
+// CHECK-IR: void @test7() #4 
+__attribute__((target("cpu=rocket-rv64"))) void test7 () {}
+
+// CHECK-ASM-LABEL: test8
+// CHECK-ASM-NOT: .option pop
+// CHECK-IR: void @test8() #5
+__attribute__((target("tune=rocket-rv64"))) void test8 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c
+// CHECK-ASM-LABEL: test9
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test9() #6
+__attribute__((target("cpu=rocket-rv64,arch=+c"))) void test9 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c, +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test10
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test10() #7
+__attribute__((target("cpu=rocket-rv64,arch=rv64gc,+v"))) void test10 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c, +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test11
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test11() #8
+__attribute__((target("tune=rocket-rv64,arch=rv64gc,+v"))) void test11 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test12
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test12() #9
+__attribute__((target("cpu=rocket-rv64,tune=generic-rv64,arch=+v"))) void test12 () {}
+
+// CHECK-ASM-LABEL: test13
+// CHECK-ASM-NOT: .option pop
+// CHECK-IR: void @test13() #10
+__attribute__((target("cpu=rocket-rv64,tune=generic-rv64"))) void test13 () {}
+
+// CHECK-ASM-LABEL: test14
+// CHECK-ASM-NOT: .option pop
+// CHECK-IR: void @test14() #10
+__attribute__((target("tune=generic-rv64,cpu=rocket-rv64"))) void test14 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test15
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test15() #9
+__attribute__((target("arch=+v,tune=generic-rv64,cpu=rocket-rv64"))) void test15 () {}
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b
+// CHECK-ASM-LABEL: test16
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test16() #9
+__attribute__((target("tune=generic-rv64,arch=+v,cpu=rocket-rv64"))) void test16 () {}
+
+
+// CHECK-ASM: .option push
+// CHECK-ASM-NEXT: .option        arch,   +c
+// CHECK-ASM-LABEL: test17
+// CHECK-ASM: .option pop
+// CHECK-IR: void @test17() #11
+__attribute__((target("tune=rocket-rv64,arch=rv64gcv,-v"))) void test17 () {}
+
+// CHECK-IR: attributes #5 {{.*}} "tune-cpu"="rocket-rv64" {{.*}}
+// CHECK-IR: attributes #6 {{.*}} "target-cpu"="rocket-rv64" {{.*}}
+// CHECK-IR: attributes #7 {{.*}} "target-cpu"="rocket-rv64" {{.*}}
+// CHECK-IR: attributes #8 {{.*}} "tune-cpu"="rocket-rv64" {{.*}}
+// CHECK-IR: attributes #9 {{.*}} "target-cpu"="rocket-rv64" {{.*}} "tune-cpu"="generic-rv64" {{.*}}
+// CHECK-IR: attributes #10 {{.*}} "target-cpu"="rocket-rv64" {{.*}} "tune-cpu"="generic-rv64" {{.*}}
+// CHECK-IR: attributes #11 {{.*}} "tune-cpu"="rocket-rv64" {{.*}}
+
+// 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,9 @@
   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; }
+  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,73 @@
   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;
+
+  for (auto &Feature : AttrFeatures) {
+    Feature = Feature.trim();
+    StringRef Attrstring = Feature.split("=").second.trim();
+
+    if (Feature.startswith("arch=")) {
+      if (FoundArch)
+        Ret.Duplicate = "arch=";
+      FoundArch = true;
+
+      // EXTENSION like arch=+v
+      if (Attrstring.startswith("+") || Attrstring.startswith("-"))
+        Ret.Features.push_back(Attrstring.str());
+      else {
+        // full-arch-string like arch=rv64gcv
+        auto RII = llvm::RISCVISAInfo::parseArchString(
+            Attrstring, /* EnableExperimentalExtension */ true);
+        if (!RII) {
+          std::string Buffer;
+          llvm::raw_string_ostream OutputErrMsg(Buffer);
+          handleAllErrors(RII.takeError(), [&](llvm::StringError &ErrMsg) {
+            OutputErrMsg << "invalid arch name '" << Attrstring << "', "
+                         << ErrMsg.getMessage();
+          });
+        }
+
+        std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
+        for (auto FeatString : FeatStrings)
+          Ret.Features.push_back(FeatString);
+      }
+      continue;
+    }
+
+    if (Feature.startswith("cpu=")) {
+      if (!Ret.CPU.empty())
+        Ret.Duplicate = "cpu=";
+      else
+        Ret.CPU = Attrstring;
+      continue;
+    }
+
+    if (Feature.startswith("tune=")) {
+      if (!Ret.Tune.empty())
+        Ret.Duplicate = "tune=";
+      else
+        Ret.Tune = Attrstring;
+      continue;
+    }
+
+    if (Feature.startswith("+") || Feature.startswith("-"))
+      Ret.Features.push_back(Feature.str());
+  }
+  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