[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