Skip to content

Commit 1cafde2

Browse files
[clang][X86] Add __cpuidex function to cpuid.h (llvm#97785)
MSVC has a __cpuidex function implemented to call the underlying cpuid instruction which accepts a leaf, subleaf, and data array that the output data is written into. This patch adds this functionality into clang under the cpuid.h header. This also makes clang match GCC's behavior. GCC has had __cpuidex in its cpuid.h since 2020. This is another attempt to land https://reviews.llvm.org/D158348.
1 parent ce4aada commit 1cafde2

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

clang/lib/Headers/cpuid.h

+9
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,13 @@ static __inline int __get_cpuid_count (unsigned int __leaf,
339339
return 1;
340340
}
341341

342+
// In some configurations, __cpuidex is defined as a builtin (primarily
343+
// -fms-extensions) which will conflict with the __cpuidex definition below.
344+
#if !(__has_builtin(__cpuidex))
345+
static __inline void __cpuidex(int __cpu_info[4], int __leaf, int __subleaf) {
346+
__cpuid_count(__leaf, __subleaf, __cpu_info[0], __cpu_info[1], __cpu_info[2],
347+
__cpu_info[3]);
348+
}
349+
#endif
350+
342351
#endif /* __CPUID_H */
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Make sure that __cpuidex in cpuid.h doesn't conflict with the MS
2+
// extensions built in by ensuring compilation succeeds:
3+
// RUN: %clang_cc1 %s -ffreestanding -fms-extensions -fms-compatibility \
4+
// RUN: -fms-compatibility-version=19.00 -triple x86_64-pc-windows-msvc -emit-llvm -o -
5+
// %clang_cc1 %s -ffreestanding -triple x86_64-w64-windows-gnu -fms-extensions -emit-llvm -o -
6+
// RUN: %clang_cc1 %s -ffreestanding -fopenmp -fopenmp-is-target-device -aux-triple x86_64-unknown-linux-gnu
7+
8+
typedef __SIZE_TYPE__ size_t;
9+
10+
// We declare __cpuidex here as where the buitlin should be exposed (MSVC), the
11+
// declaration is in <intrin.h>, but <intrin.h> is not available from all the
12+
// targets that are being tested here.
13+
void __cpuidex (int[4], int, int);
14+
15+
#include <cpuid.h>
16+
17+
int cpuid_info[4];
18+
19+
void test_cpuidex(unsigned level, unsigned count) {
20+
__cpuidex(cpuid_info, level, count);
21+
}
22+

clang/test/Headers/cpuid.c

+5
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@
66

77
// CHECK-64: {{.*}} call { i32, i32, i32, i32 } asm " xchgq %rbx,${1:q}\0A cpuid\0A xchgq %rbx,${1:q}", "={ax},=r,={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}})
88
// CHECK-64: {{.*}} call { i32, i32, i32, i32 } asm " xchgq %rbx,${1:q}\0A cpuid\0A xchgq %rbx,${1:q}", "={ax},=r,={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
9+
// CHECK-64: {{.*}} call { i32, i32, i32, i32 } asm " xchgq %rbx,${1:q}\0A cpuid\0A xchgq %rbx,${1:q}", "={ax},=r,={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
910

1011
// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}})
1112
// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
13+
// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}}, i32 %{{[a-z0-9]+}})
1214

1315
unsigned eax0, ebx0, ecx0, edx0;
1416
unsigned eax1, ebx1, ecx1, edx1;
1517

18+
int cpuid_info[4];
19+
1620
void test_cpuid(unsigned level, unsigned count) {
1721
__cpuid(level, eax1, ebx1, ecx1, edx1);
1822
__cpuid_count(level, count, eax0, ebx0, ecx0, edx0);
23+
__cpuidex(cpuid_info, level, count);
1924
}

0 commit comments

Comments
 (0)