Skip to content

Commit 174247d

Browse files
authored
Merge pull request #1302 from AntoinePrv/sve-rvv-vl
Check SVE and RVV vector length
2 parents 2293695 + 37dfb7c commit 174247d

File tree

4 files changed

+108
-8
lines changed

4 files changed

+108
-8
lines changed

include/xsimd/config/xsimd_cpu_features_arm.hpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#ifndef XSIMD_CPU_FEATURES_ARM_HPP
1313
#define XSIMD_CPU_FEATURES_ARM_HPP
1414

15+
#include <cstddef>
16+
#include <cstdint>
17+
1518
#include "./xsimd_config.hpp"
1619
#include "./xsimd_getauxval.hpp"
1720

@@ -24,6 +27,24 @@
2427

2528
namespace xsimd
2629
{
30+
31+
namespace detail
32+
{
33+
using arm_reg64_t = std::uint64_t;
34+
35+
/**
36+
* Return the SVE vector length in bytes for the current thread.
37+
*
38+
* SVE vector length can be restricted
39+
* Contrary to `svcntb` this does not require to be compiles with SVE, which
40+
* should not be done in a dynamic dispatch jump function.
41+
*
42+
* Safety: It is the user responsibility to first make sure that SVE is
43+
* available.
44+
*/
45+
inline arm_reg64_t arm_rdvl_unsafe();
46+
}
47+
2748
/**
2849
* An opinionated CPU feature detection utility for ARM.
2950
*
@@ -40,13 +61,28 @@ namespace xsimd
4061
inline bool neon() const noexcept;
4162
inline bool neon64() const noexcept;
4263
inline bool sve() const noexcept;
64+
inline std::size_t sve_size_bytes() const noexcept;
4365
inline bool i8mm() const noexcept;
4466
};
4567

4668
/********************
4769
* Implementation *
4870
********************/
4971

72+
namespace detail
73+
{
74+
#if XSIMD_TARGET_ARM64 && (defined(__GNUC__) || defined(__clang__))
75+
__attribute__((target("arch=armv8-a+sve"))) inline arm_reg64_t arm_rdvl_unsafe()
76+
{
77+
arm_reg64_t vl;
78+
__asm__ volatile("rdvl %0, #1" : "=r"(vl));
79+
return vl;
80+
}
81+
#else
82+
inline arm_reg64_t arm_rdvl_unsafe() { return 0; }
83+
#endif
84+
}
85+
5086
inline bool arm_cpu_features::neon() const noexcept
5187
{
5288
#if XSIMD_TARGET_ARM && !XSIMD_TARGET_ARM64 && XSIMD_HAVE_LINUX_GETAUXVAL
@@ -70,6 +106,15 @@ namespace xsimd
70106
#endif
71107
}
72108

109+
inline std::size_t arm_cpu_features::sve_size_bytes() const noexcept
110+
{
111+
if (sve())
112+
{
113+
return detail::arm_rdvl_unsafe();
114+
}
115+
return 0;
116+
}
117+
73118
inline bool arm_cpu_features::i8mm() const noexcept
74119
{
75120
#if XSIMD_TARGET_ARM64 && XSIMD_HAVE_LINUX_GETAUXVAL

include/xsimd/config/xsimd_cpu_features_riscv.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#ifndef XSIMD_CPU_FEATURES_RISCV_HPP
1313
#define XSIMD_CPU_FEATURES_RISCV_HPP
1414

15+
#include <cstddef>
16+
#include <cstdint>
17+
1518
#include "./xsimd_config.hpp"
1619
#include "./xsimd_getauxval.hpp"
1720

@@ -24,16 +27,47 @@
2427

2528
namespace xsimd
2629
{
30+
namespace detail
31+
{
32+
using riscv_reg64_t = std::uint64_t;
33+
34+
/**
35+
* Return the RVV vector length in bytes.
36+
*
37+
* This does not require to be compiles with SVE, which should not
38+
* be done in a dynamic dispatch jump function.
39+
*
40+
* Safety: It is the user responsibility to first make sure that RVV is
41+
* available.
42+
*/
43+
inline riscv_reg64_t riscv_csrr_unsafe();
44+
}
45+
2746
class riscv_cpu_features : private linux_hwcap_backend_default
2847
{
2948
public:
3049
inline bool rvv() const noexcept;
50+
inline std::size_t rvv_size_bytes() const noexcept;
3151
};
3252

3353
/********************
3454
* Implementation *
3555
********************/
3656

57+
namespace detail
58+
{
59+
#if XSIMD_TARGET_RISCV && (defined(__GNUC__) || defined(__clang__))
60+
__attribute__((target("arch=+v"))) inline riscv_reg64_t riscv_csrr_unsafe()
61+
{
62+
riscv_reg64_t vlenb;
63+
__asm__ volatile("csrr %0, vlenb" : "=r"(vlenb));
64+
return vlenb;
65+
}
66+
#else
67+
inline riscv_reg64_t riscv_csrr_unsafe() { return 0; }
68+
#endif
69+
}
70+
3771
inline bool riscv_cpu_features::rvv() const noexcept
3872
{
3973
#if XSIMD_TARGET_RISCV && XSIMD_HAVE_LINUX_GETAUXVAL
@@ -47,6 +81,15 @@ namespace xsimd
4781
return false;
4882
#endif
4983
}
84+
85+
inline std::size_t riscv_cpu_features::rvv_size_bytes() const noexcept
86+
{
87+
if (rvv())
88+
{
89+
return detail::riscv_csrr_unsafe();
90+
}
91+
return 0;
92+
}
5093
}
5194

5295
#endif

include/xsimd/config/xsimd_cpuid.hpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ namespace xsimd
6363
ARCH_FIELD(neon)
6464
ARCH_FIELD(neon64)
6565
ARCH_FIELD_EX(i8mm<::xsimd::neon64>, i8mm_neon64)
66-
ARCH_FIELD_EX(detail::sve<512>, sve)
67-
ARCH_FIELD_EX_REUSE(detail::sve<256>, sve)
68-
ARCH_FIELD_EX_REUSE(detail::sve<128>, sve)
69-
ARCH_FIELD_EX(detail::rvv<512>, rvv)
70-
ARCH_FIELD_EX_REUSE(detail::rvv<256>, rvv)
71-
ARCH_FIELD_EX_REUSE(detail::rvv<128>, rvv)
66+
ARCH_FIELD_EX(detail::sve<512>, sve512)
67+
ARCH_FIELD_EX(detail::sve<256>, sve256)
68+
ARCH_FIELD_EX(detail::sve<128>, sve128)
69+
ARCH_FIELD_EX(detail::rvv<512>, rvv512)
70+
ARCH_FIELD_EX(detail::rvv<256>, rvv256)
71+
ARCH_FIELD_EX(detail::rvv<128>, rvv128)
7272
ARCH_FIELD(wasm)
7373
ARCH_FIELD(vsx)
7474

@@ -87,15 +87,19 @@ namespace xsimd
8787
// Safe on all platforms, it will be all false if non risc-v.
8888
const auto riscv_cpu = xsimd::riscv_cpu_features();
8989

90-
rvv = riscv_cpu.rvv();
90+
rvv128 = riscv_cpu.rvv() && (riscv_cpu.rvv_size_bytes() >= (128 / 8));
91+
rvv256 = riscv_cpu.rvv() && (riscv_cpu.rvv_size_bytes() >= (256 / 8));
92+
rvv512 = riscv_cpu.rvv() && (riscv_cpu.rvv_size_bytes() >= (512 / 8));
9193

9294
// Safe on all platforms, it will be all false if non arm.
9395
const auto arm_cpu = xsimd::arm_cpu_features();
9496

9597
neon = arm_cpu.neon();
9698
neon64 = arm_cpu.neon64();
9799
i8mm_neon64 = arm_cpu.neon64() && arm_cpu.i8mm();
98-
sve = arm_cpu.sve();
100+
sve128 = arm_cpu.sve() && (arm_cpu.sve_size_bytes() >= (128 / 8));
101+
sve256 = arm_cpu.sve() && (arm_cpu.sve_size_bytes() >= (256 / 8));
102+
sve512 = arm_cpu.sve() && (arm_cpu.sve_size_bytes() >= (512 / 8));
99103

100104
// Safe on all platforms, it will be all false if non x86.
101105
const auto x86_cpu = xsimd::x86_cpu_features();

test/test_cpu_features.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ TEST_CASE("[cpu_features] arm implication chains")
142142

143143
CHECK_IMPLICATION(cpu.neon64(), cpu.neon());
144144
CHECK_IMPLICATION(cpu.sve(), cpu.neon64());
145+
CHECK_IMPLICATION(cpu.sve(), cpu.sve_size_bytes() >= (128 / 8));
145146
CHECK_IMPLICATION(cpu.i8mm(), cpu.neon64());
146147
}
147148

@@ -155,6 +156,13 @@ TEST_CASE("[cpu_features] arm features from environment")
155156
CHECK_ENV_FEATURE("XSIMD_TEST_CPU_ASSUME_I8MM", cpu.i8mm());
156157
}
157158

159+
TEST_CASE("[cpu_features] risc-v implication chains")
160+
{
161+
xsimd::riscv_cpu_features cpu;
162+
163+
CHECK_IMPLICATION(cpu.rvv(), cpu.rvv_size_bytes() >= (128 / 8));
164+
}
165+
158166
TEST_CASE("[cpu_features] risc-v features from environment")
159167
{
160168
xsimd::riscv_cpu_features cpu;

0 commit comments

Comments
 (0)