File: | gromacs/gmxlib/gmx_cpuid.c |
Location: | line 468, column 12 |
Description: | Potential leak of memory pointed to by 'unique' |
1 | /* | |||
2 | * This file is part of the GROMACS molecular simulation package. | |||
3 | * | |||
4 | * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by | |||
5 | * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, | |||
6 | * and including many others, as listed in the AUTHORS file in the | |||
7 | * top-level source directory and at http://www.gromacs.org. | |||
8 | * | |||
9 | * GROMACS is free software; you can redistribute it and/or | |||
10 | * modify it under the terms of the GNU Lesser General Public License | |||
11 | * as published by the Free Software Foundation; either version 2.1 | |||
12 | * of the License, or (at your option) any later version. | |||
13 | * | |||
14 | * GROMACS is distributed in the hope that it will be useful, | |||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | * Lesser General Public License for more details. | |||
18 | * | |||
19 | * You should have received a copy of the GNU Lesser General Public | |||
20 | * License along with GROMACS; if not, see | |||
21 | * http://www.gnu.org/licenses, or write to the Free Software Foundation, | |||
22 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
23 | * | |||
24 | * If you want to redistribute modifications to GROMACS, please | |||
25 | * consider that scientific software is very special. Version | |||
26 | * control is crucial - bugs must be traceable. We will be happy to | |||
27 | * consider code for inclusion in the official distribution, but | |||
28 | * derived work must not be called official GROMACS. Details are found | |||
29 | * in the README & COPYING files - if they are missing, get the | |||
30 | * official version at http://www.gromacs.org. | |||
31 | * | |||
32 | * To help us fund GROMACS development, we humbly ask that you cite | |||
33 | * the research papers on the package. Check out http://www.gromacs.org. | |||
34 | */ | |||
35 | #ifdef HAVE_CONFIG_H1 | |||
36 | #include <config.h> | |||
37 | #endif | |||
38 | ||||
39 | #ifdef HAVE_SCHED_H | |||
40 | #define _GNU_SOURCE | |||
41 | #include <sched.h> | |||
42 | #endif | |||
43 | ||||
44 | #include <stdio.h> | |||
45 | #include <stdlib.h> | |||
46 | #include <string.h> | |||
47 | #include <ctype.h> | |||
48 | #ifdef _MSC_VER | |||
49 | /* MSVC definition for __cpuid() */ | |||
50 | #include <intrin.h> | |||
51 | /* sysinfo functions */ | |||
52 | #include <windows.h> | |||
53 | #endif | |||
54 | #ifdef HAVE_UNISTD_H | |||
55 | /* sysconf() definition */ | |||
56 | #include <unistd.h> | |||
57 | #endif | |||
58 | ||||
59 | #include "gmx_cpuid.h" | |||
60 | ||||
61 | ||||
62 | ||||
63 | /* For convenience, and to enable configure-time invocation, we keep all architectures | |||
64 | * in a single file, but to avoid repeated ifdefs we set the overall architecture here. | |||
65 | */ | |||
66 | #ifdef GMX_TARGET_X86 | |||
67 | /* OK, it is x86, but can we execute cpuid? */ | |||
68 | #if defined(GMX_X86_GCC_INLINE_ASM) || ( defined(_MSC_VER) && ( (_MSC_VER > 1500) || (_MSC_VER == 1500 & _MSC_FULL_VER >= 150030729))) | |||
69 | # define GMX_CPUID_X86 | |||
70 | #endif | |||
71 | #endif | |||
72 | ||||
73 | /* Global constant character strings corresponding to our enumerated types */ | |||
74 | const char * | |||
75 | gmx_cpuid_vendor_string[GMX_CPUID_NVENDORS] = | |||
76 | { | |||
77 | "CannotDetect", | |||
78 | "Unknown", | |||
79 | "GenuineIntel", | |||
80 | "AuthenticAMD", | |||
81 | "Fujitsu", | |||
82 | "IBM" | |||
83 | }; | |||
84 | ||||
85 | const char * | |||
86 | gmx_cpuid_vendor_string_alternative[GMX_CPUID_NVENDORS] = | |||
87 | { | |||
88 | "CannotDetect", | |||
89 | "Unknown", | |||
90 | "GenuineIntel", | |||
91 | "AuthenticAMD", | |||
92 | "Fujitsu", | |||
93 | "ibm" /* Used on BlueGene/Q */ | |||
94 | }; | |||
95 | ||||
96 | const char * | |||
97 | gmx_cpuid_feature_string[GMX_CPUID_NFEATURES] = | |||
98 | { | |||
99 | "CannotDetect", | |||
100 | "aes", | |||
101 | "apic", | |||
102 | "avx", | |||
103 | "avx2", | |||
104 | "clfsh", | |||
105 | "cmov", | |||
106 | "cx8", | |||
107 | "cx16", | |||
108 | "f16c", | |||
109 | "fma", | |||
110 | "fma4", | |||
111 | "htt", | |||
112 | "lahf_lm", | |||
113 | "misalignsse", | |||
114 | "mmx", | |||
115 | "msr", | |||
116 | "nonstop_tsc", | |||
117 | "pcid", | |||
118 | "pclmuldq", | |||
119 | "pdcm", | |||
120 | "pdpe1gb", | |||
121 | "popcnt", | |||
122 | "pse", | |||
123 | "rdrnd", | |||
124 | "rdtscp", | |||
125 | "sse2", | |||
126 | "sse3", | |||
127 | "sse4a", | |||
128 | "sse4.1", | |||
129 | "sse4.2", | |||
130 | "ssse3", | |||
131 | "tdt", | |||
132 | "x2apic", | |||
133 | "xop" | |||
134 | }; | |||
135 | ||||
136 | const char * | |||
137 | gmx_cpuid_simd_string[GMX_CPUID_NSIMD] = | |||
138 | { | |||
139 | "CannotDetect", | |||
140 | "None", | |||
141 | "Reference", | |||
142 | "SSE2", | |||
143 | "SSE4.1", | |||
144 | "AVX_128_FMA", | |||
145 | "AVX_256", | |||
146 | "AVX2_256", | |||
147 | "Sparc64 HPC-ACE", | |||
148 | "IBM_QPX" | |||
149 | }; | |||
150 | ||||
151 | /* Max length of brand string */ | |||
152 | #define GMX_CPUID_BRAND_MAXLEN256 256 | |||
153 | ||||
154 | ||||
155 | /* Contents of the abstract datatype */ | |||
156 | struct gmx_cpuid | |||
157 | { | |||
158 | enum gmx_cpuid_vendor vendor; | |||
159 | char brand[GMX_CPUID_BRAND_MAXLEN256]; | |||
160 | int family; | |||
161 | int model; | |||
162 | int stepping; | |||
163 | /* Not using gmx_bool here, since this file must be possible to compile without simple.h */ | |||
164 | char feature[GMX_CPUID_NFEATURES]; | |||
165 | ||||
166 | /* Basic CPU topology information. For x86 this is a bit complicated since the topology differs between | |||
167 | * operating systems and sometimes even settings. For most other architectures you can likely just check | |||
168 | * the documentation and then write static information to these arrays rather than detecting on-the-fly. | |||
169 | */ | |||
170 | int have_cpu_topology; | |||
171 | int nproc; /* total number of logical processors from OS */ | |||
172 | int npackages; | |||
173 | int ncores_per_package; | |||
174 | int nhwthreads_per_core; | |||
175 | int * package_id; | |||
176 | int * core_id; /* Local core id in each package */ | |||
177 | int * hwthread_id; /* Local hwthread id in each core */ | |||
178 | int * locality_order; /* Processor indices sorted in locality order */ | |||
179 | }; | |||
180 | ||||
181 | ||||
182 | /* Simple routines to access the data structure. The initialization routine is | |||
183 | * further down since that needs to call other static routines in this file. | |||
184 | */ | |||
185 | enum gmx_cpuid_vendor | |||
186 | gmx_cpuid_vendor (gmx_cpuid_t cpuid) | |||
187 | { | |||
188 | return cpuid->vendor; | |||
189 | } | |||
190 | ||||
191 | ||||
192 | const char * | |||
193 | gmx_cpuid_brand (gmx_cpuid_t cpuid) | |||
194 | { | |||
195 | return cpuid->brand; | |||
196 | } | |||
197 | ||||
198 | int | |||
199 | gmx_cpuid_family (gmx_cpuid_t cpuid) | |||
200 | { | |||
201 | return cpuid->family; | |||
202 | } | |||
203 | ||||
204 | int | |||
205 | gmx_cpuid_model (gmx_cpuid_t cpuid) | |||
206 | { | |||
207 | return cpuid->model; | |||
208 | } | |||
209 | ||||
210 | int | |||
211 | gmx_cpuid_stepping (gmx_cpuid_t cpuid) | |||
212 | { | |||
213 | return cpuid->stepping; | |||
214 | } | |||
215 | ||||
216 | int | |||
217 | gmx_cpuid_feature (gmx_cpuid_t cpuid, | |||
218 | enum gmx_cpuid_feature feature) | |||
219 | { | |||
220 | return (cpuid->feature[feature] != 0); | |||
221 | } | |||
222 | ||||
223 | ||||
224 | ||||
225 | ||||
226 | /* What type of SIMD was compiled in, if any? */ | |||
227 | #ifdef GMX_SIMD_X86_AVX2_256 | |||
228 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX2_256; | |||
229 | #elif defined GMX_SIMD_X86_AVX_256 | |||
230 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX_256; | |||
231 | #elif defined GMX_SIMD_X86_AVX_128_FMA | |||
232 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX_128_FMA; | |||
233 | #elif defined GMX_SIMD_X86_SSE4_1 | |||
234 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_SSE4_1; | |||
235 | #elif defined GMX_SIMD_X86_SSE2 | |||
236 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_SSE2; | |||
237 | #elif defined GMX_SIMD_SPARC64_HPC_ACE | |||
238 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_SPARC64_HPC_ACE; | |||
239 | #elif defined GMX_SIMD_IBM_QPX | |||
240 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_IBM_QPX; | |||
241 | #elif defined GMX_SIMD_REFERENCE | |||
242 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_REFERENCE; | |||
243 | #else | |||
244 | static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_NONE; | |||
245 | #endif | |||
246 | ||||
247 | ||||
248 | #ifdef GMX_CPUID_X86 | |||
249 | ||||
250 | /* Execute CPUID on x86 class CPUs. level sets function to exec, and the | |||
251 | * contents of register output is returned. See Intel/AMD docs for details. | |||
252 | * | |||
253 | * This version supports extended information where we can also have an input | |||
254 | * value in the ecx register. This is ignored for most levels, but some of them | |||
255 | * (e.g. level 0xB on Intel) use it. | |||
256 | */ | |||
257 | static int | |||
258 | execute_x86cpuid(unsigned int level, | |||
259 | unsigned int ecxval, | |||
260 | unsigned int * eax, | |||
261 | unsigned int * ebx, | |||
262 | unsigned int * ecx, | |||
263 | unsigned int * edx) | |||
264 | { | |||
265 | int rc = 0; | |||
266 | ||||
267 | /* Currently CPUID is only supported (1) if we can use an instruction on MSVC, or (2) | |||
268 | * if the compiler handles GNU-style inline assembly. | |||
269 | */ | |||
270 | ||||
271 | #if (defined _MSC_VER) | |||
272 | int CPUInfo[4]; | |||
273 | ||||
274 | #if (_MSC_VER > 1500) || (_MSC_VER == 1500 & _MSC_FULL_VER >= 150030729) | |||
275 | /* MSVC 9.0 SP1 or later */ | |||
276 | __cpuidex(CPUInfo, level, ecxval); | |||
277 | rc = 0; | |||
278 | #else | |||
279 | __cpuid(CPUInfo, level); | |||
280 | /* Set an error code if the user wanted a non-zero ecxval, since we did not have cpuidex */ | |||
281 | rc = (ecxval > 0) ? -1 : 0; | |||
282 | #endif | |||
283 | *eax = CPUInfo[0]; | |||
284 | *ebx = CPUInfo[1]; | |||
285 | *ecx = CPUInfo[2]; | |||
286 | *edx = CPUInfo[3]; | |||
287 | ||||
288 | #elif (defined GMX_X86_GCC_INLINE_ASM) | |||
289 | /* for now this means GMX_X86_GCC_INLINE_ASM should be defined, | |||
290 | * but there might be more options added in the future. | |||
291 | */ | |||
292 | *eax = level; | |||
293 | *ecx = ecxval; | |||
294 | *ebx = 0; | |||
295 | *edx = 0; | |||
296 | #if defined(__i386__) && defined(__PIC__2) | |||
297 | /* Avoid clobbering the global offset table in 32-bit pic code (ebx register) */ | |||
298 | __asm__ __volatile__ ("xchgl %%ebx, %1 \n\t" | |||
299 | "cpuid \n\t" | |||
300 | "xchgl %%ebx, %1 \n\t" | |||
301 | : "+a" (*eax), "+r" (*ebx), "+c" (*ecx), "+d" (*edx)); | |||
302 | #else | |||
303 | /* i386 without PIC, or x86-64. Things are easy and we can clobber any reg we want :-) */ | |||
304 | __asm__ __volatile__ ("cpuid \n\t" | |||
305 | : "+a" (*eax), "+b" (*ebx), "+c" (*ecx), "+d" (*edx)); | |||
306 | #endif | |||
307 | rc = 0; | |||
308 | #else | |||
309 | /* Death and horror! | |||
310 | * Apparently this is an x86 platform where we don't know how to call cpuid. | |||
311 | * | |||
312 | * This is REALLY bad, since we will lose all Gromacs SIMD support. | |||
313 | */ | |||
314 | *eax = 0; | |||
315 | *ebx = 0; | |||
316 | *ecx = 0; | |||
317 | *edx = 0; | |||
318 | ||||
319 | rc = -1; | |||
320 | #endif | |||
321 | return rc; | |||
322 | } | |||
323 | ||||
324 | ||||
325 | /* Identify CPU features common to Intel & AMD - mainly brand string, | |||
326 | * version and some features. Vendor has already been detected outside this. | |||
327 | */ | |||
328 | static int | |||
329 | cpuid_check_common_x86(gmx_cpuid_t cpuid) | |||
330 | { | |||
331 | int fn, max_stdfn, max_extfn; | |||
332 | unsigned int eax, ebx, ecx, edx; | |||
333 | char str[GMX_CPUID_BRAND_MAXLEN256]; | |||
334 | char * p; | |||
335 | ||||
336 | /* Find largest standard/extended function input value */ | |||
337 | execute_x86cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); | |||
338 | max_stdfn = eax; | |||
339 | execute_x86cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); | |||
340 | max_extfn = eax; | |||
341 | ||||
342 | p = str; | |||
343 | if (max_extfn >= 0x80000005) | |||
344 | { | |||
345 | /* Get CPU brand string */ | |||
346 | for (fn = 0x80000002; fn < 0x80000005; fn++) | |||
347 | { | |||
348 | execute_x86cpuid(fn, 0, &eax, &ebx, &ecx, &edx); | |||
349 | memcpy(p, &eax, 4); | |||
350 | memcpy(p+4, &ebx, 4); | |||
351 | memcpy(p+8, &ecx, 4); | |||
352 | memcpy(p+12, &edx, 4); | |||
353 | p += 16; | |||
354 | } | |||
355 | *p = '\0'; | |||
356 | ||||
357 | /* Remove empty initial space */ | |||
358 | p = str; | |||
359 | while (isspace(*(p))((*__ctype_b_loc ())[(int) ((*(p)))] & (unsigned short int ) _ISspace)) | |||
360 | { | |||
361 | p++; | |||
362 | } | |||
363 | strncpy(cpuid->brand, p, GMX_CPUID_BRAND_MAXLEN)__builtin_strncpy (cpuid->brand, p, 256); | |||
364 | } | |||
365 | else | |||
366 | { | |||
367 | strncpy(cpuid->brand, "Unknown CPU brand", GMX_CPUID_BRAND_MAXLEN)__builtin_strncpy (cpuid->brand, "Unknown CPU brand", 256); | |||
368 | } | |||
369 | ||||
370 | /* Find basic CPU properties */ | |||
371 | if (max_stdfn >= 1) | |||
372 | { | |||
373 | execute_x86cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); | |||
374 | ||||
375 | cpuid->family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8); | |||
376 | /* Note that extended model should be shifted left 4, so only shift right 12 iso 16. */ | |||
377 | cpuid->model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4); | |||
378 | cpuid->stepping = (eax & 0x0000000F); | |||
379 | ||||
380 | /* Feature flags common to AMD and intel */ | |||
381 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSE3] = (ecx & (1 << 0)) != 0; | |||
382 | cpuid->feature[GMX_CPUID_FEATURE_X86_PCLMULDQ] = (ecx & (1 << 1)) != 0; | |||
383 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSSE3] = (ecx & (1 << 9)) != 0; | |||
384 | cpuid->feature[GMX_CPUID_FEATURE_X86_FMA] = (ecx & (1 << 12)) != 0; | |||
385 | cpuid->feature[GMX_CPUID_FEATURE_X86_CX16] = (ecx & (1 << 13)) != 0; | |||
386 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4_1] = (ecx & (1 << 19)) != 0; | |||
387 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4_2] = (ecx & (1 << 20)) != 0; | |||
388 | cpuid->feature[GMX_CPUID_FEATURE_X86_POPCNT] = (ecx & (1 << 23)) != 0; | |||
389 | cpuid->feature[GMX_CPUID_FEATURE_X86_AES] = (ecx & (1 << 25)) != 0; | |||
390 | cpuid->feature[GMX_CPUID_FEATURE_X86_AVX] = (ecx & (1 << 28)) != 0; | |||
391 | cpuid->feature[GMX_CPUID_FEATURE_X86_F16C] = (ecx & (1 << 29)) != 0; | |||
392 | cpuid->feature[GMX_CPUID_FEATURE_X86_RDRND] = (ecx & (1 << 30)) != 0; | |||
393 | ||||
394 | cpuid->feature[GMX_CPUID_FEATURE_X86_PSE] = (edx & (1 << 3)) != 0; | |||
395 | cpuid->feature[GMX_CPUID_FEATURE_X86_MSR] = (edx & (1 << 5)) != 0; | |||
396 | cpuid->feature[GMX_CPUID_FEATURE_X86_CX8] = (edx & (1 << 8)) != 0; | |||
397 | cpuid->feature[GMX_CPUID_FEATURE_X86_APIC] = (edx & (1 << 9)) != 0; | |||
398 | cpuid->feature[GMX_CPUID_FEATURE_X86_CMOV] = (edx & (1 << 15)) != 0; | |||
399 | cpuid->feature[GMX_CPUID_FEATURE_X86_CLFSH] = (edx & (1 << 19)) != 0; | |||
400 | cpuid->feature[GMX_CPUID_FEATURE_X86_MMX] = (edx & (1 << 23)) != 0; | |||
401 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSE2] = (edx & (1 << 26)) != 0; | |||
402 | cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] = (edx & (1 << 28)) != 0; | |||
403 | } | |||
404 | else | |||
405 | { | |||
406 | cpuid->family = -1; | |||
407 | cpuid->model = -1; | |||
408 | cpuid->stepping = -1; | |||
409 | } | |||
410 | ||||
411 | if (max_extfn >= 0x80000001) | |||
412 | { | |||
413 | execute_x86cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx); | |||
414 | cpuid->feature[GMX_CPUID_FEATURE_X86_LAHF_LM] = (ecx & (1 << 0)) != 0; | |||
415 | cpuid->feature[GMX_CPUID_FEATURE_X86_PDPE1GB] = (edx & (1 << 26)) != 0; | |||
416 | cpuid->feature[GMX_CPUID_FEATURE_X86_RDTSCP] = (edx & (1 << 27)) != 0; | |||
417 | } | |||
418 | ||||
419 | if (max_extfn >= 0x80000007) | |||
420 | { | |||
421 | execute_x86cpuid(0x80000007, 0, &eax, &ebx, &ecx, &edx); | |||
422 | cpuid->feature[GMX_CPUID_FEATURE_X86_NONSTOP_TSC] = (edx & (1 << 8)) != 0; | |||
423 | } | |||
424 | return 0; | |||
425 | } | |||
426 | ||||
427 | /* This routine returns the number of unique different elements found in the array, | |||
428 | * and renumbers these starting from 0. For example, the array {0,1,2,8,9,10,8,9,10,0,1,2} | |||
429 | * will be rewritten to {0,1,2,3,4,5,3,4,5,0,1,2}, and it returns 6 for the | |||
430 | * number of unique elements. | |||
431 | */ | |||
432 | static int | |||
433 | cpuid_renumber_elements(int *data, int n) | |||
434 | { | |||
435 | int *unique; | |||
436 | int i, j, nunique, found; | |||
437 | ||||
438 | unique = malloc(sizeof(int)*n); | |||
439 | ||||
440 | nunique = 0; | |||
441 | for (i = 0; i < n; i++) | |||
442 | { | |||
443 | for (j = 0, found = 0; j < nunique && !found; j++) | |||
444 | { | |||
445 | found = (data[i] == unique[j]); | |||
446 | } | |||
447 | if (!found) | |||
448 | { | |||
449 | /* Insert in sorted order! */ | |||
450 | for (j = nunique++; j > 0 && unique[j-1] > data[i]; j--) | |||
451 | { | |||
452 | unique[j] = unique[j-1]; | |||
453 | } | |||
454 | unique[j] = data[i]; | |||
455 | } | |||
456 | } | |||
457 | /* renumber */ | |||
458 | for (i = 0; i < n; i++) | |||
459 | { | |||
460 | for (j = 0; j < nunique; j++) | |||
461 | { | |||
462 | if (data[i] == unique[j]) | |||
463 | { | |||
464 | data[i] = j; | |||
465 | } | |||
466 | } | |||
467 | } | |||
468 | return nunique; | |||
| ||||
469 | } | |||
470 | ||||
471 | /* APIC IDs, or everything you wanted to know about your x86 cores but were afraid to ask... | |||
472 | * | |||
473 | * Raw APIC IDs are unfortunately somewhat dirty. For technical reasons they are assigned | |||
474 | * in power-of-2 chunks, and even then there are no guarantees about specific numbers - all | |||
475 | * we know is that the part for each thread/core/package is unique, and how many bits are | |||
476 | * reserved for that part. | |||
477 | * This routine does internal renumbering so we get continuous indices, and also | |||
478 | * decodes the actual number of packages,cores-per-package and hwthreads-per-core. | |||
479 | * Returns: 0 on success, non-zero on failure. | |||
480 | */ | |||
481 | static int | |||
482 | cpuid_x86_decode_apic_id(gmx_cpuid_t cpuid, int *apic_id, int core_bits, int hwthread_bits) | |||
483 | { | |||
484 | int i, idx; | |||
485 | int hwthread_mask, core_mask_after_shift; | |||
486 | ||||
487 | cpuid->hwthread_id = malloc(sizeof(int)*cpuid->nproc); | |||
488 | cpuid->core_id = malloc(sizeof(int)*cpuid->nproc); | |||
489 | cpuid->package_id = malloc(sizeof(int)*cpuid->nproc); | |||
490 | cpuid->locality_order = malloc(sizeof(int)*cpuid->nproc); | |||
491 | ||||
492 | hwthread_mask = (1 << hwthread_bits) - 1; | |||
493 | core_mask_after_shift = (1 << core_bits) - 1; | |||
494 | ||||
495 | for (i = 0; i < cpuid->nproc; i++) | |||
496 | { | |||
497 | cpuid->hwthread_id[i] = apic_id[i] & hwthread_mask; | |||
498 | cpuid->core_id[i] = (apic_id[i] >> hwthread_bits) & core_mask_after_shift; | |||
499 | cpuid->package_id[i] = apic_id[i] >> (core_bits + hwthread_bits); | |||
500 | } | |||
501 | ||||
502 | cpuid->npackages = cpuid_renumber_elements(cpuid->package_id, cpuid->nproc); | |||
503 | cpuid->ncores_per_package = cpuid_renumber_elements(cpuid->core_id, cpuid->nproc); | |||
504 | cpuid->nhwthreads_per_core = cpuid_renumber_elements(cpuid->hwthread_id, cpuid->nproc); | |||
505 | ||||
506 | /* now check for consistency */ | |||
507 | if ( (cpuid->npackages * cpuid->ncores_per_package * | |||
508 | cpuid->nhwthreads_per_core) != cpuid->nproc) | |||
509 | { | |||
510 | /* the packages/cores-per-package/hwthreads-per-core counts are | |||
511 | inconsistent. */ | |||
512 | return -1; | |||
513 | } | |||
514 | ||||
515 | /* Create a locality order array, i.e. first all resources in package0, which in turn | |||
516 | * are sorted so we first have all resources in core0, where threads are sorted in order, etc. | |||
517 | */ | |||
518 | ||||
519 | for (i = 0; i < cpuid->nproc; i++) | |||
520 | { | |||
521 | idx = (cpuid->package_id[i]*cpuid->ncores_per_package + cpuid->core_id[i])*cpuid->nhwthreads_per_core + cpuid->hwthread_id[i]; | |||
522 | cpuid->locality_order[idx] = i; | |||
523 | } | |||
524 | return 0; | |||
525 | } | |||
526 | ||||
527 | ||||
528 | /* Detection of AMD-specific CPU features */ | |||
529 | static int | |||
530 | cpuid_check_amd_x86(gmx_cpuid_t cpuid) | |||
531 | { | |||
532 | int max_stdfn, max_extfn, ret; | |||
533 | unsigned int eax, ebx, ecx, edx; | |||
534 | int hwthread_bits, core_bits; | |||
535 | int * apic_id; | |||
536 | ||||
537 | cpuid_check_common_x86(cpuid); | |||
538 | ||||
539 | execute_x86cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); | |||
540 | max_stdfn = eax; | |||
541 | ||||
542 | execute_x86cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); | |||
543 | max_extfn = eax; | |||
544 | ||||
545 | if (max_extfn >= 0x80000001) | |||
546 | { | |||
547 | execute_x86cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx); | |||
548 | ||||
549 | cpuid->feature[GMX_CPUID_FEATURE_X86_SSE4A] = (ecx & (1 << 6)) != 0; | |||
550 | cpuid->feature[GMX_CPUID_FEATURE_X86_MISALIGNSSE] = (ecx & (1 << 7)) != 0; | |||
551 | cpuid->feature[GMX_CPUID_FEATURE_X86_XOP] = (ecx & (1 << 11)) != 0; | |||
552 | cpuid->feature[GMX_CPUID_FEATURE_X86_FMA4] = (ecx & (1 << 16)) != 0; | |||
553 | } | |||
554 | ||||
555 | /* Query APIC information on AMD */ | |||
556 | if (max_extfn >= 0x80000008) | |||
557 | { | |||
558 | #if (defined HAVE_SCHED_H && defined HAVE_SCHED_SETAFFINITY && defined HAVE_SYSCONF && defined __linux__1) | |||
559 | /* Linux */ | |||
560 | unsigned int i; | |||
561 | cpu_set_t cpuset, save_cpuset; | |||
562 | cpuid->nproc = sysconf(_SC_NPROCESSORS_ONLN_SC_NPROCESSORS_ONLN); | |||
563 | apic_id = malloc(sizeof(int)*cpuid->nproc); | |||
564 | sched_getaffinity(0, sizeof(cpu_set_t), &save_cpuset); | |||
565 | /* Get APIC id from each core */ | |||
566 | CPU_ZERO(&cpuset)do __builtin_memset (&cpuset, '\0', sizeof (cpu_set_t)); while (0); | |||
567 | for (i = 0; i < cpuid->nproc; i++) | |||
568 | { | |||
569 | CPU_SET(i, &cpuset)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (sizeof ( cpu_set_t)) ? (((__cpu_mask *) ((&cpuset)->__bits))[(( __cpu) / (8 * sizeof (__cpu_mask)))] |= ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask))))) : 0; })); | |||
570 | sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); | |||
571 | execute_x86cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); | |||
572 | apic_id[i] = ebx >> 24; | |||
573 | CPU_CLR(i, &cpuset)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (sizeof ( cpu_set_t)) ? (((__cpu_mask *) ((&cpuset)->__bits))[(( __cpu) / (8 * sizeof (__cpu_mask)))] &= ~((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask))))) : 0; })); | |||
574 | } | |||
575 | /* Reset affinity to the value it had when calling this routine */ | |||
576 | sched_setaffinity(0, sizeof(cpu_set_t), &save_cpuset); | |||
577 | #define CPUID_HAVE_APIC | |||
578 | #elif defined GMX_NATIVE_WINDOWS | |||
579 | /* Windows */ | |||
580 | DWORD_PTR i; | |||
581 | SYSTEM_INFO sysinfo; | |||
582 | unsigned int save_affinity, affinity; | |||
583 | GetSystemInfo( &sysinfo ); | |||
584 | cpuid->nproc = sysinfo.dwNumberOfProcessors; | |||
585 | apic_id = malloc(sizeof(int)*cpuid->nproc); | |||
586 | /* Get previous affinity mask */ | |||
587 | save_affinity = SetThreadAffinityMask(GetCurrentThread(), 1); | |||
588 | for (i = 0; i < cpuid->nproc; i++) | |||
589 | { | |||
590 | SetThreadAffinityMask(GetCurrentThread(), (((DWORD_PTR)1)<<i)); | |||
591 | Sleep(0); | |||
592 | execute_x86cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); | |||
593 | apic_id[i] = ebx >> 24; | |||
594 | } | |||
595 | SetThreadAffinityMask(GetCurrentThread(), save_affinity); | |||
596 | #define CPUID_HAVE_APIC | |||
597 | #endif | |||
598 | #ifdef CPUID_HAVE_APIC | |||
599 | /* AMD does not support SMT yet - there are no hwthread bits in apic ID */ | |||
600 | hwthread_bits = 0; | |||
601 | /* Get number of core bits in apic ID - try modern extended method first */ | |||
602 | execute_x86cpuid(0x80000008, 0, &eax, &ebx, &ecx, &edx); | |||
603 | core_bits = (ecx >> 12) & 0xf; | |||
604 | if (core_bits == 0) | |||
605 | { | |||
606 | /* Legacy method for old single/dual core AMD CPUs */ | |||
607 | int i = ecx & 0xF; | |||
608 | for (core_bits = 0; (i>>core_bits) > 0; core_bits++) | |||
609 | { | |||
610 | ; | |||
611 | } | |||
612 | } | |||
613 | ret = cpuid_x86_decode_apic_id(cpuid, apic_id, core_bits, | |||
614 | hwthread_bits); | |||
615 | cpuid->have_cpu_topology = (ret == 0); | |||
616 | #endif | |||
617 | } | |||
618 | return 0; | |||
619 | } | |||
620 | ||||
621 | /* Detection of Intel-specific CPU features */ | |||
622 | static int | |||
623 | cpuid_check_intel_x86(gmx_cpuid_t cpuid) | |||
624 | { | |||
625 | unsigned int max_stdfn, max_extfn, ret; | |||
626 | unsigned int eax, ebx, ecx, edx; | |||
627 | unsigned int max_logical_cores, max_physical_cores; | |||
628 | int hwthread_bits, core_bits; | |||
629 | int * apic_id; | |||
630 | ||||
631 | cpuid_check_common_x86(cpuid); | |||
632 | ||||
633 | execute_x86cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); | |||
634 | max_stdfn = eax; | |||
635 | ||||
636 | execute_x86cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); | |||
637 | max_extfn = eax; | |||
638 | ||||
639 | if (max_stdfn >= 1) | |||
| ||||
640 | { | |||
641 | execute_x86cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); | |||
642 | cpuid->feature[GMX_CPUID_FEATURE_X86_PDCM] = (ecx & (1 << 15)) != 0; | |||
643 | cpuid->feature[GMX_CPUID_FEATURE_X86_PCID] = (ecx & (1 << 17)) != 0; | |||
644 | cpuid->feature[GMX_CPUID_FEATURE_X86_X2APIC] = (ecx & (1 << 21)) != 0; | |||
645 | cpuid->feature[GMX_CPUID_FEATURE_X86_TDT] = (ecx & (1 << 24)) != 0; | |||
646 | } | |||
647 | ||||
648 | if (max_stdfn >= 7) | |||
649 | { | |||
650 | execute_x86cpuid(0x7, 0, &eax, &ebx, &ecx, &edx); | |||
651 | cpuid->feature[GMX_CPUID_FEATURE_X86_AVX2] = (ebx & (1 << 5)) != 0; | |||
652 | } | |||
653 | ||||
654 | /* Check whether Hyper-Threading is enabled, not only supported */ | |||
655 | if (cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] && max_stdfn >= 4) | |||
656 | { | |||
657 | execute_x86cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); | |||
658 | max_logical_cores = (ebx >> 16) & 0x0FF; | |||
659 | execute_x86cpuid(0x4, 0, &eax, &ebx, &ecx, &edx); | |||
660 | max_physical_cores = ((eax >> 26) & 0x3F) + 1; | |||
661 | ||||
662 | /* Clear HTT flag if we only have 1 logical core per physical */ | |||
663 | if (max_logical_cores/max_physical_cores < 2) | |||
664 | { | |||
665 | cpuid->feature[GMX_CPUID_FEATURE_X86_HTT] = 0; | |||
666 | } | |||
667 | } | |||
668 | ||||
669 | if (max_stdfn >= 0xB) | |||
670 | { | |||
671 | /* Query x2 APIC information from cores */ | |||
672 | #if (defined HAVE_SCHED_H && defined HAVE_SCHED_SETAFFINITY && defined HAVE_SYSCONF && defined __linux__1) | |||
673 | /* Linux */ | |||
674 | unsigned int i; | |||
675 | cpu_set_t cpuset, save_cpuset; | |||
676 | cpuid->nproc = sysconf(_SC_NPROCESSORS_ONLN_SC_NPROCESSORS_ONLN); | |||
677 | apic_id = malloc(sizeof(int)*cpuid->nproc); | |||
678 | sched_getaffinity(0, sizeof(cpu_set_t), &save_cpuset); | |||
679 | /* Get x2APIC ID from each hardware thread */ | |||
680 | CPU_ZERO(&cpuset)do __builtin_memset (&cpuset, '\0', sizeof (cpu_set_t)); while (0); | |||
681 | for (i = 0; i < cpuid->nproc; i++) | |||
682 | { | |||
683 | CPU_SET(i, &cpuset)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (sizeof ( cpu_set_t)) ? (((__cpu_mask *) ((&cpuset)->__bits))[(( __cpu) / (8 * sizeof (__cpu_mask)))] |= ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask))))) : 0; })); | |||
684 | sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); | |||
685 | execute_x86cpuid(0xB, 0, &eax, &ebx, &ecx, &edx); | |||
686 | apic_id[i] = edx; | |||
687 | CPU_CLR(i, &cpuset)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (sizeof ( cpu_set_t)) ? (((__cpu_mask *) ((&cpuset)->__bits))[(( __cpu) / (8 * sizeof (__cpu_mask)))] &= ~((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask))))) : 0; })); | |||
688 | } | |||
689 | /* Reset affinity to the value it had when calling this routine */ | |||
690 | sched_setaffinity(0, sizeof(cpu_set_t), &save_cpuset); | |||
691 | #define CPUID_HAVE_APIC | |||
692 | #elif defined GMX_NATIVE_WINDOWS | |||
693 | /* Windows */ | |||
694 | DWORD_PTR i; | |||
695 | SYSTEM_INFO sysinfo; | |||
696 | unsigned int save_affinity, affinity; | |||
697 | GetSystemInfo( &sysinfo ); | |||
698 | cpuid->nproc = sysinfo.dwNumberOfProcessors; | |||
699 | apic_id = malloc(sizeof(int)*cpuid->nproc); | |||
700 | /* Get previous affinity mask */ | |||
701 | save_affinity = SetThreadAffinityMask(GetCurrentThread(), 1); | |||
702 | for (i = 0; i < cpuid->nproc; i++) | |||
703 | { | |||
704 | SetThreadAffinityMask(GetCurrentThread(), (((DWORD_PTR)1)<<i)); | |||
705 | Sleep(0); | |||
706 | execute_x86cpuid(0xB, 0, &eax, &ebx, &ecx, &edx); | |||
707 | apic_id[i] = edx; | |||
708 | } | |||
709 | SetThreadAffinityMask(GetCurrentThread(), save_affinity); | |||
710 | #define CPUID_HAVE_APIC | |||
711 | #endif | |||
712 | #ifdef CPUID_HAVE_APIC | |||
713 | execute_x86cpuid(0xB, 0, &eax, &ebx, &ecx, &edx); | |||
714 | hwthread_bits = eax & 0x1F; | |||
715 | execute_x86cpuid(0xB, 1, &eax, &ebx, &ecx, &edx); | |||
716 | core_bits = (eax & 0x1F) - hwthread_bits; | |||
717 | ret = cpuid_x86_decode_apic_id(cpuid, apic_id, core_bits, | |||
718 | hwthread_bits); | |||
719 | cpuid->have_cpu_topology = (ret == 0); | |||
720 | #endif | |||
721 | } | |||
722 | return 0; | |||
723 | } | |||
724 | #endif /* GMX_CPUID_X86 */ | |||
725 | ||||
726 | ||||
727 | ||||
728 | ||||
729 | static void | |||
730 | chomp_substring_before_colon(const char *in, char *s, int maxlength) | |||
731 | { | |||
732 | char *p; | |||
733 | strncpy(s, in, maxlength)__builtin_strncpy (s, in, maxlength); | |||
734 | p = strchr(s, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (s) && (':') == '\0' ? (char *) __rawmemchr (s, ':') : __builtin_strchr (s, ':'))); | |||
735 | if (p != NULL((void*)0)) | |||
736 | { | |||
737 | *p = '\0'; | |||
738 | while (isspace(*(--p))((*__ctype_b_loc ())[(int) ((*(--p)))] & (unsigned short int ) _ISspace) && (p >= s)) | |||
739 | { | |||
740 | *p = '\0'; | |||
741 | } | |||
742 | } | |||
743 | else | |||
744 | { | |||
745 | *s = '\0'; | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | static void | |||
750 | chomp_substring_after_colon(const char *in, char *s, int maxlength) | |||
751 | { | |||
752 | char *p; | |||
753 | if ( (p = strchr(in, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (in) && (':') == '\0' ? (char *) __rawmemchr (in, ':' ) : __builtin_strchr (in, ':')))) != NULL((void*)0)) | |||
754 | { | |||
755 | p++; | |||
756 | while (isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) | |||
757 | { | |||
758 | p++; | |||
759 | } | |||
760 | strncpy(s, p, maxlength)__builtin_strncpy (s, p, maxlength); | |||
761 | p = s+strlen(s); | |||
762 | while (isspace(*(--p))((*__ctype_b_loc ())[(int) ((*(--p)))] & (unsigned short int ) _ISspace) && (p >= s)) | |||
763 | { | |||
764 | *p = '\0'; | |||
765 | } | |||
766 | } | |||
767 | else | |||
768 | { | |||
769 | *s = '\0'; | |||
770 | } | |||
771 | } | |||
772 | ||||
773 | /* Try to find the vendor of the current CPU, so we know what specific | |||
774 | * detection routine to call. | |||
775 | */ | |||
776 | static enum gmx_cpuid_vendor | |||
777 | cpuid_check_vendor(void) | |||
778 | { | |||
779 | enum gmx_cpuid_vendor i, vendor; | |||
780 | /* Register data used on x86 */ | |||
781 | unsigned int eax, ebx, ecx, edx; | |||
782 | char vendorstring[13]; | |||
783 | FILE * fp; | |||
784 | char buffer[255], before_colon[255], after_colon[255]; | |||
785 | ||||
786 | /* Set default first */ | |||
787 | vendor = GMX_CPUID_VENDOR_UNKNOWN; | |||
788 | ||||
789 | #ifdef GMX_CPUID_X86 | |||
790 | execute_x86cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); | |||
791 | ||||
792 | memcpy(vendorstring, &ebx, 4); | |||
793 | memcpy(vendorstring+4, &edx, 4); | |||
794 | memcpy(vendorstring+8, &ecx, 4); | |||
795 | ||||
796 | vendorstring[12] = '\0'; | |||
797 | ||||
798 | for (i = GMX_CPUID_VENDOR_UNKNOWN; i < GMX_CPUID_NVENDORS; i++) | |||
799 | { | |||
800 | if (!strncmp(vendorstring, gmx_cpuid_vendor_string[i], 12)(__extension__ (__builtin_constant_p (12) && ((__builtin_constant_p (vendorstring) && strlen (vendorstring) < ((size_t ) (12))) || (__builtin_constant_p (gmx_cpuid_vendor_string[i] ) && strlen (gmx_cpuid_vendor_string[i]) < ((size_t ) (12)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (vendorstring) && __builtin_constant_p (gmx_cpuid_vendor_string [i]) && (__s1_len = strlen (vendorstring), __s2_len = strlen (gmx_cpuid_vendor_string[i]), (!((size_t)(const void * )((vendorstring) + 1) - (size_t)(const void *)(vendorstring) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((gmx_cpuid_vendor_string[i]) + 1) - (size_t)(const void *)(gmx_cpuid_vendor_string [i]) == 1) || __s2_len >= 4)) ? __builtin_strcmp (vendorstring , gmx_cpuid_vendor_string[i]) : (__builtin_constant_p (vendorstring ) && ((size_t)(const void *)((vendorstring) + 1) - (size_t )(const void *)(vendorstring) == 1) && (__s1_len = strlen (vendorstring), __s1_len < 4) ? (__builtin_constant_p (gmx_cpuid_vendor_string [i]) && ((size_t)(const void *)((gmx_cpuid_vendor_string [i]) + 1) - (size_t)(const void *)(gmx_cpuid_vendor_string[i] ) == 1) ? __builtin_strcmp (vendorstring, gmx_cpuid_vendor_string [i]) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (gmx_cpuid_vendor_string[i]); int __result = (((const unsigned char *) (const char *) (vendorstring))[0 ] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (vendorstring ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (vendorstring ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (vendorstring ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( gmx_cpuid_vendor_string[i]) && ((size_t)(const void * )((gmx_cpuid_vendor_string[i]) + 1) - (size_t)(const void *)( gmx_cpuid_vendor_string[i]) == 1) && (__s2_len = strlen (gmx_cpuid_vendor_string[i]), __s2_len < 4) ? (__builtin_constant_p (vendorstring) && ((size_t)(const void *)((vendorstring ) + 1) - (size_t)(const void *)(vendorstring) == 1) ? __builtin_strcmp (vendorstring, gmx_cpuid_vendor_string[i]) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (vendorstring); int __result = (((const unsigned char *) (const char *) (gmx_cpuid_vendor_string[i]))[0] - __s2[0] ); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (gmx_cpuid_vendor_string [i]))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (gmx_cpuid_vendor_string [i]))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (gmx_cpuid_vendor_string [i]))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp ( vendorstring, gmx_cpuid_vendor_string[i])))); }) : strncmp (vendorstring , gmx_cpuid_vendor_string[i], 12)))) | |||
801 | { | |||
802 | vendor = i; | |||
803 | } | |||
804 | } | |||
805 | #elif defined(__linux__1) || defined(__linux1) | |||
806 | /* General Linux. Try to get CPU vendor from /proc/cpuinfo */ | |||
807 | if ( (fp = fopen("/proc/cpuinfo", "r")) != NULL((void*)0)) | |||
808 | { | |||
809 | while ( (vendor == GMX_CPUID_VENDOR_UNKNOWN) && (fgets(buffer, sizeof(buffer), fp) != NULL((void*)0))) | |||
810 | { | |||
811 | chomp_substring_before_colon(buffer, before_colon, sizeof(before_colon)); | |||
812 | /* Intel/AMD use "vendor_id", IBM "vendor"(?) or "model". Fujitsu "manufacture". Add others if you have them! */ | |||
813 | if (!strcmp(before_colon, "vendor_id")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (before_colon) && __builtin_constant_p ("vendor_id") && (__s1_len = strlen (before_colon), __s2_len = strlen ("vendor_id"), (!((size_t)(const void *)((before_colon) + 1) - (size_t)(const void *)(before_colon) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("vendor_id") + 1) - (size_t)(const void *)("vendor_id") == 1) || __s2_len >= 4 )) ? __builtin_strcmp (before_colon, "vendor_id") : (__builtin_constant_p (before_colon) && ((size_t)(const void *)((before_colon ) + 1) - (size_t)(const void *)(before_colon) == 1) && (__s1_len = strlen (before_colon), __s1_len < 4) ? (__builtin_constant_p ("vendor_id") && ((size_t)(const void *)(("vendor_id" ) + 1) - (size_t)(const void *)("vendor_id") == 1) ? __builtin_strcmp (before_colon, "vendor_id") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("vendor_id" ); int __result = (((const unsigned char *) (const char *) (before_colon ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (before_colon ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (before_colon ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (before_colon ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "vendor_id") && ((size_t)(const void *)(("vendor_id") + 1) - (size_t)(const void *)("vendor_id") == 1) && ( __s2_len = strlen ("vendor_id"), __s2_len < 4) ? (__builtin_constant_p (before_colon) && ((size_t)(const void *)((before_colon ) + 1) - (size_t)(const void *)(before_colon) == 1) ? __builtin_strcmp (before_colon, "vendor_id") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (before_colon ); int __result = (((const unsigned char *) (const char *) ("vendor_id" ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("vendor_id" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("vendor_id" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("vendor_id" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (before_colon , "vendor_id")))); }) | |||
814 | || !strcmp(before_colon, "vendor")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (before_colon) && __builtin_constant_p ("vendor") && (__s1_len = strlen (before_colon), __s2_len = strlen ("vendor" ), (!((size_t)(const void *)((before_colon) + 1) - (size_t)(const void *)(before_colon) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("vendor") + 1) - (size_t)(const void *)("vendor") == 1) || __s2_len >= 4)) ? __builtin_strcmp ( before_colon, "vendor") : (__builtin_constant_p (before_colon ) && ((size_t)(const void *)((before_colon) + 1) - (size_t )(const void *)(before_colon) == 1) && (__s1_len = strlen (before_colon), __s1_len < 4) ? (__builtin_constant_p ("vendor" ) && ((size_t)(const void *)(("vendor") + 1) - (size_t )(const void *)("vendor") == 1) ? __builtin_strcmp (before_colon , "vendor") : (__extension__ ({ const unsigned char *__s2 = ( const unsigned char *) (const char *) ("vendor"); int __result = (((const unsigned char *) (const char *) (before_colon))[0 ] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (before_colon ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (before_colon ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (before_colon ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "vendor") && ((size_t)(const void *)(("vendor") + 1) - (size_t)(const void *)("vendor") == 1) && (__s2_len = strlen ("vendor"), __s2_len < 4) ? (__builtin_constant_p ( before_colon) && ((size_t)(const void *)((before_colon ) + 1) - (size_t)(const void *)(before_colon) == 1) ? __builtin_strcmp (before_colon, "vendor") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (before_colon ); int __result = (((const unsigned char *) (const char *) ("vendor" ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("vendor" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("vendor" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("vendor" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (before_colon , "vendor")))); }) | |||
815 | || !strcmp(before_colon, "manufacture")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (before_colon) && __builtin_constant_p ("manufacture" ) && (__s1_len = strlen (before_colon), __s2_len = strlen ("manufacture"), (!((size_t)(const void *)((before_colon) + 1 ) - (size_t)(const void *)(before_colon) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("manufacture") + 1) - (size_t)(const void *)("manufacture") == 1) || __s2_len >= 4)) ? __builtin_strcmp (before_colon, "manufacture") : (__builtin_constant_p (before_colon) && ((size_t)(const void *)((before_colon ) + 1) - (size_t)(const void *)(before_colon) == 1) && (__s1_len = strlen (before_colon), __s1_len < 4) ? (__builtin_constant_p ("manufacture") && ((size_t)(const void *)(("manufacture" ) + 1) - (size_t)(const void *)("manufacture") == 1) ? __builtin_strcmp (before_colon, "manufacture") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("manufacture" ); int __result = (((const unsigned char *) (const char *) (before_colon ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (before_colon ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (before_colon ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (before_colon ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "manufacture") && ((size_t)(const void *)(("manufacture" ) + 1) - (size_t)(const void *)("manufacture") == 1) && (__s2_len = strlen ("manufacture"), __s2_len < 4) ? (__builtin_constant_p (before_colon) && ((size_t)(const void *)((before_colon ) + 1) - (size_t)(const void *)(before_colon) == 1) ? __builtin_strcmp (before_colon, "manufacture") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (before_colon ); int __result = (((const unsigned char *) (const char *) ("manufacture" ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("manufacture" ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) ("manufacture" ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) ("manufacture" ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (before_colon , "manufacture")))); }) | |||
816 | || !strcmp(before_colon, "model")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (before_colon) && __builtin_constant_p ("model") && (__s1_len = strlen (before_colon), __s2_len = strlen ("model" ), (!((size_t)(const void *)((before_colon) + 1) - (size_t)(const void *)(before_colon) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)(("model") + 1) - (size_t)(const void *)("model") == 1) || __s2_len >= 4)) ? __builtin_strcmp ( before_colon, "model") : (__builtin_constant_p (before_colon) && ((size_t)(const void *)((before_colon) + 1) - (size_t )(const void *)(before_colon) == 1) && (__s1_len = strlen (before_colon), __s1_len < 4) ? (__builtin_constant_p ("model" ) && ((size_t)(const void *)(("model") + 1) - (size_t )(const void *)("model") == 1) ? __builtin_strcmp (before_colon , "model") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("model"); int __result = (( (const unsigned char *) (const char *) (before_colon))[0] - __s2 [0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (before_colon))[1 ] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (before_colon ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (before_colon ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( "model") && ((size_t)(const void *)(("model") + 1) - ( size_t)(const void *)("model") == 1) && (__s2_len = strlen ("model"), __s2_len < 4) ? (__builtin_constant_p (before_colon ) && ((size_t)(const void *)((before_colon) + 1) - (size_t )(const void *)(before_colon) == 1) ? __builtin_strcmp (before_colon , "model") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (before_colon); int __result = (((const unsigned char *) (const char *) ("model"))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("model"))[1] - __s2 [1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("model"))[2] - __s2 [2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("model"))[3] - __s2 [3]); } } __result; })))) : __builtin_strcmp (before_colon, "model" )))); })) | |||
817 | { | |||
818 | chomp_substring_after_colon(buffer, after_colon, sizeof(after_colon)); | |||
819 | for (i = GMX_CPUID_VENDOR_UNKNOWN; i < GMX_CPUID_NVENDORS; i++) | |||
820 | { | |||
821 | /* Be liberal and accept if we find the vendor | |||
822 | * string (or alternative string) anywhere. Using | |||
823 | * strcasestr() would be non-portable. */ | |||
824 | if (strstr(after_colon, gmx_cpuid_vendor_string[i]) | |||
825 | || strstr(after_colon, gmx_cpuid_vendor_string_alternative[i])) | |||
826 | { | |||
827 | vendor = i; | |||
828 | } | |||
829 | } | |||
830 | } | |||
831 | } | |||
832 | } | |||
833 | fclose(fp); | |||
834 | #endif | |||
835 | ||||
836 | return vendor; | |||
837 | } | |||
838 | ||||
839 | ||||
840 | ||||
841 | int | |||
842 | gmx_cpuid_topology(gmx_cpuid_t cpuid, | |||
843 | int * nprocessors, | |||
844 | int * npackages, | |||
845 | int * ncores_per_package, | |||
846 | int * nhwthreads_per_core, | |||
847 | const int ** package_id, | |||
848 | const int ** core_id, | |||
849 | const int ** hwthread_id, | |||
850 | const int ** locality_order) | |||
851 | { | |||
852 | int rc; | |||
853 | ||||
854 | if (cpuid->have_cpu_topology) | |||
855 | { | |||
856 | *nprocessors = cpuid->nproc; | |||
857 | *npackages = cpuid->npackages; | |||
858 | *ncores_per_package = cpuid->ncores_per_package; | |||
859 | *nhwthreads_per_core = cpuid->nhwthreads_per_core; | |||
860 | *package_id = cpuid->package_id; | |||
861 | *core_id = cpuid->core_id; | |||
862 | *hwthread_id = cpuid->hwthread_id; | |||
863 | *locality_order = cpuid->locality_order; | |||
864 | rc = 0; | |||
865 | } | |||
866 | else | |||
867 | { | |||
868 | rc = -1; | |||
869 | } | |||
870 | return rc; | |||
871 | } | |||
872 | ||||
873 | ||||
874 | enum gmx_cpuid_x86_smt | |||
875 | gmx_cpuid_x86_smt(gmx_cpuid_t cpuid) | |||
876 | { | |||
877 | enum gmx_cpuid_x86_smt rc; | |||
878 | ||||
879 | if (cpuid->have_cpu_topology) | |||
880 | { | |||
881 | rc = (cpuid->nhwthreads_per_core > 1) ? GMX_CPUID_X86_SMT_ENABLED : GMX_CPUID_X86_SMT_DISABLED; | |||
882 | } | |||
883 | else if (cpuid->vendor == GMX_CPUID_VENDOR_AMD || gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_HTT) == 0) | |||
884 | { | |||
885 | rc = GMX_CPUID_X86_SMT_DISABLED; | |||
886 | } | |||
887 | else | |||
888 | { | |||
889 | rc = GMX_CPUID_X86_SMT_CANNOTDETECT; | |||
890 | } | |||
891 | return rc; | |||
892 | } | |||
893 | ||||
894 | ||||
895 | int | |||
896 | gmx_cpuid_init (gmx_cpuid_t * pcpuid) | |||
897 | { | |||
898 | gmx_cpuid_t cpuid; | |||
899 | int i; | |||
900 | FILE * fp; | |||
901 | char buffer[255], buffer2[255]; | |||
902 | int found_brand; | |||
903 | ||||
904 | cpuid = malloc(sizeof(*cpuid)); | |||
905 | ||||
906 | *pcpuid = cpuid; | |||
907 | ||||
908 | for (i = 0; i < GMX_CPUID_NFEATURES; i++) | |||
909 | { | |||
910 | cpuid->feature[i] = 0; | |||
911 | } | |||
912 | ||||
913 | cpuid->have_cpu_topology = 0; | |||
914 | cpuid->nproc = 0; | |||
915 | cpuid->npackages = 0; | |||
916 | cpuid->ncores_per_package = 0; | |||
917 | cpuid->nhwthreads_per_core = 0; | |||
918 | cpuid->package_id = NULL((void*)0); | |||
919 | cpuid->core_id = NULL((void*)0); | |||
920 | cpuid->hwthread_id = NULL((void*)0); | |||
921 | cpuid->locality_order = NULL((void*)0); | |||
922 | ||||
923 | cpuid->vendor = cpuid_check_vendor(); | |||
924 | ||||
925 | switch (cpuid->vendor) | |||
926 | { | |||
927 | #ifdef GMX_CPUID_X86 | |||
928 | case GMX_CPUID_VENDOR_INTEL: | |||
929 | cpuid_check_intel_x86(cpuid); | |||
930 | break; | |||
931 | case GMX_CPUID_VENDOR_AMD: | |||
932 | cpuid_check_amd_x86(cpuid); | |||
933 | break; | |||
934 | #endif | |||
935 | default: | |||
936 | /* Default value */ | |||
937 | strncpy(cpuid->brand, "Unknown CPU brand", GMX_CPUID_BRAND_MAXLEN)__builtin_strncpy (cpuid->brand, "Unknown CPU brand", 256); | |||
938 | #if defined(__linux__1) || defined(__linux1) | |||
939 | /* General Linux. Try to get CPU type from /proc/cpuinfo */ | |||
940 | if ( (fp = fopen("/proc/cpuinfo", "r")) != NULL((void*)0)) | |||
941 | { | |||
942 | found_brand = 0; | |||
943 | while ( (found_brand == 0) && (fgets(buffer, sizeof(buffer), fp) != NULL((void*)0))) | |||
944 | { | |||
945 | chomp_substring_before_colon(buffer, buffer2, sizeof(buffer2)); | |||
946 | /* Intel uses "model name", Fujitsu and IBM "cpu". */ | |||
947 | if (!strcmp(buffer2, "model name")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (buffer2) && __builtin_constant_p ("model name") && (__s1_len = strlen (buffer2), __s2_len = strlen ("model name" ), (!((size_t)(const void *)((buffer2) + 1) - (size_t)(const void *)(buffer2) == 1) || __s1_len >= 4) && (!((size_t )(const void *)(("model name") + 1) - (size_t)(const void *)( "model name") == 1) || __s2_len >= 4)) ? __builtin_strcmp ( buffer2, "model name") : (__builtin_constant_p (buffer2) && ((size_t)(const void *)((buffer2) + 1) - (size_t)(const void *)(buffer2) == 1) && (__s1_len = strlen (buffer2), __s1_len < 4) ? (__builtin_constant_p ("model name") && (( size_t)(const void *)(("model name") + 1) - (size_t)(const void *)("model name") == 1) ? __builtin_strcmp (buffer2, "model name" ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("model name"); int __result = (((const unsigned char *) (const char *) (buffer2))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buffer2))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buffer2))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (buffer2))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("model name") && ((size_t)(const void *)(("model name") + 1) - (size_t)(const void *)("model name") == 1) && (__s2_len = strlen ("model name" ), __s2_len < 4) ? (__builtin_constant_p (buffer2) && ((size_t)(const void *)((buffer2) + 1) - (size_t)(const void *)(buffer2) == 1) ? __builtin_strcmp (buffer2, "model name") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buffer2); int __result = (((const unsigned char *) (const char *) ("model name"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("model name"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("model name"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("model name"))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (buffer2, "model name")))); }) || !strcmp(buffer2, "cpu")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (buffer2) && __builtin_constant_p ("cpu") && (__s1_len = strlen (buffer2), __s2_len = strlen ("cpu"), (!( (size_t)(const void *)((buffer2) + 1) - (size_t)(const void * )(buffer2) == 1) || __s1_len >= 4) && (!((size_t)( const void *)(("cpu") + 1) - (size_t)(const void *)("cpu") == 1) || __s2_len >= 4)) ? __builtin_strcmp (buffer2, "cpu") : (__builtin_constant_p (buffer2) && ((size_t)(const void *)((buffer2) + 1) - (size_t)(const void *)(buffer2) == 1 ) && (__s1_len = strlen (buffer2), __s1_len < 4) ? (__builtin_constant_p ("cpu") && ((size_t)(const void *)(("cpu") + 1) - (size_t)(const void *)("cpu") == 1) ? __builtin_strcmp (buffer2, "cpu") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("cpu"); int __result = (((const unsigned char *) (const char *) (buffer2))[0] - __s2 [0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buffer2))[1] - __s2 [1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buffer2))[2] - __s2 [2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (buffer2))[3] - __s2 [3]); } } __result; }))) : (__builtin_constant_p ("cpu") && ((size_t)(const void *)(("cpu") + 1) - (size_t)(const void * )("cpu") == 1) && (__s2_len = strlen ("cpu"), __s2_len < 4) ? (__builtin_constant_p (buffer2) && ((size_t )(const void *)((buffer2) + 1) - (size_t)(const void *)(buffer2 ) == 1) ? __builtin_strcmp (buffer2, "cpu") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buffer2); int __result = (((const unsigned char *) ( const char *) ("cpu"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("cpu"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("cpu"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("cpu"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (buffer2, "cpu")))); })) | |||
948 | { | |||
949 | chomp_substring_after_colon(buffer, cpuid->brand, GMX_CPUID_BRAND_MAXLEN256); | |||
950 | found_brand = 1; | |||
951 | } | |||
952 | } | |||
953 | } | |||
954 | fclose(fp); | |||
955 | #endif | |||
956 | cpuid->family = 0; | |||
957 | cpuid->model = 0; | |||
958 | cpuid->stepping = 0; | |||
959 | ||||
960 | for (i = 0; i < GMX_CPUID_NFEATURES; i++) | |||
961 | { | |||
962 | cpuid->feature[i] = 0; | |||
963 | } | |||
964 | cpuid->feature[GMX_CPUID_FEATURE_CANNOTDETECT] = 1; | |||
965 | break; | |||
966 | } | |||
967 | return 0; | |||
968 | } | |||
969 | ||||
970 | ||||
971 | ||||
972 | void | |||
973 | gmx_cpuid_done (gmx_cpuid_t cpuid) | |||
974 | { | |||
975 | free(cpuid); | |||
976 | } | |||
977 | ||||
978 | ||||
979 | int | |||
980 | gmx_cpuid_formatstring (gmx_cpuid_t cpuid, | |||
981 | char * str, | |||
982 | int n) | |||
983 | { | |||
984 | int c; | |||
985 | int i; | |||
986 | enum gmx_cpuid_feature feature; | |||
987 | ||||
988 | #ifdef _MSC_VER | |||
989 | _snprintf(str, n, | |||
990 | "Vendor: %s\n" | |||
991 | "Brand: %s\n" | |||
992 | "Family: %2d Model: %2d Stepping: %2d\n" | |||
993 | "Features:", | |||
994 | gmx_cpuid_vendor_string[gmx_cpuid_vendor(cpuid)], | |||
995 | gmx_cpuid_brand(cpuid), | |||
996 | gmx_cpuid_family(cpuid), gmx_cpuid_model(cpuid), gmx_cpuid_stepping(cpuid)); | |||
997 | #else | |||
998 | snprintf(str, n, | |||
999 | "Vendor: %s\n" | |||
1000 | "Brand: %s\n" | |||
1001 | "Family: %2d Model: %2d Stepping: %2d\n" | |||
1002 | "Features:", | |||
1003 | gmx_cpuid_vendor_string[gmx_cpuid_vendor(cpuid)], | |||
1004 | gmx_cpuid_brand(cpuid), | |||
1005 | gmx_cpuid_family(cpuid), gmx_cpuid_model(cpuid), gmx_cpuid_stepping(cpuid)); | |||
1006 | #endif | |||
1007 | ||||
1008 | str[n-1] = '\0'; | |||
1009 | c = strlen(str); | |||
1010 | n -= c; | |||
1011 | str += c; | |||
1012 | ||||
1013 | for (feature = GMX_CPUID_FEATURE_CANNOTDETECT; feature < GMX_CPUID_NFEATURES; feature++) | |||
1014 | { | |||
1015 | if (gmx_cpuid_feature(cpuid, feature) == 1) | |||
1016 | { | |||
1017 | #ifdef _MSC_VER | |||
1018 | _snprintf(str, n, " %s", gmx_cpuid_feature_string[feature]); | |||
1019 | #else | |||
1020 | snprintf(str, n, " %s", gmx_cpuid_feature_string[feature]); | |||
1021 | #endif | |||
1022 | str[n-1] = '\0'; | |||
1023 | c = strlen(str); | |||
1024 | n -= c; | |||
1025 | str += c; | |||
1026 | } | |||
1027 | } | |||
1028 | #ifdef _MSC_VER | |||
1029 | _snprintf(str, n, "\n"); | |||
1030 | #else | |||
1031 | snprintf(str, n, "\n"); | |||
1032 | #endif | |||
1033 | str[n-1] = '\0'; | |||
1034 | ||||
1035 | return 0; | |||
1036 | } | |||
1037 | ||||
1038 | ||||
1039 | ||||
1040 | enum gmx_cpuid_simd | |||
1041 | gmx_cpuid_simd_suggest (gmx_cpuid_t cpuid) | |||
1042 | { | |||
1043 | enum gmx_cpuid_simd tmpsimd; | |||
1044 | ||||
1045 | tmpsimd = GMX_CPUID_SIMD_NONE; | |||
1046 | ||||
1047 | if (gmx_cpuid_vendor(cpuid) == GMX_CPUID_VENDOR_INTEL) | |||
1048 | { | |||
1049 | if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_AVX2)) | |||
1050 | { | |||
1051 | tmpsimd = GMX_CPUID_SIMD_X86_AVX2_256; | |||
1052 | } | |||
1053 | else if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_AVX)) | |||
1054 | { | |||
1055 | tmpsimd = GMX_CPUID_SIMD_X86_AVX_256; | |||
1056 | } | |||
1057 | else if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_SSE4_1)) | |||
1058 | { | |||
1059 | tmpsimd = GMX_CPUID_SIMD_X86_SSE4_1; | |||
1060 | } | |||
1061 | else if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_SSE2)) | |||
1062 | { | |||
1063 | tmpsimd = GMX_CPUID_SIMD_X86_SSE2; | |||
1064 | } | |||
1065 | } | |||
1066 | else if (gmx_cpuid_vendor(cpuid) == GMX_CPUID_VENDOR_AMD) | |||
1067 | { | |||
1068 | if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_AVX)) | |||
1069 | { | |||
1070 | tmpsimd = GMX_CPUID_SIMD_X86_AVX_128_FMA; | |||
1071 | } | |||
1072 | else if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_SSE4_1)) | |||
1073 | { | |||
1074 | tmpsimd = GMX_CPUID_SIMD_X86_SSE4_1; | |||
1075 | } | |||
1076 | else if (gmx_cpuid_feature(cpuid, GMX_CPUID_FEATURE_X86_SSE2)) | |||
1077 | { | |||
1078 | tmpsimd = GMX_CPUID_SIMD_X86_SSE2; | |||
1079 | } | |||
1080 | } | |||
1081 | else if (gmx_cpuid_vendor(cpuid) == GMX_CPUID_VENDOR_FUJITSU) | |||
1082 | { | |||
1083 | if (strstr(gmx_cpuid_brand(cpuid), "SPARC64")) | |||
1084 | { | |||
1085 | tmpsimd = GMX_CPUID_SIMD_SPARC64_HPC_ACE; | |||
1086 | } | |||
1087 | } | |||
1088 | else if (gmx_cpuid_vendor(cpuid) == GMX_CPUID_VENDOR_IBM) | |||
1089 | { | |||
1090 | if (strstr(gmx_cpuid_brand(cpuid), "A2")) | |||
1091 | { | |||
1092 | tmpsimd = GMX_CPUID_SIMD_IBM_QPX; | |||
1093 | } | |||
1094 | } | |||
1095 | return tmpsimd; | |||
1096 | } | |||
1097 | ||||
1098 | ||||
1099 | ||||
1100 | int | |||
1101 | gmx_cpuid_simd_check(gmx_cpuid_t cpuid, | |||
1102 | FILE * log, | |||
1103 | int print_to_stderr) | |||
1104 | { | |||
1105 | int rc; | |||
1106 | char str[1024]; | |||
1107 | enum gmx_cpuid_simd simd; | |||
1108 | ||||
1109 | simd = gmx_cpuid_simd_suggest(cpuid); | |||
1110 | ||||
1111 | rc = (simd != compiled_simd); | |||
1112 | ||||
1113 | gmx_cpuid_formatstring(cpuid, str, 1023); | |||
1114 | str[1023] = '\0'; | |||
1115 | ||||
1116 | if (log != NULL((void*)0)) | |||
1117 | { | |||
1118 | fprintf(log, | |||
1119 | "\nDetecting CPU SIMD instructions.\nPresent hardware specification:\n" | |||
1120 | "%s" | |||
1121 | "SIMD instructions most likely to fit this hardware: %s\n" | |||
1122 | "SIMD instructions selected at GROMACS compile time: %s\n\n", | |||
1123 | str, | |||
1124 | gmx_cpuid_simd_string[simd], | |||
1125 | gmx_cpuid_simd_string[compiled_simd]); | |||
1126 | } | |||
1127 | ||||
1128 | if (rc != 0) | |||
1129 | { | |||
1130 | if (log != NULL((void*)0)) | |||
1131 | { | |||
1132 | fprintf(log, "\nBinary not matching hardware - you might be losing performance.\n" | |||
1133 | "SIMD instructions most likely to fit this hardware: %s\n" | |||
1134 | "SIMD instructions selected at GROMACS compile time: %s\n\n", | |||
1135 | gmx_cpuid_simd_string[simd], | |||
1136 | gmx_cpuid_simd_string[compiled_simd]); | |||
1137 | } | |||
1138 | if (print_to_stderr) | |||
1139 | { | |||
1140 | fprintf(stderrstderr, "Compiled SIMD instructions: %s (Gromacs could use %s on this machine, which is better)\n", | |||
1141 | gmx_cpuid_simd_string[compiled_simd], | |||
1142 | gmx_cpuid_simd_string[simd]); | |||
1143 | } | |||
1144 | } | |||
1145 | return rc; | |||
1146 | } | |||
1147 | ||||
1148 | ||||
1149 | #ifdef GMX_CPUID_STANDALONE | |||
1150 | /* Stand-alone program to enable queries of CPU features from Cmake. | |||
1151 | * Note that you need to check inline ASM capabilities before compiling and set | |||
1152 | * -DGMX_X86_GCC_INLINE_ASM for the cpuid instruction to work... | |||
1153 | */ | |||
1154 | int | |||
1155 | main(int argc, char **argv) | |||
1156 | { | |||
1157 | gmx_cpuid_t cpuid; | |||
1158 | enum gmx_cpuid_simd simd; | |||
1159 | int i, cnt; | |||
1160 | ||||
1161 | if (argc < 2) | |||
1162 | { | |||
1163 | fprintf(stdoutstdout, | |||
1164 | "Usage:\n\n%s [flags]\n\n" | |||
1165 | "Available flags:\n" | |||
1166 | "-vendor Print CPU vendor.\n" | |||
1167 | "-brand Print CPU brand string.\n" | |||
1168 | "-family Print CPU family version.\n" | |||
1169 | "-model Print CPU model version.\n" | |||
1170 | "-stepping Print CPU stepping version.\n" | |||
1171 | "-features Print CPU feature flags.\n" | |||
1172 | "-simd Print suggested GROMACS SIMD instructions.\n", | |||
1173 | argv[0]); | |||
1174 | exit(0); | |||
1175 | } | |||
1176 | ||||
1177 | gmx_cpuid_init(&cpuid); | |||
1178 | ||||
1179 | if (!strncmp(argv[1], "-vendor", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-vendor") && strlen ("-vendor" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-vendor") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-vendor"), (!((size_t)(const void *)((argv[1]) + 1 ) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4 ) && (!((size_t)(const void *)(("-vendor") + 1) - (size_t )(const void *)("-vendor") == 1) || __s2_len >= 4)) ? __builtin_strcmp (argv[1], "-vendor") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ("-vendor") && ((size_t )(const void *)(("-vendor") + 1) - (size_t)(const void *)("-vendor" ) == 1) ? __builtin_strcmp (argv[1], "-vendor") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-vendor"); int __result = (((const unsigned char * ) (const char *) (argv[1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[1]))[3] - __s2[3]); } } __result; }) )) : (__builtin_constant_p ("-vendor") && ((size_t)(const void *)(("-vendor") + 1) - (size_t)(const void *)("-vendor") == 1) && (__s2_len = strlen ("-vendor"), __s2_len < 4) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1 ) ? __builtin_strcmp (argv[1], "-vendor") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) ( const char *) ("-vendor"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-vendor"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-vendor"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-vendor"))[3] - __s2[3]); } } __result; } )))) : __builtin_strcmp (argv[1], "-vendor")))); }) : strncmp (argv[1], "-vendor", 3)))) | |||
1180 | { | |||
1181 | printf("%s\n", gmx_cpuid_vendor_string[cpuid->vendor]); | |||
1182 | } | |||
1183 | else if (!strncmp(argv[1], "-brand", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-brand") && strlen ("-brand" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-brand") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-brand"), (!((size_t)(const void *)((argv[1]) + 1 ) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4 ) && (!((size_t)(const void *)(("-brand") + 1) - (size_t )(const void *)("-brand") == 1) || __s2_len >= 4)) ? __builtin_strcmp (argv[1], "-brand") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ("-brand") && ((size_t )(const void *)(("-brand") + 1) - (size_t)(const void *)("-brand" ) == 1) ? __builtin_strcmp (argv[1], "-brand") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-brand"); int __result = (((const unsigned char *) (const char *) (argv[1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[1]))[3] - __s2[3]); } } __result; }) )) : (__builtin_constant_p ("-brand") && ((size_t)(const void *)(("-brand") + 1) - (size_t)(const void *)("-brand") == 1) && (__s2_len = strlen ("-brand"), __s2_len < 4 ) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1 ) ? __builtin_strcmp (argv[1], "-brand") : (- (__extension__ ( { const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) (const char *) ("-brand"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-brand"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-brand"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-brand"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (argv[1], "-brand")))); }) : strncmp (argv[1], "-brand", 3)) )) | |||
1184 | { | |||
1185 | printf("%s\n", cpuid->brand); | |||
1186 | } | |||
1187 | else if (!strncmp(argv[1], "-family", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-family") && strlen ("-family" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-family") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-family"), (!((size_t)(const void *)((argv[1]) + 1 ) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4 ) && (!((size_t)(const void *)(("-family") + 1) - (size_t )(const void *)("-family") == 1) || __s2_len >= 4)) ? __builtin_strcmp (argv[1], "-family") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ("-family") && ((size_t )(const void *)(("-family") + 1) - (size_t)(const void *)("-family" ) == 1) ? __builtin_strcmp (argv[1], "-family") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-family"); int __result = (((const unsigned char * ) (const char *) (argv[1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[1]))[3] - __s2[3]); } } __result; }) )) : (__builtin_constant_p ("-family") && ((size_t)(const void *)(("-family") + 1) - (size_t)(const void *)("-family") == 1) && (__s2_len = strlen ("-family"), __s2_len < 4) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1 ) ? __builtin_strcmp (argv[1], "-family") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) ( const char *) ("-family"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-family"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-family"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-family"))[3] - __s2[3]); } } __result; } )))) : __builtin_strcmp (argv[1], "-family")))); }) : strncmp (argv[1], "-family", 3)))) | |||
1188 | { | |||
1189 | printf("%d\n", cpuid->family); | |||
1190 | } | |||
1191 | else if (!strncmp(argv[1], "-model", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-model") && strlen ("-model" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-model") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-model"), (!((size_t)(const void *)((argv[1]) + 1 ) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4 ) && (!((size_t)(const void *)(("-model") + 1) - (size_t )(const void *)("-model") == 1) || __s2_len >= 4)) ? __builtin_strcmp (argv[1], "-model") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ("-model") && ((size_t )(const void *)(("-model") + 1) - (size_t)(const void *)("-model" ) == 1) ? __builtin_strcmp (argv[1], "-model") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-model"); int __result = (((const unsigned char *) (const char *) (argv[1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[1]))[3] - __s2[3]); } } __result; }) )) : (__builtin_constant_p ("-model") && ((size_t)(const void *)(("-model") + 1) - (size_t)(const void *)("-model") == 1) && (__s2_len = strlen ("-model"), __s2_len < 4 ) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1 ) ? __builtin_strcmp (argv[1], "-model") : (- (__extension__ ( { const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) (const char *) ("-model"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-model"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-model"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-model"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (argv[1], "-model")))); }) : strncmp (argv[1], "-model", 3)) )) | |||
1192 | { | |||
1193 | printf("%d\n", cpuid->model); | |||
1194 | } | |||
1195 | else if (!strncmp(argv[1], "-stepping", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-stepping") && strlen ("-stepping" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-stepping") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-stepping"), (!((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("-stepping") + 1) - (size_t)(const void *)("-stepping") == 1) || __s2_len >= 4 )) ? __builtin_strcmp (argv[1], "-stepping") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ( "-stepping") && ((size_t)(const void *)(("-stepping") + 1) - (size_t)(const void *)("-stepping") == 1) ? __builtin_strcmp (argv[1], "-stepping") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-stepping") ; int __result = (((const unsigned char *) (const char *) (argv [1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv [1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv [1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv [1]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("-stepping") && ((size_t)(const void *)(("-stepping" ) + 1) - (size_t)(const void *)("-stepping") == 1) && (__s2_len = strlen ("-stepping"), __s2_len < 4) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) ? __builtin_strcmp (argv [1], "-stepping") : (- (__extension__ ({ const unsigned char * __s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) (const char *) ("-stepping"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-stepping"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-stepping"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-stepping"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (argv[1], "-stepping")))); }) : strncmp (argv[1], "-stepping", 3)))) | |||
1196 | { | |||
1197 | printf("%d\n", cpuid->stepping); | |||
1198 | } | |||
1199 | else if (!strncmp(argv[1], "-features", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-features") && strlen ("-features" ) < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-features") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-features"), (!((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("-features") + 1) - (size_t)(const void *)("-features") == 1) || __s2_len >= 4 )) ? __builtin_strcmp (argv[1], "-features") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ( "-features") && ((size_t)(const void *)(("-features") + 1) - (size_t)(const void *)("-features") == 1) ? __builtin_strcmp (argv[1], "-features") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-features") ; int __result = (((const unsigned char *) (const char *) (argv [1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv [1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv [1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv [1]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("-features") && ((size_t)(const void *)(("-features" ) + 1) - (size_t)(const void *)("-features") == 1) && (__s2_len = strlen ("-features"), __s2_len < 4) ? (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) ? __builtin_strcmp (argv [1], "-features") : (- (__extension__ ({ const unsigned char * __s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) (const char *) ("-features"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-features"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-features"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-features"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (argv[1], "-features")))); }) : strncmp (argv[1], "-features", 3)))) | |||
1200 | { | |||
1201 | cnt = 0; | |||
1202 | for (i = 0; i < GMX_CPUID_NFEATURES; i++) | |||
1203 | { | |||
1204 | if (cpuid->feature[i] == 1) | |||
1205 | { | |||
1206 | if (cnt++ > 0) | |||
1207 | { | |||
1208 | printf(" "); | |||
1209 | } | |||
1210 | printf("%s", gmx_cpuid_feature_string[i]); | |||
1211 | } | |||
1212 | } | |||
1213 | printf("\n"); | |||
1214 | } | |||
1215 | else if (!strncmp(argv[1], "-simd", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p (argv[1]) && strlen (argv[1]) < ((size_t) (3))) || (__builtin_constant_p ("-simd") && strlen ("-simd") < ((size_t) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len ; (__builtin_constant_p (argv[1]) && __builtin_constant_p ("-simd") && (__s1_len = strlen (argv[1]), __s2_len = strlen ("-simd"), (!((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("-simd") + 1) - (size_t)(const void *)("-simd") == 1) || __s2_len >= 4)) ? __builtin_strcmp ( argv[1], "-simd") : (__builtin_constant_p (argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - (size_t)(const void *)(argv[1]) == 1) && (__s1_len = strlen (argv[1]), __s1_len < 4) ? (__builtin_constant_p ("-simd") && ((size_t )(const void *)(("-simd") + 1) - (size_t)(const void *)("-simd" ) == 1) ? __builtin_strcmp (argv[1], "-simd") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("-simd"); int __result = (((const unsigned char *) ( const char *) (argv[1]))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (argv[1]))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (argv[1]))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("-simd") && ((size_t)(const void *)(("-simd") + 1) - (size_t)(const void *)("-simd") == 1) && (__s2_len = strlen ("-simd"), __s2_len < 4) ? (__builtin_constant_p ( argv[1]) && ((size_t)(const void *)((argv[1]) + 1) - ( size_t)(const void *)(argv[1]) == 1) ? __builtin_strcmp (argv [1], "-simd") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (argv[1]); int __result = (((const unsigned char *) (const char *) ("-simd"))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-simd"))[1] - __s2 [1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("-simd"))[2] - __s2 [2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("-simd"))[3] - __s2 [3]); } } __result; })))) : __builtin_strcmp (argv[1], "-simd" )))); }) : strncmp (argv[1], "-simd", 3)))) | |||
1216 | { | |||
1217 | simd = gmx_cpuid_simd_suggest(cpuid); | |||
1218 | fprintf(stdoutstdout, "%s\n", gmx_cpuid_simd_string[simd]); | |||
1219 | } | |||
1220 | ||||
1221 | gmx_cpuid_done(cpuid); | |||
1222 | ||||
1223 | ||||
1224 | return 0; | |||
1225 | } | |||
1226 | ||||
1227 | #endif |