simdjson  3.1.1
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(__arm__) || defined(__aarch64__) // incl. armel, armhf, arm64
88 
89 #if defined(__ARM_NEON)
90 
91 static inline uint32_t detect_supported_architectures() {
92  return instruction_set::NEON;
93 }
94 
95 #else // ARM without NEON
96 
97 static inline uint32_t detect_supported_architectures() {
98  return instruction_set::DEFAULT;
99 }
100 
101 #endif
102 
103 #elif defined(__x86_64__) || defined(_M_AMD64) // x64
104 
105 
106 namespace {
107 // Can be found on Intel ISA Reference for CPUID
108 constexpr uint32_t cpuid_avx2_bit = 1 << 5;
109 constexpr uint32_t cpuid_bmi1_bit = 1 << 3;
110 constexpr uint32_t cpuid_bmi2_bit = 1 << 8;
111 constexpr uint32_t cpuid_avx512f_bit = 1 << 16;
112 constexpr uint32_t cpuid_avx512dq_bit = 1 << 17;
113 constexpr uint32_t cpuid_avx512ifma_bit = 1 << 21;
114 constexpr uint32_t cpuid_avx512pf_bit = 1 << 26;
115 constexpr uint32_t cpuid_avx512er_bit = 1 << 27;
116 constexpr uint32_t cpuid_avx512cd_bit = 1 << 28;
117 constexpr uint32_t cpuid_avx512bw_bit = 1 << 30;
118 constexpr uint32_t cpuid_avx512vl_bit = 1U << 31;
119 constexpr uint32_t cpuid_avx512vbmi2_bit = 1 << 6;
120 constexpr uint32_t cpuid_sse42_bit = 1 << 20;
121 constexpr uint32_t cpuid_pclmulqdq_bit = 1 << 1;
122 }
123 
124 
125 
126 static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
127  uint32_t *edx) {
128 #if defined(_MSC_VER)
129  int cpu_info[4];
130  __cpuid(cpu_info, *eax);
131  *eax = cpu_info[0];
132  *ebx = cpu_info[1];
133  *ecx = cpu_info[2];
134  *edx = cpu_info[3];
135 #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)
136  uint32_t level = *eax;
137  __get_cpuid(level, eax, ebx, ecx, edx);
138 #else
139  uint32_t a = *eax, b, c = *ecx, d;
140  asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d));
141  *eax = a;
142  *ebx = b;
143  *ecx = c;
144  *edx = d;
145 #endif
146 }
147 
148 static inline uint32_t detect_supported_architectures() {
149  uint32_t eax, ebx, ecx, edx;
150  uint32_t host_isa = 0x0;
151 
152  // ECX for EAX=0x7
153  eax = 0x7;
154  ecx = 0x0;
155  cpuid(&eax, &ebx, &ecx, &edx);
156  if (ebx & cpuid_avx2_bit) {
157  host_isa |= instruction_set::AVX2;
158  }
159  if (ebx & cpuid_bmi1_bit) {
160  host_isa |= instruction_set::BMI1;
161  }
162 
163  if (ebx & cpuid_bmi2_bit) {
164  host_isa |= instruction_set::BMI2;
165  }
166 
167  if (ebx & cpuid_avx512f_bit) {
168  host_isa |= instruction_set::AVX512F;
169  }
170 
171  if (ebx & cpuid_avx512dq_bit) {
172  host_isa |= instruction_set::AVX512DQ;
173  }
174 
175  if (ebx & cpuid_avx512ifma_bit) {
176  host_isa |= instruction_set::AVX512IFMA;
177  }
178 
179  if (ebx & cpuid_avx512pf_bit) {
180  host_isa |= instruction_set::AVX512PF;
181  }
182 
183  if (ebx & cpuid_avx512er_bit) {
184  host_isa |= instruction_set::AVX512ER;
185  }
186 
187  if (ebx & cpuid_avx512cd_bit) {
188  host_isa |= instruction_set::AVX512CD;
189  }
190 
191  if (ebx & cpuid_avx512bw_bit) {
192  host_isa |= instruction_set::AVX512BW;
193  }
194 
195  if (ebx & cpuid_avx512vl_bit) {
196  host_isa |= instruction_set::AVX512VL;
197  }
198 
199  if (ecx & cpuid_avx512vbmi2_bit) {
200  host_isa |= instruction_set::AVX512VBMI2;
201  }
202 
203  // EBX for EAX=0x1
204  eax = 0x1;
205  cpuid(&eax, &ebx, &ecx, &edx);
206 
207  if (ecx & cpuid_sse42_bit) {
208  host_isa |= instruction_set::SSE42;
209  }
210 
211  if (ecx & cpuid_pclmulqdq_bit) {
212  host_isa |= instruction_set::PCLMULQDQ;
213  }
214 
215  return host_isa;
216 }
217 #else // fallback
218 
219 
220 static inline uint32_t detect_supported_architectures() {
221  return instruction_set::DEFAULT;
222 }
223 
224 
225 #endif // end SIMD extension detection code
226 
227 } // namespace internal
228 } // namespace simdjson
229 
230 #endif // SIMDJSON_INTERNAL_ISADETECTION_H
We want to support argument-dependent lookup (ADL).