Skip to content

Commit db88312

Browse files
committed
Add arm_cpu_features
1 parent 53c5fd5 commit db88312

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/***************************************************************************
2+
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3+
* Martin Renou *
4+
* Copyright (c) QuantStack *
5+
* Copyright (c) Serge Guelton *
6+
* *
7+
* Distributed under the terms of the BSD 3-Clause License. *
8+
* *
9+
* The full license is in the file LICENSE, distributed with this software. *
10+
***************************************************************************/
11+
12+
#ifndef XSIMD_CPU_FEATURES_ARM_HPP
13+
#define XSIMD_CPU_FEATURES_ARM_HPP
14+
15+
16+
#include "./xsimd_config.hpp"
17+
18+
#if XSIMD_WITH_LINUX_GETAUXVAL
19+
#include "./xsimd_getauxval.hpp"
20+
#endif
21+
22+
namespace xsimd
23+
{
24+
/**
25+
* An opinionated CPU feature detection utility for ARM.
26+
*
27+
* Combines compile-time knowledge with runtime detection when available.
28+
* On Linux, runtime detection uses getauxval to query the auxiliary vector.
29+
* On other platforms, only compile-time information is used.
30+
*
31+
* This is well defined on all architectures. It will always return false on
32+
* non-ARM architectures.
33+
*/
34+
class arm_cpu_features
35+
{
36+
public:
37+
arm_cpu_features() noexcept = default;
38+
39+
inline bool neon() const noexcept
40+
{
41+
#if XSIMD_TARGET_ARM && !XSIMD_TARGET_ARM64 && XSIMD_WITH_LINUX_GETAUXVAL
42+
return get_hwcap().all_bits_set<linux_hwcap_traits::aux::neon>();
43+
#else
44+
return static_cast<bool>(XSIMD_WITH_NEON);
45+
#endif
46+
}
47+
48+
constexpr bool neon64() const noexcept
49+
{
50+
return static_cast<bool>(XSIMD_WITH_NEON64);
51+
}
52+
53+
inline bool sve() const noexcept
54+
{
55+
#if XSIMD_TARGET_ARM64 && XSIMD_WITH_LINUX_GETAUXVAL
56+
return get_hwcap().all_bits_set<linux_hwcap_traits::aux::sve>();
57+
#else
58+
return false;
59+
#endif
60+
}
61+
62+
inline bool i8mm() const noexcept
63+
{
64+
#if XSIMD_TARGET_ARM64 && XSIMD_WITH_LINUX_GETAUXVAL
65+
return get_hwcap2().all_bits_set<linux_hwcap2_traits::aux::i8mm>();
66+
#else
67+
return false;
68+
#endif
69+
}
70+
71+
private:
72+
#if XSIMD_TARGET_ARM && XSIMD_WITH_LINUX_GETAUXVAL
73+
enum class status
74+
{
75+
hwcap_valid = 0,
76+
hwcap2_valid = 1,
77+
};
78+
79+
using status_bitset = utils::uint_bitset<status, std::uint32_t>;
80+
81+
mutable status_bitset m_status {};
82+
83+
mutable xsimd::linux_hwcap m_hwcap {};
84+
85+
inline xsimd::linux_hwcap const& get_hwcap() const noexcept
86+
{
87+
if (!m_status.bit_is_set<status::hwcap_valid>())
88+
{
89+
m_hwcap = xsimd::linux_hwcap::read();
90+
m_status.set_bit<status::hwcap_valid>();
91+
}
92+
return m_hwcap;
93+
}
94+
95+
#if XSIMD_TARGET_ARM64
96+
mutable xsimd::linux_hwcap2 m_hwcap2 {};
97+
inline xsimd::linux_hwcap2 const& get_hwcap2() const noexcept
98+
{
99+
if (!m_status.bit_is_set<status::hwcap2_valid>())
100+
{
101+
m_hwcap2 = xsimd::linux_hwcap2::read();
102+
m_status.set_bit<status::hwcap2_valid>();
103+
}
104+
return m_hwcap2;
105+
}
106+
#endif
107+
#endif // XSIMD_TARGET_ARM && XSIMD_WITH_LINUX_GETAUXVAL
108+
};
109+
}
110+
#endif

0 commit comments

Comments
 (0)