diff --git a/builtins/dispatch.ll b/builtins/dispatch.ll index 10ba05a8..e61292aa 100644 --- a/builtins/dispatch.ll +++ b/builtins/dispatch.ll @@ -48,23 +48,42 @@ declare void @abort() noreturn ;; corresponding to one of the Target::ISA enumerant values that gives the ;; most capable ISA that the curremt system can run. ;; -;; #ifdef _MSC_VER -;; extern void __stdcall __cpuid(int info[4], int infoType); -;; #else +;; Note: clang from LLVM 2.9 should be used if this is updated, for maximum +;; backwards compatibility for anyone building ispc with LLVM 2.9. +;; +;; #include +;; #include +;; ;; static void __cpuid(int info[4], int infoType) { ;; __asm__ __volatile__ ("cpuid" ;; : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3]) ;; : "0" (infoType)); ;; } -;; #endif +;; +;; /* Save %ebx in case it's the PIC register */ +;; static void __cpuid_count(int info[4], int level, int count) { +;; __asm__ __volatile__ ("xchg{l}\t{%%}ebx, %1\n\t" +;; "cpuid\n\t" +;; "xchg{l}\t{%%}ebx, %1\n\t" +;; : "=a" (info[0]), "=r" (info[1]), "=c" (info[2]), "=d" (info[3]) +;; : "0" (level), "2" (count)); +;; } ;; ;; int32_t __get_system_isa() { ;; int info[4]; ;; __cpuid(info, 1); +;; ;; /* NOTE: the values returned below must be the same as the ;; corresponding enumerant values in Target::ISA. */ -;; if ((info[2] & (1 << 28)) != 0) -;; return 2; // AVX +;; if ((info[2] & (1 << 28)) != 0) { +;; // AVX1 for sure. Do we have AVX2? +;; // Call cpuid with eax=7, ecx=0 +;; __cpuid_count(info, 7, 0); +;; if ((info[1] & (1 << 5)) != 0) +;; return 3; // AVX2 +;; else +;; return 2; // AVX1 +;; } ;; else if ((info[2] & (1 << 19)) != 0) ;; return 1; // SSE4 ;; else if ((info[3] & (1 << 26)) != 0) @@ -76,33 +95,42 @@ declare void @abort() noreturn %0 = type { i32, i32, i32, i32 } define i32 @__get_system_isa() nounwind ssp { - %1 = tail call %0 asm sideeffect "cpuid", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 1) nounwind - %2 = extractvalue %0 %1, 2 - %3 = extractvalue %0 %1, 3 - %4 = and i32 %2, 268435456 - %5 = icmp eq i32 %4, 0 - br i1 %5, label %6, label %13 +entry: + %0 = tail call %0 asm sideeffect "cpuid", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 1) nounwind + %asmresult9.i = extractvalue %0 %0, 2 + %asmresult10.i = extractvalue %0 %0, 3 + %and = and i32 %asmresult9.i, 268435456 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %if.else7, label %if.then -;