-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Conversation
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.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-backend-x86 Author: Aiden Grossman (boomanaiden154) ChangesMSVC 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:
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);
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
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. |
There was a problem hiding this 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
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 is another attempt to land https://reviews.llvm.org/D158348.