llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Brandon Wu (4vtomat)

<details>
<summary>Changes</summary>

Normally intrinsic support is decoupled from assembler support which
means we cant simply use arch string to check if intrinsics are
supported. This patch defines macros "__riscv_v_intrinsic_{EXTENSION}}
to check whether the intrinsics of EXTENSION is supported by this compiler.


---
Full diff: https://github.com/llvm/llvm-project/pull/187197.diff


4 Files Affected:

- (modified) clang/lib/Basic/Targets/RISCV.cpp (+46) 
- (added) clang/test/Preprocessor/riscv-vector-intrinsic-exts.c (+63) 
- (modified) clang/utils/TableGen/RISCVVEmitter.cpp (+16-3) 
- (modified) llvm/docs/RISCVUsage.rst (+23) 


``````````diff
diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index 685925b0773dc..a46eb87d88b94 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -22,6 +22,16 @@
 using namespace clang;
 using namespace clang::targets;
 
+namespace {
+static constexpr StringRef UniqueExtensions[] = {
+#define DECL_REQUIRED_EXTENSIONS
+#include "clang/Basic/riscv_andes_vector_builtins.inc"
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#include "clang/Basic/riscv_vector_builtins.inc"
+#undef DECL_REQUIRED_EXTENSIONS
+};
+} // namespace
+
 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
   // clang-format off
   static const char *const GCCRegNames[] = {
@@ -225,6 +235,42 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions 
&Opts,
   // Currently we support the v1.0 RISC-V V intrinsics.
   Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));
 
+  // These macros indicate which extensions have intrinsics supported by the
+  // toolchain, regardless of whether they are currently enabled.
+  for (llvm::StringRef Ext : UniqueExtensions) {
+    if (Ext == "64bit")
+      continue;
+    Builder.defineMacro("__riscv_v_intrinsic_" + Twine(Ext));
+  }
+
+  // Define macros for intrinsics that are not explicitly listed in
+  // RequiredFeatures in td files.
+  const char *ImplicitList[] = {"v",      "zve32x", "zve32f",
+                                "zve64x", "zve64f", "zve64d"};
+  for (const auto *Ext : ImplicitList)
+    Builder.defineMacro(Twine("__riscv_v_intrinsic_") + Ext);
+
+  // Define macros for shorthand extensions when all of intrinsics of its
+  // extensions are presented.
+  auto DefineSuperExt = [&](const char *Name, ArrayRef<const char *> Required) 
{
+    assert(Required.size() > 0);
+    std::string Condition =
+        std::string("#if defined(__riscv_v_intrinsic_") + Required[0] + ")";
+    for (size_t i = 1; i < Required.size(); ++i)
+      Condition +=
+          std::string(" && defined(__riscv_v_intrinsic_") + Required[i] + ")";
+    Builder.append(Condition);
+    Builder.defineMacro(Twine("__riscv_v_intrinsic_") + Name);
+    Builder.append("#endif");
+  };
+
+  DefineSuperExt("zvkn", {"zvkned", "zvknhb", "zvkb"});
+  DefineSuperExt("zvknc", {"zvkn", "zvbc"});
+  DefineSuperExt("zvkng", {"zvkn", "zvkg"});
+  DefineSuperExt("zvks", {"zvksed", "zvksh", "zvkb"});
+  DefineSuperExt("zvksc", {"zvks", "zvbc"});
+  DefineSuperExt("zvksg", {"zvks", "zvkg"});
+
   auto VScale = getVScaleRange(Opts, ArmStreamingKind::NotStreaming);
   if (VScale && VScale->first && VScale->first == VScale->second)
     Builder.defineMacro("__riscv_v_fixed_vlen",
diff --git a/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c 
b/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c
new file mode 100644
index 0000000000000..77e9293aec502
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c
@@ -0,0 +1,63 @@
+// RUN: %clang --target=riscv32-unknown-linux-gnu \
+// RUN:   -march=rv32iv -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ALL-INTRINSICS %s
+// RUN: %clang --target=riscv64-unknown-linux-gnu \
+// RUN:   -march=rv64iv -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ALL-INTRINSICS %s
+
+// Base vector intrinsics
+// CHECK-ALL-INTRINSICS: __riscv_v_intrinsic_v 1
+
+// Andes vendor extensions
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xandesvbfhcvt 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xandesvdot 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xandesvpackfph 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xandesvsintload 1
+
+// SiFive vendor extensions
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmm32a16f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmm32a32f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmm32a8f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmm32a8i 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmm64a64f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfmmbase 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvcp 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfbfexp16e 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfexp16e 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfexp32e 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfexpa 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfexpa64e 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfnrclipxfqf 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvfwmaccqqq 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvqmaccdod 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_xsfvqmaccqoq 1
+
+// Standard vector extensions
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvabd 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvbb 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvbc 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvdot4a8i 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zve32f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zve32x 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zve64d 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zve64f 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zve64x 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfbfa 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfbfmin 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfbfwma 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfh 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfhmin 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvfofp8min 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvkb 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvkg 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvkn 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvknc 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvkned 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvkng 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvknha 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvknhb 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvks 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvksc 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvksed 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvksg 1
+// CHECK-ALL-INTRINSICS-NEXT: __riscv_v_intrinsic_zvksh 1
diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp 
b/clang/utils/TableGen/RISCVVEmitter.cpp
index 970132d85d5b6..4810e9838e6e9 100644
--- a/clang/utils/TableGen/RISCVVEmitter.cpp
+++ b/clang/utils/TableGen/RISCVVEmitter.cpp
@@ -118,7 +118,8 @@ class RVVEmitter {
 private:
   /// Create all intrinsics and add them to \p Out and SemaRecords.
   void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
-                           std::vector<SemaRecord> *SemaRecords = nullptr);
+                           std::vector<SemaRecord> *SemaRecords = nullptr,
+                           std::set<StringRef> *UniqueExtensions = nullptr);
   /// Create all intrinsic records and SemaSignatureTable from SemaRecords.
   void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
                                  SemaSignatureTable &SST,
@@ -504,7 +505,8 @@ void RVVEmitter::createHeader(raw_ostream &OS) {
 
 void RVVEmitter::createBuiltins(raw_ostream &OS) {
   std::vector<std::unique_ptr<RVVIntrinsic>> Defs;
-  createRVVIntrinsics(Defs);
+  std::set<StringRef> UniqueExtensions;
+  createRVVIntrinsics(Defs, nullptr, &UniqueExtensions);
 
   llvm::StringToOffsetTable Table;
   // Ensure offset zero is the empty string.
@@ -568,6 +570,12 @@ void RVVEmitter::createBuiltins(raw_ostream &OS) {
     OS << "HeaderDesc::NO_HEADER, ALL_LANGUAGES},\n";
   }
   OS << "#endif // GET_RISCVV_BUILTIN_INFOS\n\n";
+
+  // Collect all unique required extensions for vector intrinsics
+  OS << "#ifdef DECL_REQUIRED_EXTENSIONS\n";
+  for (const auto &UE : UniqueExtensions)
+    OS << "  \"" << UE << "\",\n";
+  OS << "#endif // DECL_REQUIRED_EXTENSIONS\n\n";
 }
 
 void RVVEmitter::createCodeGen(raw_ostream &OS) {
@@ -626,7 +634,8 @@ void RVVEmitter::createCodeGen(raw_ostream &OS) {
 
 void RVVEmitter::createRVVIntrinsics(
     std::vector<std::unique_ptr<RVVIntrinsic>> &Out,
-    std::vector<SemaRecord> *SemaRecords) {
+    std::vector<SemaRecord> *SemaRecords,
+    std::set<StringRef> *UniqueExtensions) {
   for (const Record *R : Records.getAllDerivedDefinitions("RVVBuiltin")) {
     StringRef Name = R->getValueAsString("Name");
     StringRef SuffixProto = R->getValueAsString("Suffix");
@@ -676,6 +685,10 @@ void RVVEmitter::createRVVIntrinsics(
     SmallVector<PrototypeDescriptor> OverloadedSuffixDesc =
         parsePrototypes(OverloadedSuffixProto);
 
+    if (UniqueExtensions)
+      UniqueExtensions->insert(RequiredFeatures.begin(),
+                               RequiredFeatures.end());
+
     // Compute Builtin types
     auto Prototype = RVVIntrinsic::computeBuiltinTypes(
         BasicPrototype, /*IsMasked=*/false,
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index d1befbd645900..165c1f081b39d 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -578,6 +578,29 @@ line.  This currently applies to the following extensions:
 
 No extensions have experimental intrinsics.
 
+Vector Intrinsic Detection Macros
+==================================
+
+Clang defines preprocessor macros ``__riscv_v_intrinsic_<extension>`` to 
indicate
+toolchain support for RISC-V vector intrinsics. These macros are defined for 
all
+vector extensions that have intrinsics, allowing code to detect whether the 
compiler
+supports intrinsics for a specific extension.
+
+Note: These macros are defined unconditionally because it's intended to show 
capabilities
+of this compiler instead of showing whether extension is enabled.
+
+Example usage:
+
+.. code-block:: c
+
+    #if defined(__riscv_v_intrinsic_zvbb)
+    // Compiler supports Zvbb intrinsics - can use them
+    #include <riscv_vector.h>
+    void use_zvbb_intrinsics() {
+      // Use Zvbb intrinsics here
+    }
+    #endif
+
 Long (>32-bit) Instruction Support
 ==================================
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/187197
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to