diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/TargetParser/Host.cpp | 98 |
1 files changed, 18 insertions, 80 deletions
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp index 7e637cb..0803521 100644 --- a/llvm/lib/TargetParser/Host.cpp +++ b/llvm/lib/TargetParser/Host.cpp @@ -50,6 +50,11 @@ #if defined(__sun__) && defined(__svr4__) #include <kstat.h> #endif +#if defined(__GNUC__) || defined(__clang__) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER) +#include <cpuid.h> +#endif +#endif #define DEBUG_TYPE "host-detection" @@ -522,68 +527,15 @@ StringRef sys::detail::getHostCPUNameForBPF() { #endif } -#if defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64) - -// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). -// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID -// support. Consequently, for i386, the presence of CPUID is checked first -// via the corresponding eflags bit. -// Removal of cpuid.h header motivated by PR30384 -// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp -// or test-suite, but are used in external projects e.g. libstdcxx -static bool isCpuIdSupported() { -#if defined(__GNUC__) || defined(__clang__) -#if defined(__i386__) - int __cpuid_supported; - __asm__(" pushfl\n" - " popl %%eax\n" - " movl %%eax,%%ecx\n" - " xorl $0x00200000,%%eax\n" - " pushl %%eax\n" - " popfl\n" - " pushfl\n" - " popl %%eax\n" - " movl $0,%0\n" - " cmpl %%eax,%%ecx\n" - " je 1f\n" - " movl $1,%0\n" - "1:" - : "=r"(__cpuid_supported) - : - : "eax", "ecx"); - if (!__cpuid_supported) - return false; -#endif - return true; -#endif - return true; -} +#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \ + defined(_M_X64) /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in /// the specified arguments. If we can't run cpuid on the host, return true. static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { -#if defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) - // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. - // FIXME: should we save this for Clang? - __asm__("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value)); - return false; -#elif defined(__i386__) - __asm__("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value)); - return false; -#else - return true; -#endif +#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER) + return !__get_cpuid(value, rEAX, rEBX, rECX, rEDX); #elif defined(_MSC_VER) // The MSVC intrinsic is portable across x86 and x64. int registers[4]; @@ -610,9 +562,6 @@ VendorSignatures getVendorSignature(unsigned *MaxLeaf) { else *MaxLeaf = 0; - if (!isCpuIdSupported()) - return VendorSignatures::UNKNOWN; - if (getX86CpuIDAndInfo(0, MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1) return VendorSignatures::UNKNOWN; @@ -640,26 +589,12 @@ using namespace llvm::sys::detail::x86; static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, unsigned *rEAX, unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { -#if defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) - // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. - // FIXME: should we save this for Clang? - __asm__("movq\t%%rbx, %%rsi\n\t" - "cpuid\n\t" - "xchgq\t%%rbx, %%rsi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value), "c"(subleaf)); - return false; -#elif defined(__i386__) - __asm__("movl\t%%ebx, %%esi\n\t" - "cpuid\n\t" - "xchgl\t%%ebx, %%esi\n\t" - : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) - : "a"(value), "c"(subleaf)); - return false; -#else - return true; -#endif + // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang + // are such that __cpuidex is defined within cpuid.h for both, we can remove + // the __get_cpuid_count function and share the MSVC implementation between + // all three. +#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER) + return !__get_cpuid_count(value, subleaf, rEAX, rEBX, rECX, rEDX); #elif defined(_MSC_VER) int registers[4]; __cpuidex(registers, value, subleaf); @@ -675,6 +610,9 @@ static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, // Read control register 0 (XCR0). Used to detect features such as AVX. static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { + // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang + // are such that _xgetbv is supported by both, we can unify the implementation + // with MSVC and remove all inline assembly. #if defined(__GNUC__) || defined(__clang__) // Check xgetbv; this uses a .byte sequence instead of the instruction // directly because older assemblers do not include support for xgetbv and |