diff options
author | Tom Rondeau <tom@trondeau.com> | 2013-08-27 13:03:12 -0400 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2013-08-27 13:03:12 -0400 |
commit | 584f201d23e266400111dd24657b7f63868941b8 (patch) | |
tree | b1a124fde7f271107c2f57bd030e685d49a04a9c | |
parent | f8a150552f0659f07f2066241ced769cb279bdc5 (diff) | |
parent | 48fe4d89f22e8e9db7d01830e57e6868cfdaf4e4 (diff) |
Merge branch 'maint'
-rw-r--r-- | volk/lib/CMakeLists.txt | 31 | ||||
-rw-r--r-- | volk/tmpl/volk_cpu.tmpl.c | 2 |
2 files changed, 31 insertions, 2 deletions
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index 68fadc35b0..d2b3cb5a90 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -119,14 +119,43 @@ endmacro(OVERRULE_ARCH) ######################################################################## # eliminate AVX on GCC < 4.4 -# even though it accepts -mavx, as won't assemble xgetbv, which we need +# even though it accepts -mavx, as won't assemble xgetbv, which we need. +# even on GCC >= 4.4, verify that the compiler/linked accepts the xgetbv instruction, +# and if not cross-compiling verify that the executable runs cleanly. ######################################################################## if(CPU_IS_x86 AND COMPILER_NAME MATCHES "GNU") execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) if(GCC_VERSION VERSION_LESS "4.4") OVERRULE_ARCH(avx "GCC missing xgetbv") + else() + # check to make sure compiler/linker works with xgetb instruction + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "unsigned long long _xgetbv(unsigned int index) { unsigned int eax, edx; __asm__ __volatile__(\"xgetbv\" : \"=a\"(eax), \"=d\"(edx) : \"c\"(index)); return ((unsigned long long)edx << 32) | eax; } int main (void) { (void) _xgetbv(0); return (0); }") + execute_process(COMMAND ${CMAKE_C_COMPILER} -o + ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv + ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE avx_compile_result) + if(NOT ${avx_compile_result} EQUAL 0) + OVERRULE_ARCH(avx "Compiler or linker missing xgetbv instruction") + elseif(NOT CROSSCOMPILE_MULTILIB) + execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE avx_exe_result) + if(NOT ${avx_exe_result} EQUAL 0) + OVERRULE_ARCH(avx "CPU missing xgetbv.") + else() + add_definitions(-DHAVE_XGETBV) + endif() + else() + # cross compiling and compiler/linker seems to work; assume working + add_definitions(-DHAVE_XGETBV) + endif() + file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv + ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c) endif() +else() + OVERRULE_ARCH(avx "Not using GCC; assuming no xgetbv") endif() ######################################################################## diff --git a/volk/tmpl/volk_cpu.tmpl.c b/volk/tmpl/volk_cpu.tmpl.c index b1a0a4afe1..71f42f220d 100644 --- a/volk/tmpl/volk_cpu.tmpl.c +++ b/volk/tmpl/volk_cpu.tmpl.c @@ -44,7 +44,7 @@ struct VOLK_CPU volk_cpu; * This function will bomb on non-AVX-capable machines, so * check for AVX capability before executing. */ - #if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 + #if (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4) && defined(HAVE_XGETBV) static inline unsigned long long _xgetbv(unsigned int index){ unsigned int eax, edx; __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); |