simdjson  3.1.6
Ridiculously Fast JSON
isadetection.h
1 /* From
2 https://github.com/endorno/pytorch/blob/master/torch/lib/TH/generic/simd/simd.h
3 Highly modified.
4 
5 Copyright (c) 2016- Facebook, Inc (Adam Paszke)
6 Copyright (c) 2014- Facebook, Inc (Soumith Chintala)
7 Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert)
8 Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu)
9 Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)
10 Copyright (c) 2011-2013 NYU (Clement Farabet)
11 Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou,
12 Iain Melvin, Jason Weston) Copyright (c) 2006 Idiap Research Institute
13 (Samy Bengio) Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert,
14 Samy Bengio, Johnny Mariethoz)
15 
16 All rights reserved.
17 
18 Redistribution and use in source and binary forms, with or without
19 modification, are permitted provided that the following conditions are met:
20 
21 1. Redistributions of source code must retain the above copyright
22  notice, this list of conditions and the following disclaimer.
23 
24 2. Redistributions in binary form must reproduce the above copyright
25  notice, this list of conditions and the following disclaimer in the
26  documentation and/or other materials provided with the distribution.
27 
28 3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories
29 America and IDIAP Research Institute nor the names of its contributors may be
30  used to endorse or promote products derived from this software without
31  specific prior written permission.
32 
33 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
37 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 POSSIBILITY OF SUCH DAMAGE.
44 */
45 
46 #ifndef SIMDJSON_INTERNAL_ISADETECTION_H
47 #define SIMDJSON_INTERNAL_ISADETECTION_H
48 
49 #include <cstdint>
50 #include <cstdlib>
51 #if defined(_MSC_VER)
52 #include <intrin.h>
53 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
54 #include <cpuid.h>
55 #endif
56 
57 namespace simdjson {
58 namespace internal {
59 
60 
61 enum instruction_set {
62  DEFAULT = 0x0,
63  NEON = 0x1,
64  AVX2 = 0x4,
65  SSE42 = 0x8,
66  PCLMULQDQ = 0x10,
67  BMI1 = 0x20,
68  BMI2 = 0x40,
69  ALTIVEC = 0x80,
70  AVX512F = 0x100,
71  AVX512DQ = 0x200,
72  AVX512IFMA = 0x400,
73  AVX512PF = 0x800,
74  AVX512ER = 0x1000,
75  AVX512CD = 0x2000,
76  AVX512BW = 0x4000,
77  AVX512VL = 0x8000,
78  AVX512VBMI2 = 0x10000
79 };
80 
81 #if defined(__PPC64__)
82 
83 static inline uint32_t detect_supported_architectures() {
84  return instruction_set::ALTIVEC;
85 }
86 
87 #elif defined(__aarch64__) || defined(_M_ARM64)
88 
89 static inline uint32_t detect_supported_architectures() {
90  return instruction_set::NEON;
91 }
92 
93 #elif defined(__x86_64__) || defined(_M_AMD64) // x64
94 
95 
96 namespace {
97 // Can be found on Intel ISA Reference for CPUID
98 constexpr uint32_t cpuid_avx2_bit = 1 << 5;
99 constexpr uint32_t cpuid_bmi1_bit = 1 << 3;
100 constexpr uint32_t cpuid_bmi2_bit = 1 << 8;
101 constexpr uint32_t cpuid_avx512f_bit = 1 << 16;
102 constexpr uint32_t cpuid_avx512dq_bit = 1 << 17;
103 constexpr uint32_t cpuid_avx512ifma_bit = 1 << 21;
104 constexpr uint32_t cpuid_avx512pf_bit = 1 << 26;
105 constexpr uint32_t cpuid_avx512er_bit = 1 << 27;
106 constexpr uint32_t cpuid_avx512cd_bit = 1 << 28;
107 constexpr uint32_t cpuid_avx512bw_bit = 1 << 30;
108 constexpr uint32_t cpuid_avx512vl_bit = 1U << 31;
109 constexpr uint32_t cpuid_avx512vbmi2_bit = 1 << 6;
110 constexpr uint32_t cpuid_sse42_bit = 1 << 20;
111 constexpr uint32_t cpuid_pclmulqdq_bit = 1 << 1;
112 }
113 
114 
115 
116 static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
117  uint32_t *edx) {
118 #if defined(_MSC_VER)
119  int cpu_info[4];
120  __cpuid(cpu_info, *eax);
121  *eax = cpu_info[0];
122  *ebx = cpu_info[1];
123  *ecx = cpu_info[2];
124  *edx = cpu_info[3];
125 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
126  uint32_t level = *eax;
127  __get_cpuid(level, eax, ebx, ecx, edx);
128 #else
129  uint32_t a = *eax, b, c = *ecx, d;
130  asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d));
131  *eax = a;
132  *ebx = b;
133  *ecx = c;
134  *edx = d;
135 #endif
136 }
137 
138 static inline uint32_t detect_supported_architectures() {
139  uint32_t eax, ebx, ecx, edx;
140  uint32_t host_isa = 0x0;
141 
142  // ECX for EAX=0x7
143  eax = 0x7;
144  ecx = 0x0;
145  cpuid(&eax, &ebx, &ecx, &edx);
146  if (ebx & cpuid_avx2_bit) {
147  host_isa |= instruction_set::AVX2;
148  }
149  if (ebx & cpuid_bmi1_bit) {
150  host_isa |= instruction_set::BMI1;
151  }
152 
153  if (ebx & cpuid_bmi2_bit) {
154  host_isa |= instruction_set::BMI2;
155  }
156 
157  if (ebx & cpuid_avx512f_bit) {
158  host_isa |= instruction_set::AVX512F;
159  }
160 
161  if (ebx & cpuid_avx512dq_bit) {
162  host_isa |= instruction_set::AVX512DQ;
163  }
164 
165  if (ebx & cpuid_avx512ifma_bit) {
166  host_isa |= instruction_set::AVX512IFMA;
167  }
168 
169  if (ebx & cpuid_avx512pf_bit) {
170  host_isa |= instruction_set::AVX512PF;
171  }
172 
173  if (ebx & cpuid_avx512er_bit) {
174  host_isa |= instruction_set::AVX512ER;
175  }
176 
177  if (ebx & cpuid_avx512cd_bit) {
178  host_isa |= instruction_set::AVX512CD;
179  }
180 
181  if (ebx & cpuid_avx512bw_bit) {
182  host_isa |= instruction_set::AVX512BW;
183  }
184 
185  if (ebx & cpuid_avx512vl_bit) {
186  host_isa |= instruction_set::AVX512VL;
187  }
188 
189  if (ecx & cpuid_avx512vbmi2_bit) {
190  host_isa |= instruction_set::AVX512VBMI2;
191  }
192 
193  // EBX for EAX=0x1
194  eax = 0x1;
195  cpuid(&eax, &ebx, &ecx, &edx);
196 
197  if (ecx & cpuid_sse42_bit) {
198  host_isa |= instruction_set::SSE42;
199  }
200 
201  if (ecx & cpuid_pclmulqdq_bit) {
202  host_isa |= instruction_set::PCLMULQDQ;
203  }
204 
205  return host_isa;
206 }
207 #else // fallback
208 
209 
210 static inline uint32_t detect_supported_architectures() {
211  return instruction_set::DEFAULT;
212 }
213 
214 
215 #endif // end SIMD extension detection code
216 
217 } // namespace internal
218 } // namespace simdjson
219 
220 #endif // SIMDJSON_INTERNAL_ISADETECTION_H
We want to support argument-dependent lookup (ADL).