-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement __cpuid and __cpuidex as Clang builtins
https://reviews.llvm.org/D23944 implemented the #pragma intrinsic from MSVC. This causes the statement #pragma intrinsic(cpuid) to fail [0] on Clang because cpuid is currently implemented in intrin.h instead of a Clang builtin. Reimplementing cpuid (as well as it's releated function, cpuidex) should resolve this. [0]: https://crbug.com/1279344 Differential revision: https://reviews.llvm.org/D121653
- Loading branch information
Showing
4 changed files
with
110 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,80 @@ | ||
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ | ||
// RUN: -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=X86 | ||
// RUN: -Werror -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=X86 | ||
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ | ||
// RUN: -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=X64 | ||
// RUN: -Werror -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=X64 | ||
|
||
// intrin.h needs size_t, but -ffreestanding prevents us from getting it from | ||
// stddef.h. Work around it with this typedef. | ||
typedef __SIZE_TYPE__ size_t; | ||
|
||
#include <intrin.h> | ||
|
||
void test__cpuid(int *info, int level) { | ||
__cpuid(info, level); | ||
#pragma intrinsic(__cpuid) | ||
|
||
void test__cpuid(int cpuInfo[4], int function_id) { | ||
__cpuid(cpuInfo, function_id); | ||
} | ||
// X86-LABEL: define {{.*}} @test__cpuid(i32* noundef %{{.*}}, i32 noundef %{{.*}}) | ||
// X86: call { i32, i32, i32, i32 } asm "cpuid", | ||
// X86-SAME: "={ax},={bx},={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}" | ||
// X86-SAME: (i32 %{{.*}}, i32 0) | ||
// X86-DAG: [[ASMRESULTS:%[0-9]+]] = call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},{ax},{cx}" | ||
// X86-DAG: [[ADDRPTR0:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 0 | ||
// X86-DAG: [[ADDRPTR1:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 1 | ||
// X86-DAG: [[ADDRPTR2:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 2 | ||
// X86-DAG: [[ADDRPTR3:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 3 | ||
// X86-DAG: [[RESULT0:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 | ||
// X86-DAG: [[RESULT1:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 | ||
// X86-DAG: [[RESULT2:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 | ||
// X86-DAG: [[RESULT3:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 | ||
// X86-DAG: store i32 [[RESULT0]], i32* [[ADDRPTR0]], align 4 | ||
// X86-DAG: store i32 [[RESULT1]], i32* [[ADDRPTR1]], align 4 | ||
// X86-DAG: store i32 [[RESULT2]], i32* [[ADDRPTR2]], align 4 | ||
// X86-DAG: store i32 [[RESULT3]], i32* [[ADDRPTR3]], align 4 | ||
|
||
// X64-LABEL: define {{.*}} @test__cpuid(i32* noundef %{{.*}}, i32 noundef %{{.*}}) | ||
// X64: call { i32, i32, i32, i32 } asm "xchg$(q$) $(%rbx{{.*}}$){{.*}}cpuid{{.*}}xchg$(q$) $(%rbx{{.*}}$)", | ||
// X64-SAME: "={ax},=r,={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}" | ||
// X64-SAME: (i32 %{{.*}}, i32 0) | ||
// X64-DAG: [[ASMRESULTS:%[0-9]+]] = call { i32, i32, i32, i32 } asm "xchgq %rbx, ${1:q}\0Acpuid\0Axchgq %rbx, ${1:q}", "={ax},=r,={cx},={dx},0,2" | ||
// X64-DAG: [[ADDRPTR0:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 0 | ||
// X64-DAG: [[ADDRPTR1:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 1 | ||
// X64-DAG: [[ADDRPTR2:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 2 | ||
// X64-DAG: [[ADDRPTR3:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 3 | ||
// X64-DAG: [[RESULT0:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 | ||
// X64-DAG: [[RESULT1:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 | ||
// X64-DAG: [[RESULT2:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 | ||
// X64-DAG: [[RESULT3:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 | ||
// X64-DAG: store i32 [[RESULT0]], i32* [[ADDRPTR0]], align 4 | ||
// X64-DAG: store i32 [[RESULT1]], i32* [[ADDRPTR1]], align 4 | ||
// X64-DAG: store i32 [[RESULT2]], i32* [[ADDRPTR2]], align 4 | ||
// X64-DAG: store i32 [[RESULT3]], i32* [[ADDRPTR3]], align 4 | ||
|
||
#pragma intrinsic(__cpuidex) | ||
|
||
void test__cpuidex(int cpuInfo[4], int function_id, int subfunction_id) { | ||
__cpuidex(cpuInfo, function_id, subfunction_id); | ||
} | ||
// X86-LABEL: define {{.*}} @test__cpuidex(i32* noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) | ||
// X86-DAG: [[ASMRESULTS:%[0-9]+]] = call { i32, i32, i32, i32 } asm "cpuid", "={ax},={bx},={cx},={dx},{ax},{cx}" | ||
// X86-DAG: [[ADDRPTR0:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 0 | ||
// X86-DAG: [[ADDRPTR1:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 1 | ||
// X86-DAG: [[ADDRPTR2:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 2 | ||
// X86-DAG: [[ADDRPTR3:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 3 | ||
// X86-DAG: [[RESULT0:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 | ||
// X86-DAG: [[RESULT1:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 | ||
// X86-DAG: [[RESULT2:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 | ||
// X86-DAG: [[RESULT3:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 | ||
// X86-DAG: store i32 [[RESULT0]], i32* [[ADDRPTR0]], align 4 | ||
// X86-DAG: store i32 [[RESULT1]], i32* [[ADDRPTR1]], align 4 | ||
// X86-DAG: store i32 [[RESULT2]], i32* [[ADDRPTR2]], align 4 | ||
// X86-DAG: store i32 [[RESULT3]], i32* [[ADDRPTR3]], align 4 | ||
|
||
// X64-LABEL: define {{.*}} @test__cpuidex(i32* noundef %{{.*}}, i32 noundef %{{.*}}, i32 noundef %{{.*}}) | ||
// X64-DAG: [[ASMRESULTS:%[0-9]+]] = call { i32, i32, i32, i32 } asm "xchgq %rbx, ${1:q}\0Acpuid\0Axchgq %rbx, ${1:q}", "={ax},=r,={cx},={dx},0,2" | ||
// X64-DAG: [[ADDRPTR0:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 0 | ||
// X64-DAG: [[ADDRPTR1:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 1 | ||
// X64-DAG: [[ADDRPTR2:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 2 | ||
// X64-DAG: [[ADDRPTR3:%[0-9]+]] = getelementptr inbounds i32, i32* %{{.*}}, i32 3 | ||
// X64-DAG: [[RESULT0:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 0 | ||
// X64-DAG: [[RESULT1:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 1 | ||
// X64-DAG: [[RESULT2:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 2 | ||
// X64-DAG: [[RESULT3:%[0-9]+]] = extractvalue { i32, i32, i32, i32 } [[ASMRESULTS]], 3 | ||
// X64-DAG: store i32 [[RESULT0]], i32* [[ADDRPTR0]], align 4 | ||
// X64-DAG: store i32 [[RESULT1]], i32* [[ADDRPTR1]], align 4 | ||
// X64-DAG: store i32 [[RESULT2]], i32* [[ADDRPTR2]], align 4 | ||
// X64-DAG: store i32 [[RESULT3]], i32* [[ADDRPTR3]], align 4 |