[clang] 5a91032 - [clang][RISCV] Use macro to check if intrinsics are supported (#187197)

via cfe-commits cfe-commits at lists.llvm.org
Sun May 3 23:09:50 PDT 2026


Author: Brandon Wu
Date: 2026-05-04T14:09:45+08:00
New Revision: 5a9103274ca08cbf40acb023d05e5e18f2902312

URL: https://github.com/llvm/llvm-project/commit/5a9103274ca08cbf40acb023d05e5e18f2902312
DIFF: https://github.com/llvm/llvm-project/commit/5a9103274ca08cbf40acb023d05e5e18f2902312.diff

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

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_intrinsic\_{EXTENSION}
to check whether the intrinsics of EXTENSION is supported by this
compiler.

c-api-doc PR: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/183

Added: 
    clang/docs/RISCVSupport.rst
    clang/test/Preprocessor/riscv-intrinsic-exts.c

Modified: 
    clang/docs/index.rst
    clang/lib/Headers/andes_vector.h
    clang/lib/Headers/riscv_bitmanip.h
    clang/lib/Headers/riscv_corev_alu.h
    clang/lib/Headers/riscv_crypto.h
    clang/lib/Headers/riscv_mips.h
    clang/lib/Headers/riscv_nds.h
    clang/lib/Headers/riscv_ntlh.h
    clang/lib/Headers/sifive_vector.h
    clang/utils/TableGen/RISCVVEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/RISCVSupport.rst b/clang/docs/RISCVSupport.rst
new file mode 100644
index 0000000000000..7d49c445756b6
--- /dev/null
+++ b/clang/docs/RISCVSupport.rst
@@ -0,0 +1,34 @@
+==============
+RISC-V Support
+==============
+
+.. contents::
+   :local:
+
+Intrinsic Detection Macros
+===========================
+
+Clang provides macros to detect which RISC-V intrinsics are supported by the
+toolchain. This is only available if intrinsics are ratified, in other word,
+experimental intrinsics do not have macro defined.
+Note: This is independent from assembler support.
+
+Intrinsic Detection
+---------------------------
+
+Macros of the form ``__riscv_intrinsic_<extension>`` indicate that the toolchain
+supports intrinsics for a given extension:
+
+.. code-block:: c
+
+  #if defined(__riscv_intrinsic_zbb)
+    // Toolchain supports Zbb scalar intrinsics like __riscv_orc_b_*
+    // These can be used with target attributes even if -march doesn't include Zbb
+    __attribute__((target("arch=+zbb")))
+    unsigned long process_with_zbb(unsigned long x) {
+      return __riscv_orc_b_64(x);
+    }
+  #endif
+
+Composite extensions are also defined when all their sub-extensions are available, e.g.
+ ``__riscv_intrinsic_zkn`` - zbkb + zbkc + zbkx + zkne + zknd + zknh

diff  --git a/clang/docs/index.rst b/clang/docs/index.rst
index 898667e36011d..05bb7512fda92 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
    CIR/index
    CommandGuide/index

diff  --git a/clang/lib/Headers/andes_vector.h b/clang/lib/Headers/andes_vector.h
index dc717e6d805b9..968a922b6a21c 100644
--- a/clang/lib/Headers/andes_vector.h
+++ b/clang/lib/Headers/andes_vector.h
@@ -13,4 +13,9 @@
 
 #pragma clang riscv intrinsic andes_vector
 
+#define __riscv_intrinsic_xandesvbfhcvt 1
+#define __riscv_intrinsic_xandesvdot 1
+#define __riscv_intrinsic_xandesvpackfph 1
+#define __riscv_intrinsic_xandesvsintload 1
+
 #endif //_ANDES_VECTOR_H_

diff  --git a/clang/lib/Headers/riscv_bitmanip.h b/clang/lib/Headers/riscv_bitmanip.h
index 2bc7ee022a96b..e03e5cea6617f 100644
--- a/clang/lib/Headers/riscv_bitmanip.h
+++ b/clang/lib/Headers/riscv_bitmanip.h
@@ -16,6 +16,12 @@
 extern "C" {
 #endif
 
+#define __riscv_intrinsic_zbb 1
+#define __riscv_intrinsic_zbc 1
+#define __riscv_intrinsic_zbkb 1
+#define __riscv_intrinsic_zbkc 1
+#define __riscv_intrinsic_zbkx 1
+
 #if defined(__riscv_zbb)
 static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
 __riscv_orc_b_32(uint32_t __x) {

diff  --git a/clang/lib/Headers/riscv_corev_alu.h b/clang/lib/Headers/riscv_corev_alu.h
index 84f4d087e4863..d6fba94790aab 100644
--- a/clang/lib/Headers/riscv_corev_alu.h
+++ b/clang/lib/Headers/riscv_corev_alu.h
@@ -16,6 +16,8 @@
 extern "C" {
 #endif
 
+#define __riscv_intrinsic_xcvalu 1
+
 #if defined(__riscv_xcvalu)
 
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))

diff  --git a/clang/lib/Headers/riscv_crypto.h b/clang/lib/Headers/riscv_crypto.h
index 7cd2a708f5575..ea9f29c0dd31b 100644
--- a/clang/lib/Headers/riscv_crypto.h
+++ b/clang/lib/Headers/riscv_crypto.h
@@ -16,6 +16,14 @@
 extern "C" {
 #endif
 
+#define __riscv_intrinsic_zkn 1
+#define __riscv_intrinsic_zknd 1
+#define __riscv_intrinsic_zkne 1
+#define __riscv_intrinsic_zknh 1
+#define __riscv_intrinsic_zks 1
+#define __riscv_intrinsic_zksed 1
+#define __riscv_intrinsic_zksh 1
+
 #if defined(__riscv_zknd)
 #if __riscv_xlen == 32
 #define __riscv_aes32dsi(x, y, bs) __builtin_riscv_aes32dsi(x, y, bs)

diff  --git a/clang/lib/Headers/riscv_mips.h b/clang/lib/Headers/riscv_mips.h
index 124a989280ed4..afd390b174bf4 100644
--- a/clang/lib/Headers/riscv_mips.h
+++ b/clang/lib/Headers/riscv_mips.h
@@ -14,6 +14,8 @@
 #error "This header is only meant to be used on riscv architecture"
 #endif
 
+#define __riscv_intrinsic_xmipsexectl 1
+
 #define __DEFAULT_FN_ATTRS                                                     \
   __attribute__((__always_inline__, __nodebug__, __target__("xmipsexectl")))
 

diff  --git a/clang/lib/Headers/riscv_nds.h b/clang/lib/Headers/riscv_nds.h
index 29734c43834c7..c321e0b263380 100644
--- a/clang/lib/Headers/riscv_nds.h
+++ b/clang/lib/Headers/riscv_nds.h
@@ -16,6 +16,9 @@
 extern "C" {
 #endif
 
+#define __riscv_intrinsic_xandesbfhcvt 1
+#define __riscv_intrinsic_xandesperf 1
+
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
 
 #if defined(__riscv_xandesperf)

diff  --git a/clang/lib/Headers/riscv_ntlh.h b/clang/lib/Headers/riscv_ntlh.h
index c92e580a0a631..10540d95eb164 100644
--- a/clang/lib/Headers/riscv_ntlh.h
+++ b/clang/lib/Headers/riscv_ntlh.h
@@ -10,6 +10,8 @@
 #ifndef __RISCV_NTLH_H
 #define __RISCV_NTLH_H
 
+#define __riscv_intrinsic_zihintntl 1
+
 #ifndef __riscv_zihintntl
 #error "NTLH intrinsics require the NTLH extension."
 #endif

diff  --git a/clang/lib/Headers/sifive_vector.h b/clang/lib/Headers/sifive_vector.h
index d315eb9609821..6df1dae535041 100644
--- a/clang/lib/Headers/sifive_vector.h
+++ b/clang/lib/Headers/sifive_vector.h
@@ -13,6 +13,23 @@
 
 #pragma clang riscv intrinsic sifive_vector
 
+#define __riscv_intrinsic_xsfmm32a16f 1
+#define __riscv_intrinsic_xsfmm32a32f 1
+#define __riscv_intrinsic_xsfmm32a8f 1
+#define __riscv_intrinsic_xsfmm32a8i 1
+#define __riscv_intrinsic_xsfmm64a64f 1
+#define __riscv_intrinsic_xsfmmbase 1
+#define __riscv_intrinsic_xsfvcp 1
+#define __riscv_intrinsic_xsfvfbfexp16e 1
+#define __riscv_intrinsic_xsfvfexp16e 1
+#define __riscv_intrinsic_xsfvfexp32e 1
+#define __riscv_intrinsic_xsfvfexpa 1
+#define __riscv_intrinsic_xsfvfexpa64e 1
+#define __riscv_intrinsic_xsfvfnrclipxfqf 1
+#define __riscv_intrinsic_xsfvfwmaccqqq 1
+#define __riscv_intrinsic_xsfvqmaccdod 1
+#define __riscv_intrinsic_xsfvqmaccqoq 1
+
 #define __riscv_sf_vc_x_se_u8mf4(p27_26, p24_20, p11_7, rs1, vl)               \
   __riscv_sf_vc_x_se(p27_26, p24_20, p11_7, (uint8_t)rs1, 8, 6, vl)
 #define __riscv_sf_vc_x_se_u8mf2(p27_26, p24_20, p11_7, rs1, vl)               \

diff  --git a/clang/test/Preprocessor/riscv-intrinsic-exts.c b/clang/test/Preprocessor/riscv-intrinsic-exts.c
new file mode 100644
index 0000000000000..133b2c3600a1e
--- /dev/null
+++ b/clang/test/Preprocessor/riscv-intrinsic-exts.c
@@ -0,0 +1,85 @@
+// 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 -target-feature +zihintntl -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-INTRINSIC-EXTS %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zihintntl -E -dM %s -o - \
+// RUN:   | FileCheck --check-prefix=CHECK-INTRINSIC-EXTS %s
+
+#include <riscv_bitmanip.h>
+#include <riscv_corev_alu.h>
+#include <riscv_crypto.h>
+#include <riscv_mips.h>
+#include <riscv_nds.h>
+#include <riscv_ntlh.h>
+#include <riscv_vector.h>
+#include <andes_vector.h>
+#include <sifive_vector.h>
+
+// CHECK-INTRINSIC-EXTS: #define __riscv_intrinsic_v 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesbfhcvt 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesperf 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesvbfhcvt 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesvdot 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesvpackfph 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xandesvsintload 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xcvalu 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xmipsexectl 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmm32a16f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmm32a32f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmm32a8f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmm32a8i 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmm64a64f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfmmbase 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvcp 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfbfexp16e 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfexp16e 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfexp32e 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfexpa 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfexpa64e 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfnrclipxfqf 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvfwmaccqqq 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvqmaccdod 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_xsfvqmaccqoq 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zbb 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zbc 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zbkb 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zbkc 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zbkx 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zihintntl 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zkn 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zknd 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zkne 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zknh 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zks 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zksed 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zksh 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvabd 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvbb 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvbc 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvdot4a8i 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zve32f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zve32x 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zve64d 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zve64f 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zve64x 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfbfa 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfbfmin 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfbfwma 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfh 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfhmin 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvfofp8min 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvkb 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvkg 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvkn 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvknc 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvkned 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvkng 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvknha 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvknhb 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvks 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvksc 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvksed 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvksg 1
+// CHECK-INTRINSIC-EXTS-NEXT: #define __riscv_intrinsic_zvksh 1

diff  --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp
index f5b787ce5a06e..1b8ad7e556e8b 100644
--- a/clang/utils/TableGen/RISCVVEmitter.cpp
+++ b/clang/utils/TableGen/RISCVVEmitter.cpp
@@ -431,6 +431,17 @@ void RVVEmitter::createHeader(raw_ostream &OS) {
 
   OS << "#pragma clang riscv intrinsic vector\n\n";
 
+  // This array includes all extensions that have intrinsics implemented. We
+  // need to update the list when any new intrinsic are defined.
+  static const char *const Exts[] = {
+      "v",        "zvabd",  "zvbb",    "zvbc",       "zvdot4a8i", "zve32f",
+      "zve32x",   "zve64d", "zve64f",  "zve64x",     "zvfbfa",    "zvfbfmin",
+      "zvfbfwma", "zvfh",   "zvfhmin", "zvfofp8min", "zvkb",      "zvkg",
+      "zvkn",     "zvknc",  "zvkned",  "zvkng",      "zvknha",    "zvknhb",
+      "zvks",     "zvksc",  "zvksed",  "zvksg",      "zvksh"};
+  for (const char *Ext : Exts)
+    OS << "#define __riscv_intrinsic_" << Ext << " 1\n";
+
   printHeaderCode(OS);
 
   auto printType = [&](auto T) {


        


More information about the cfe-commits mailing list