Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][X86] Add __cpuidex function to cpuid.h #97785

Merged
merged 2 commits into from
Jul 11, 2024

Conversation

boomanaiden154
Copy link
Contributor

@boomanaiden154 boomanaiden154 commented Jul 5, 2024

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.

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 patch diverges from the gcc behavior slightly bynot marking
__cpuidex as static. If __cpuidex is marked as static, then this differs
from the signature used by MSVC (or at least what clang uses for MSVC),
which can cause include ordering issues if intrin.h (which contains a
declaration for __cpuidex) occurs before cpuid.h is included.
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics labels Jul 5, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 5, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-x86

Author: Aiden Grossman (boomanaiden154)

Changes

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 patch diverges from the gcc behavior slightly bynot marking __cpuidex as static. If __cpuidex is marked as static, then this differs from the signature used by MSVC (or at least what clang uses for MSVC), which can cause include ordering issues if intrin.h (which contains a declaration for __cpuidex) occurs before cpuid.h is included.

This is another attempt to land https://reviews.llvm.org/D158348.


Full diff: https://github.com/llvm/llvm-project/pull/97785.diff

3 Files Affected:

  • (modified) clang/lib/Headers/cpuid.h (+10)
  • (added) clang/test/Headers/__cpuidex_conflict.c (+22)
  • (modified) clang/test/Headers/cpuid.c (+5)
diff --git a/clang/lib/Headers/cpuid.h b/clang/lib/Headers/cpuid.h
index bb7692efb78ffe..cd55410cda8b7c 100644
--- a/clang/lib/Headers/cpuid.h
+++ b/clang/lib/Headers/cpuid.h
@@ -339,4 +339,14 @@ static __inline int __get_cpuid_count (unsigned int __leaf,
     return 1;
 }
 
+// In some configurations, __cpuidex is defined as a builtin (primarily
+// -fms-extensions) which will conflict with the __cpuidex definition below.
+#if !(__has_builtin(__cpuidex))
+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 */
diff --git a/clang/test/Headers/__cpuidex_conflict.c b/clang/test/Headers/__cpuidex_conflict.c
new file mode 100644
index 00000000000000..8687a6aa2f897a
--- /dev/null
+++ b/clang/test/Headers/__cpuidex_conflict.c
@@ -0,0 +1,22 @@
+// Make sure that __cpuidex in cpuid.h doesn't conflict with the MS
+// extensions 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 -
+// %clang_cc1 %s -ffreestanding -triple x86_64-w64-windows-gnu -fms-extensions -emit-llvm -o -
+// RUN: %clang_cc1 %s -ffreestanding -fopenmp -fopenmp-is-target-device -aux-triple x86_64-unknown-linux-gnu
+
+typedef __SIZE_TYPE__ size_t;
+
+// We declare __cpuidex here as where the buitlin should be exposed (MSVC), the
+// declaration is in <intrin.h>, but <intrin.h> is not available from all the
+// targets that are being tested here.
+void __cpuidex (int[4], int, int);
+
+#include <cpuid.h>
+
+int cpuid_info[4];
+
+void test_cpuidex(unsigned level, unsigned count) {
+  __cpuidex(cpuid_info, level, count);
+}
+
diff --git a/clang/test/Headers/cpuid.c b/clang/test/Headers/cpuid.c
index 7e485495c10665..6ed12eca7a61d4 100644
--- a/clang/test/Headers/cpuid.c
+++ b/clang/test/Headers/cpuid.c
@@ -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);
 }

Copy link

github-actions bot commented Jul 5, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@mstorsjo
Copy link
Member

mstorsjo commented Jul 5, 2024

Thanks - I think this is fine with me. In mingw-w64/mingw-w64@a4c0c1d we adjusted the mingw-w64 headers in anticipation that this gets merged in Clang 19, so it'd be good to have it settled before the 19.x branch gets made.

@boomanaiden154
Copy link
Contributor Author

Thanks - I think this is fine with me. In mingw-w64/mingw-w64@a4c0c1d we adjusted the mingw-w64 headers in anticipation that this gets merged in Clang 19, so it'd be good to have it settled before the 19.x branch gets made.

Sounds good. Assuming there aren't any objections, I'll try and land this on Wednesday given it's just a reland, has been approved in the past, and the remaining (identified) issues have been signed off on phabricator. That should give time in case anyone has comments but still give a reasonable enough time frame to ensure it sticks for clang 19.

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let’s reland this

@boomanaiden154 boomanaiden154 merged commit 1cafde2 into llvm:main Jul 11, 2024
4 of 6 checks passed
@boomanaiden154 boomanaiden154 deleted the cpuidex-in-clang branch July 11, 2024 22:57
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants