summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Dickens <mlk@alum.mit.edu>2013-08-27 13:02:57 -0400
committerTom Rondeau <tom@trondeau.com>2013-08-27 13:02:57 -0400
commit48fe4d89f22e8e9db7d01830e57e6868cfdaf4e4 (patch)
treee1f8a25e36dd01f2f99b8e0b6e35c6d0763ef4de
parent335f0dfc0e79c7019956645937ceba487437ae8d (diff)
volk: tests if xgetbv (an avx instruction) is really, truly available. Allows us to build on OSX with GCC.
-rw-r--r--volk/lib/CMakeLists.txt31
-rw-r--r--volk/tmpl/volk_cpu.tmpl.c2
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));