Skip to content

Commit

Permalink
[clang][X86] Add __cpuidex function to cpuid.h
Browse files Browse the repository at this point in the history
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.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D150646
  • Loading branch information
boomanaiden154 committed May 24, 2023
1 parent d1a5b02 commit 2df77ac
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
10 changes: 10 additions & 0 deletions clang/lib/Headers/cpuid.h
Expand Up @@ -328,4 +328,14 @@ static __inline int __get_cpuid_count (unsigned int __leaf,
return 1;
}

// If MS extensions are enabled, __cpuidex is defined as a builtin which will
// conflict with the __cpuidex definition below.
#ifndef _MSC_EXTENSIONS
static __inline void __cpuidex (int __cpu_info[4], int __leaf, int __subleaf)
{
__cpuid_count(__leaf, __subleaf, __cpu_info[0], __cpu_info[1], __cpu_info[2],
__cpu_info[3]);
}
#endif

#endif /* __CPUID_H */
15 changes: 15 additions & 0 deletions clang/test/Headers/__cpuidex_conflict.c
@@ -0,0 +1,15 @@
// Make sure that __cpuidex in cpuid.h doesn't conflict with the MS
// compatibility built in by ensuring compilation succeeds:
// RUN: %clang_cc1 %s -ffreestanding -fms-extensions -fms-compatibility \
// RUN: -fms-compatibility-version=19.00 -triple x86_64-pc-windows-msvc -emit-llvm -o -

typedef __SIZE_TYPE__ size_t;

#include <intrin.h>
#include <cpuid.h>

int cpuid_info[4];

void test_cpuidex(unsigned level, unsigned count) {
__cpuidex(cpuid_info, level, count);
}
5 changes: 5 additions & 0 deletions clang/test/Headers/cpuid.c
Expand Up @@ -6,14 +6,19 @@

// 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]+}})
// 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]+}})
// 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]+}})

// CHECK-32: {{.*}} call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %{{[a-z0-9]+}})
// 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]+}})
// 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]+}})

unsigned eax0, ebx0, ecx0, edx0;
unsigned eax1, ebx1, ecx1, edx1;

int cpuid_info[4];

void test_cpuid(unsigned level, unsigned count) {
__cpuid(level, eax1, ebx1, ecx1, edx1);
__cpuid_count(level, count, eax0, ebx0, ecx0, edx0);
__cpuidex(cpuid_info, level, count);
}

0 comments on commit 2df77ac

Please sign in to comment.