1dnl Tries to determine appropriate function names for 2dnl fused multiply-add (fma) and fused multiply-subtract (fms). 3dnl 4dnl Usage: ACX_CXX_FMA(list) 5dnl where fma_list can contain any of ibm, c99. If list is 6dnl blank it will search for a first compatible function. 7dnl 8AC_DEFUN([AX_CXX_FMA], [ 9AC_MSG_CHECKING([for fused multiply-add/subtract]) 10AC_LANG_PUSH(C++) 11ax_cxx_fma_list=$1 12if test "x$ax_cxx_fma_list" = "x"; then 13 ax_cxx_fma_list="ibm gnu c99 compiler" 14fi 15ax_cxx_fma= 16ax_cxx_fms= 17for name in $ax_cxx_fma_list; do 18 if test "x$ax_cxx_fma" = "x"; then 19 case $name in 20 ibm) 21 # IBM VisualAge C++ __fmadd / __fmsub. 22 AC_RUN_IFELSE([AC_LANG_SOURCE([#include <cmath> 23 #include <builtins.h> 24 int main() { 25 double d = std::ldexp(1.0, -52); 26 double x = __fmadd(1.0 + d, 1.0 - d, -1.0); 27 double y = __fmsub(1.0 + d, 1.0 - d, 1.0); 28 return (x == -d*d && y == -d*d) ? 0 : 1; 29 }])], 30 [ax_cxx_fma="__fmadd(x,y,z)" 31 ax_cxx_fms="__fmsub(x,y,z)" 32 AC_DEFINE([QD_VACPP_BUILTINS_H], [1], 33 [Set to 1 if using VisualAge C++ compiler for __fmadd builtin.])]) 34 ;; 35 gnu) 36 # Later gcc (3.4 and later) have __builtin_fma that seems to work. 37 AC_RUN_IFELSE([AC_LANG_SOURCE([#include <cmath> 38 int main() { 39 double d = std::ldexp(1.0, -52); 40 return (__builtin_fma(1.0 + d, 1.0 - d, -1.0) == -d*d ? 0 : 1); 41 }])], 42 [ax_cxx_fma="__builtin_fma(x,y,z)" 43 ax_cxx_fms="__builtin_fma(x,y,-z)"]) 44 ;; 45 ia64) 46 # Intel and HP compilers for IA 64 architecture seems to have 47 # _Asm_fma/fms macros. Not much documentation is available for 48 # these... 49 AC_RUN_IFELSE([AC_LANG_SOURCE([#include <cmath> 50 int main() { 51 double d = std::ldexp(1.0, -52); 52 return (_Asm_fma(2, 1.0 + d, 1.0 - d, -1.0) == -d*d ? 0 : 1); 53 }])], 54 [ax_cxx_fma="_Asm_fma(2, x,y,z)" 55 ax_cxx_fms="_Asm_fms(2, x,y,z)"]) 56 ;; 57 c99) 58 # Try C99 fma() function. Some platforms doesn't seem to implement this 59 # correctly (Apple gcc-3.3 for example). 60 AC_RUN_IFELSE([AC_LANG_SOURCE([#include <cmath> 61 int main() { 62 double d = std::ldexp(1.0, -52); 63 return (fma(1.0 + d, 1.0 - d, -1.0) == -d*d ? 0 : 1); 64 }])], 65 [ax_cxx_fma="fma(x,y,z)" 66 ax_cxx_fms="fma(x,y,-z)"]) 67 ;; 68 compiler) 69 # Try relying on the compiler to optimize x * y + z into an fma. 70 # This method is not recommended since if it is inlined it does not 71 # always produce the same correct code. 72 AC_RUN_IFELSE([AC_LANG_SOURCE([#include <cmath> 73 int main() { 74 double d = std::ldexp(1.0, -52); 75 return ( (1.0 + d) * (1.0 - d) - 1.0 == -d*d ? 0 : 1); 76 }])], 77 [ax_cxx_fma="((x)*(y) + (z))" 78 ax_cxx_fms="((x)*(y) - (z))"]) 79 ;; 80 *) AC_MSG_ERROR([Unknown option $name to --enable-fma.]) ;; 81 esac 82 fi 83done 84AC_LANG_POP(C++) 85if test "x$ax_cxx_fma" != "x"; then 86 AC_MSG_RESULT([$ax_cxx_fma, $ax_cxx_fms]) 87else 88 AC_MSG_RESULT(none) 89fi 90]) 91