Bug Summary

File:gromacs/gmxlib/gmx_cpuid.c
Location:line 717, column 26
Description:Potential leak of memory pointed to by 'apic_id'

Annotated Source Code

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 */
74const char *
75gmx_cpuid_vendor_string[GMX_CPUID_NVENDORS] =
76{
77 "CannotDetect",
78 "Unknown",
79 "GenuineIntel",
80 "AuthenticAMD",
81 "Fujitsu",
82 "IBM"
83};
84
85const char *
86gmx_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
96const char *
97gmx_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
136const char *
137gmx_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 */
156struct 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 */
185enum gmx_cpuid_vendor
186gmx_cpuid_vendor (gmx_cpuid_t cpuid)
187{
188 return cpuid->vendor;
189}
190
191
192const char *
193gmx_cpuid_brand (gmx_cpuid_t cpuid)
194{
195 return cpuid->brand;
196}
197
198int
199gmx_cpuid_family (gmx_cpuid_t cpuid)
200{
201 return cpuid->family;
202}
203
204int
205gmx_cpuid_model (gmx_cpuid_t cpuid)
206{
207 return cpuid->model;
208}
209
210int
211gmx_cpuid_stepping (gmx_cpuid_t cpuid)
212{
213 return cpuid->stepping;
214}
215
216int
217gmx_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
228static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX2_256;
229#elif defined GMX_SIMD_X86_AVX_256
230static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX_256;
231#elif defined GMX_SIMD_X86_AVX_128_FMA
232static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_AVX_128_FMA;
233#elif defined GMX_SIMD_X86_SSE4_1
234static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_SSE4_1;
235#elif defined GMX_SIMD_X86_SSE2
236static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_X86_SSE2;
237#elif defined GMX_SIMD_SPARC64_HPC_ACE
238static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_SPARC64_HPC_ACE;
239#elif defined GMX_SIMD_IBM_QPX
240static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_IBM_QPX;
241#elif defined GMX_SIMD_REFERENCE
242static const enum gmx_cpuid_simd compiled_simd = GMX_CPUID_SIMD_REFERENCE;
243#else
244static 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 */
257static int
258execute_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 */
328static int
329cpuid_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 */
432static int
433cpuid_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 */
481static int
482cpuid_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 */
529static int
530cpuid_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 */
622static int
623cpuid_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)
1
Assuming 'max_stdfn' is >= 1
2
Taking true branch
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)
3
Assuming 'max_stdfn' is >= 7
4
Taking true branch
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)
5
Assuming 'max_stdfn' is >= 11
6
Taking true branch
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);
7
Memory is allocated
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++)
8
Loop condition is false. Execution continues on line 690
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,
9
Potential leak of memory pointed to by 'apic_id'
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
729static void
730chomp_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
749static void
750chomp_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 */
776static enum gmx_cpuid_vendor
777cpuid_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
841int
842gmx_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
874enum gmx_cpuid_x86_smt
875gmx_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
895int
896gmx_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
972void
973gmx_cpuid_done (gmx_cpuid_t cpuid)
974{
975 free(cpuid);
976}
977
978
979int
980gmx_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
1040enum gmx_cpuid_simd
1041gmx_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
1100int
1101gmx_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 */
1154int
1155main(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