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