-
Notifications
You must be signed in to change notification settings - Fork 409
/
Copy pathsimd.h
124 lines (112 loc) · 3.53 KB
/
simd.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#pragma once
#if defined(__aarch64__)
#if __has_include(<asm/hwcap.h>)
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif
#endif
namespace simd_option
{
#if defined(__x86_64__)
#ifdef TIFLASH_ENABLE_AVX_SUPPORT
extern bool ENABLE_AVX;
#endif
#ifdef TIFLASH_ENABLE_AVX512_SUPPORT
extern bool ENABLE_AVX512;
#endif
/// @attention: we keeps the SIMDFeature encoding consistent,
/// so even if the feature is not enabled, we still define an enum item for it
enum class SIMDFeature
{
avx,
avx2,
avx512f,
avx512dq,
avx512cd,
avx512bw,
avx512vl
};
static inline bool SIMDRuntimeSupport(SIMDFeature feature)
{
// Please Check:
// https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html
// GCC itself provides runtime feature checking builtins, but notice
// that GCC 7 does not yet support `avx512vnni`. Since it is not very useful
// up to current stage, we can ignore it for now.
#define CHECK_RETURN(X) \
case SIMDFeature::X: \
return __builtin_cpu_supports(#X);
switch (feature)
{
CHECK_RETURN(avx)
CHECK_RETURN(avx2)
CHECK_RETURN(avx512f)
CHECK_RETURN(avx512dq)
CHECK_RETURN(avx512cd)
CHECK_RETURN(avx512bw)
CHECK_RETURN(avx512vl)
}
#undef CHECK_RETURN
return false;
}
#elif defined(__aarch64__)
#ifdef TIFLASH_ENABLE_ASIMD_SUPPORT
extern bool ENABLE_ASIMD;
#endif
#ifdef TIFLASH_ENABLE_SVE_SUPPORT
extern bool ENABLE_SVE;
#endif
enum class SIMDFeature
{
asimd,
pmull,
sve,
sve2
};
static inline bool SIMDRuntimeSupport([[maybe_unused]] SIMDFeature feature)
{
/// Notice that we do not detect support for Darwin/arm64 since
/// it does not have HWCAP support. However, if such feature is
/// ever needed in the future, a good reference can be:
/// https://github.com/golang/sys/pull/114
#if __has_include(<asm/hwcap.h>)
unsigned long hwcap;
switch (feature)
{
// Please Check:
// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
// AARCH64 targets does not has similar builtins for runtime checking; however, it has
// a full series of HWCAP flags to achieve the similar capability.
// CentOS 7 default kernel does not support SVE2, so we just ignore SVE2 in that case.
// (Maybe one can consider it after ARMv9 becomes more prevalent.)
case SIMDFeature::sve:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_SVE;
case SIMDFeature::pmull:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_PMULL;
case SIMDFeature::asimd:
hwcap = getauxval(AT_HWCAP);
return hwcap & HWCAP_ASIMD;
case SIMDFeature::sve2:
#ifdef HWCAP2_SVE2
hwcap = getauxval(AT_HWCAP2);
return hwcap & HWCAP2_SVE2;
#else
return false;
#endif // HWCAP2_SVE2
}
#endif // __has_include(<asm/hwcap.h>)
return false;
}
#endif
/// @todo: notice that currently we use plain SIMD without OOP abstraction:
/// this gives several issues:
/// - there may be similar code paragraph for each vectorization extension
/// - this forbids passing SIMD type to template argument since GCC will give
/// off warnings on discard attributes
/// - some binary operations are ugly
/// For future improvement, one should wrap SIMD types into structs/classes and
/// https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html also gives a good example
/// to reduce some burden of type-casting.
} // namespace simd_option