[clang] [llvm] [clang][RISCV] Use macro to check if intrinsics are supported (PR #187197)

Brandon Wu via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 5 20:16:47 PDT 2026


https://github.com/4vtomat updated https://github.com/llvm/llvm-project/pull/187197

>From abec7a4d68cd56445c7e5221288394bc4d587e77 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Mon, 16 Mar 2026 23:48:35 -0700
Subject: [PATCH 1/3] [clang][RISCV] Use macro to check if intrinsics are
 supported

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.
---
 clang/lib/Basic/Targets/RISCV.cpp             | 46 ++++++++++++++
 .../riscv-vector-intrinsic-exts.c             | 63 +++++++++++++++++++
 clang/utils/TableGen/RISCVVEmitter.cpp        | 19 +++++-
 llvm/docs/RISCVUsage.rst                      | 23 +++++++
 4 files changed, 148 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Preprocessor/riscv-vector-intrinsic-exts.c

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
 ==================================
 

>From 617f95717ce406027b0df4d0a7405bcd162606ab Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Tue, 31 Mar 2026 02:34:55 -0700
Subject: [PATCH 2/3] fixup! support scalar

---
 clang/lib/Basic/Targets/RISCV.cpp             | 188 +++++++++++-------
 .../test/Preprocessor/riscv-intrinsic-exts.c  |  92 +++++++++
 .../riscv-vector-intrinsic-exts.c             |  63 ------
 3 files changed, 204 insertions(+), 139 deletions(-)
 create mode 100644 clang/test/Preprocessor/riscv-intrinsic-exts.c
 delete mode 100644 clang/test/Preprocessor/riscv-vector-intrinsic-exts.c

diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index a46eb87d88b94..f59859862191d 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -153,6 +153,92 @@ static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
   return MajorVersion * 1000000 + MinorVersion * 1000;
 }
 
+static constexpr int NumRVVBuiltins =
+    RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin;
+static constexpr int NumRVVSiFiveBuiltins =
+    RISCVVector::FirstAndesBuiltin - RISCVVector::FirstSiFiveBuiltin;
+static constexpr int NumRVVAndesBuiltins =
+    RISCVVector::FirstTSBuiltin - RISCVVector::FirstAndesBuiltin;
+static constexpr int NumRISCVBuiltins =
+    RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin;
+static constexpr int NumBuiltins =
+    RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin;
+static_assert(NumBuiltins == (NumRVVBuiltins + NumRVVSiFiveBuiltins +
+                              NumRVVAndesBuiltins + NumRISCVBuiltins));
+
+namespace RVV {
+#define GET_RISCVV_BUILTIN_STR_TABLE
+#include "clang/Basic/riscv_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_STR_TABLE
+static_assert(BuiltinStrings.size() < 100'000);
+
+static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = {
+#define GET_RISCVV_BUILTIN_INFOS
+#include "clang/Basic/riscv_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_INFOS
+};
+} // namespace RVV
+
+namespace RVVSiFive {
+#define GET_RISCVV_BUILTIN_STR_TABLE
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =
+    {
+#define GET_RISCVV_BUILTIN_INFOS
+#include "clang/Basic/riscv_sifive_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_INFOS
+};
+} // namespace RVVSiFive
+
+namespace RVVAndes {
+#define GET_RISCVV_BUILTIN_STR_TABLE
+#include "clang/Basic/riscv_andes_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_STR_TABLE
+
+static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins> BuiltinInfos =
+    {
+#define GET_RISCVV_BUILTIN_INFOS
+#include "clang/Basic/riscv_andes_vector_builtins.inc"
+#undef GET_RISCVV_BUILTIN_INFOS
+};
+} // namespace RVVAndes
+
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsRISCV.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
+#include "clang/Basic/BuiltinsRISCV.inc"
+#undef GET_BUILTIN_INFOS
+};
+static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);
+
+// Extract unique scalar extensions from RISC-V scalar builtins
+static llvm::SmallSet<std::string, 16> getUniqueScalarExtensions() {
+  llvm::SmallSet<std::string, 16> UniqueScalarExtensions;
+  for (const auto &Info : BuiltinInfos) {
+    StringRef Features = BuiltinStrings[Info.Offsets.Features];
+    if (Features.empty())
+      continue;
+
+    SmallVector<StringRef, 4> Parts;
+    Features.split(Parts, ',');
+    for (StringRef Part : Parts) {
+      SmallVector<StringRef, 2> OrParts;
+      Part.split(OrParts, '|');
+      for (StringRef Feature : OrParts) {
+        Feature = Feature.trim();
+        if (Feature != "32bit" && Feature != "64bit" && !Feature.empty())
+          UniqueScalarExtensions.insert(Feature.str());
+      }
+    }
+  }
+  return UniqueScalarExtensions;
+}
+
 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
                                        MacroBuilder &Builder) const {
   Builder.defineMacro("__riscv");
@@ -250,26 +336,39 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
   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);
+  // Define macros for scalar RISC-V extensions that have builtins.
+  // These indicate toolchain support for scalar intrinsics.
+  llvm::SmallSet<std::string, 16> UniqueScalarExtensions =
+      getUniqueScalarExtensions();
+  for (const auto &Ext : UniqueScalarExtensions)
+    Builder.defineMacro(Twine("__riscv_intrinsic_") + Ext);
+
+  // Helper to define composite extension macros when all required extensions
+  // are present. Works for both scalar and vector intrinsics.
+  auto DefineSuperExt = [&](StringRef Prefix, const char *Name,
+                            ArrayRef<const char *> Required) {
+    assert(!Required.empty());
     std::string Condition =
-        std::string("#if defined(__riscv_v_intrinsic_") + Required[0] + ")";
+        std::string("#if defined(") + Prefix.str() + Required[0] + ")";
     for (size_t i = 1; i < Required.size(); ++i)
       Condition +=
-          std::string(" && defined(__riscv_v_intrinsic_") + Required[i] + ")";
+          std::string(" && defined(") + Prefix.str() + Required[i] + ")";
     Builder.append(Condition);
-    Builder.defineMacro(Twine("__riscv_v_intrinsic_") + Name);
+    Builder.defineMacro(Twine(Prefix) + 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"});
+  // Vector crypto composite extensions
+  DefineSuperExt("__riscv_v_intrinsic_", "zvkn", {"zvkned", "zvknhb", "zvkb"});
+  DefineSuperExt("__riscv_v_intrinsic_", "zvknc", {"zvkn", "zvbc"});
+  DefineSuperExt("__riscv_v_intrinsic_", "zvkng", {"zvkn", "zvkg"});
+  DefineSuperExt("__riscv_v_intrinsic_", "zvks", {"zvksed", "zvksh", "zvkb"});
+  DefineSuperExt("__riscv_v_intrinsic_", "zvksc", {"zvks", "zvbc"});
+  DefineSuperExt("__riscv_v_intrinsic_", "zvksg", {"zvks", "zvkg"});
+
+  // Scalar crypto composite extensions
+  DefineSuperExt("__riscv_intrinsic_", "zkn", {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"});
+  DefineSuperExt("__riscv_intrinsic_", "zks", {"zbkb", "zbkc", "zbkx", "zksed", "zksh"});
 
   auto VScale = getVScaleRange(Opts, ArmStreamingKind::NotStreaming);
   if (VScale && VScale->first && VScale->first == VScale->second)
@@ -311,69 +410,6 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
   }
 }
 
-static constexpr int NumRVVBuiltins =
-    RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin;
-static constexpr int NumRVVSiFiveBuiltins =
-    RISCVVector::FirstAndesBuiltin - RISCVVector::FirstSiFiveBuiltin;
-static constexpr int NumRVVAndesBuiltins =
-    RISCVVector::FirstTSBuiltin - RISCVVector::FirstAndesBuiltin;
-static constexpr int NumRISCVBuiltins =
-    RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin;
-static constexpr int NumBuiltins =
-    RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin;
-static_assert(NumBuiltins == (NumRVVBuiltins + NumRVVSiFiveBuiltins +
-                              NumRVVAndesBuiltins + NumRISCVBuiltins));
-
-namespace RVV {
-#define GET_RISCVV_BUILTIN_STR_TABLE
-#include "clang/Basic/riscv_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_STR_TABLE
-static_assert(BuiltinStrings.size() < 100'000);
-
-static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = {
-#define GET_RISCVV_BUILTIN_INFOS
-#include "clang/Basic/riscv_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_INFOS
-};
-} // namespace RVV
-
-namespace RVVSiFive {
-#define GET_RISCVV_BUILTIN_STR_TABLE
-#include "clang/Basic/riscv_sifive_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_STR_TABLE
-
-static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =
-    {
-#define GET_RISCVV_BUILTIN_INFOS
-#include "clang/Basic/riscv_sifive_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_INFOS
-};
-} // namespace RVVSiFive
-
-namespace RVVAndes {
-#define GET_RISCVV_BUILTIN_STR_TABLE
-#include "clang/Basic/riscv_andes_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_STR_TABLE
-
-static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins> BuiltinInfos =
-    {
-#define GET_RISCVV_BUILTIN_INFOS
-#include "clang/Basic/riscv_andes_vector_builtins.inc"
-#undef GET_RISCVV_BUILTIN_INFOS
-};
-} // namespace RVVAndes
-
-#define GET_BUILTIN_STR_TABLE
-#include "clang/Basic/BuiltinsRISCV.inc"
-#undef GET_BUILTIN_STR_TABLE
-
-static constexpr Builtin::Info BuiltinInfos[] = {
-#define GET_BUILTIN_INFOS
-#include "clang/Basic/BuiltinsRISCV.inc"
-#undef GET_BUILTIN_INFOS
-};
-static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);
-
 llvm::SmallVector<Builtin::InfosShard>
 RISCVTargetInfo::getTargetBuiltins() const {
   return {
diff --git a/clang/test/Preprocessor/riscv-intrinsic-exts.c b/clang/test/Preprocessor/riscv-intrinsic-exts.c
new file mode 100644
index 0000000000000..bba8d005a2bef
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-intrinsic-exts.c
@@ -0,0 +1,92 @@
+// Tests for RISC-V intrinsic detection macros.
+// These macros indicate which extensions have intrinsics supported by the
+// toolchain, regardless of whether they are currently enabled via -march.
+
+// RUN: %clang_cc1 -triple riscv32 -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-SCALAR-EXTS %s
+// RUN: %clang_cc1 -triple riscv64 -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-SCALAR-EXTS %s
+
+// RUN: %clang --target=riscv32-unknown-linux-gnu \
+// RUN:   -march=rv32iv -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-VECTOR-EXTS %s
+// RUN: %clang --target=riscv64-unknown-linux-gnu \
+// RUN:   -march=rv64iv -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-VECTOR-EXTS %s
+
+// Scalar intrinsic extension macros (__riscv_intrinsic_*)
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zbb 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zbc 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zbkb 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zbkc 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zbkx 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zknd 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zkne 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zknh 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zksed 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zksh 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_xtheadbb 1
+
+// Scalar composite extensions (defined when all components are supported)
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zkn 1
+// CHECK-SCALAR-EXTS-DAG: #define __riscv_intrinsic_zks 1
+
+// Vector intrinsic extension macros (__riscv_v_intrinsic_*)
+
+// Base vector intrinsics
+// CHECK-VECTOR-EXTS: __riscv_v_intrinsic_v 1
+
+// Andes vendor extensions
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xandesvbfhcvt 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xandesvdot 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xandesvpackfph 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xandesvsintload 1
+
+// SiFive vendor extensions
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmm32a16f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmm32a32f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmm32a8f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmm32a8i 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmm64a64f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfmmbase 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvcp 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfbfexp16e 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfexp16e 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfexp32e 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfexpa 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfexpa64e 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfnrclipxfqf 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvfwmaccqqq 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvqmaccdod 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_xsfvqmaccqoq 1
+
+// Standard vector extensions
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvabd 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvbb 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvbc 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvdot4a8i 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zve32f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zve32x 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zve64d 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zve64f 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zve64x 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfbfa 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfbfmin 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfbfwma 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfh 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfhmin 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvfofp8min 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvkb 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvkg 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvkn 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvknc 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvkned 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvkng 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvknha 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvknhb 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvks 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvksc 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvksed 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvksg 1
+// CHECK-VECTOR-EXTS-NEXT: __riscv_v_intrinsic_zvksh 1
+
diff --git a/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c b/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c
deleted file mode 100644
index 77e9293aec502..0000000000000
--- a/clang/test/Preprocessor/riscv-vector-intrinsic-exts.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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

>From 490551f3ff4a1c1944eca0ce63f0649ec9f06e86 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Tue, 31 Mar 2026 09:36:04 -0700
Subject: [PATCH 3/3] fixup! RISCVSupport.rst

---
 clang/docs/RISCVSupport.rst | 44 +++++++++++++++++++++++++++++++++++++
 clang/docs/index.rst        |  1 +
 llvm/docs/RISCVUsage.rst    | 23 -------------------
 3 files changed, 45 insertions(+), 23 deletions(-)
 create mode 100644 clang/docs/RISCVSupport.rst

diff --git a/clang/docs/RISCVSupport.rst b/clang/docs/RISCVSupport.rst
new file mode 100644
index 0000000000000..ba11094edcd34
--- /dev/null
+++ b/clang/docs/RISCVSupport.rst
@@ -0,0 +1,44 @@
+==============
+RISC-V Support
+==============
+
+.. contents::
+   :local:
+
+Intrinsic Detection Macros
+===========================
+
+Clang provides macros to detect which RISC-V intrinsics are supported by the
+toolchain.
+Note: This is independent from assembler support.
+
+Scalar Intrinsic Detection
+---------------------------
+
+Macros of the form ``__riscv_intrinsic_<extension>`` indicate that the
+toolchain supports scalar built-in functions for a given extension:
+
+.. code-block:: c
+
+   #if defined(__riscv_intrinsic_zbb)
+     // Toolchain supports Zbb intrinsics like __builtin_riscv_orc_b_*
+     // These can be used with target attributes
+   #endif
+
+Composite extensions are also defined when all their sub-extensions are available, e.g.
+ ``__riscv_intrinsic_zkn`` - zbkb + zbkc + zbkx + zkne + zknd + zknh
+
+Vector Intrinsic Detection
+---------------------------
+
+Macros of the form ``__riscv_v_intrinsic_<extension>`` indicate that the
+toolchain supports vector intrinsics for a given extension:
+
+.. code-block:: c
+
+   #if defined(__riscv_v_intrinsic_zvbb)
+     // Toolchain supports vector bit manipulation intrinsics
+   #endif
+
+Composite vector crypto extensions are defined when all components are available, e.g.  
+ ``__riscv_v_intrinsic_zvkn`` - zvkned + zvknhb + zvkb
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 89ca6d73d9d8d..351c0ba947ecc 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -68,6 +68,7 @@ Using Clang as a Compiler
    APINotes
    DebuggingCoroutines
    AMDGPUSupport
+   RISCVSupport
    CXXTypeAwareAllocators
    CommandGuide/index
    FAQ
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 165c1f081b39d..d1befbd645900 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -578,29 +578,6 @@ 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
 ==================================
 



More information about the llvm-commits mailing list