[m-rev.] for review: add support for fused multiply-add to math module
Julien Fischer
jfischer at opturion.com
Mon Jul 21 13:06:56 AEST 2014
Branches: main
Add the fused multiply-add operation to the math module.
Support the fused multiply-add operation in C grades, where the underlying math
library provides it. Add a predicate that allows program to test for the
presence of this operation.
(The non-C target languages do not currently provide this operation.)
library/math.m:
Add the function fma/3.
Add the predicate have_fma/0 which can be used to test for the
presence of fma operation in the current grade / platform.
configure.ac:
runtime/mercury_conf.h.in:
Check whether the C99 fma() function is available.
NEWS:
Announce the above.
Julien.
diff --git a/NEWS b/NEWS
index 0091a92..ad80d04 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,9 @@ Changes to the Mercury standard library:
* We have added thread.spawn_native/4 to dedicate an OS thread to a Mercury
thread. thread.spawn/4 was added as well.
+* In C grades, the math module now provides the fused multiply-add operation
+ on platforms that support it.
+
Changes to the Mercury compiler:
* We have fixed a long-standing bug causing crashes in deep profiling
diff --git a/configure.ac b/configure.ac
index 545ec3a..7138f2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1287,7 +1287,8 @@ mercury_check_for_functions \
grantpt unlockpt ptsname tcgetattr tcsetattr ioctl \
access sleep opendir readdir closedir mkdir symlink readlink \
gettimeofday setenv putenv _putenv posix_spawn sched_setaffinity \
- sched_getaffinity sched_getcpu sched_yield mkstemp setrlimit
+ sched_getaffinity sched_getcpu sched_yield mkstemp setrlimit \
+ fma
#-----------------------------------------------------------------------------#
diff --git a/library/math.m b/library/math.m
index 78c22d3..3546ae7 100644
--- a/library/math.m
+++ b/library/math.m
@@ -203,6 +203,25 @@
:- func math.tanh(float) = float.
%---------------------------------------------------------------------------%
+%
+% Fused multiply-add operation.
+%
+
+ % Succeeds if this grade and platform provide the fused multiply-add
+ % operation.
+ %
+:- pred math.have_fma is semidet.
+
+ % fma(X, Y, Z) = FMA is true if FMA = (X * Y) + Z, rounded as one
+ % floating-point operation.
+ %
+ % This function is (currently) only available on the C backends and only if
+ % the target math library supports it.
+ % Use have_fma/0 to check whether it is supported.
+ %
+:- func math.fma(float, float, float) = float.
+
+%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
@@ -999,4 +1018,37 @@ math.tanh(X) = Tanh :-
Tanh = (exp(X)-exp(-X)) / (exp(X)+exp(-X)).
%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+ math.have_fma,
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness],
+"
+#if defined(MR_HAVE_FMA)
+ SUCCESS_INDICATOR = MR_TRUE;
+#else
+ SUCCESS_INDICATOR = MR_FALSE;
+#endif
+").
+
+have_fma :-
+ semidet_false.
+
+:- pragma foreign_proc("C",
+ math.fma(X::in, Y::in, Z::in) = (FMA::out),
+ [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+ does_not_affect_liveness],
+"
+#if defined(MR_HAVE_FMA)
+ FMA = fma(X, Y, Z);
+#else
+ MR_fatal_error(""math.fma not supported"");
+#endif
+").
+
+fma(_, _, _) = _ :-
+ private_builtin.sorry("math.fma").
+
+%---------------------------------------------------------------------------%
+:- end_module math.
%---------------------------------------------------------------------------%
diff --git a/runtime/mercury_conf.h.in b/runtime/mercury_conf.h.in
index 2223337..c2d4282 100644
--- a/runtime/mercury_conf.h.in
+++ b/runtime/mercury_conf.h.in
@@ -297,6 +297,7 @@
** pthread_mutexattr_setpshared() function.
** MR_HAVE_MKSTEMP we have the mkstemp() function.
** MR_HAVE_SETRLIMIT we have the setrlimit() function.
+** MR_HAVE_FMA we have the fma() function.
*/
#undef MR_HAVE_GETPID
#undef MR_HAVE_SETPGID
@@ -369,6 +370,7 @@
#undef MR_HAVE_PTHREAD_MUTEXATTR_SETPSHARED
#undef MR_HAVE_MKSTEMP
#undef MR_HAVE_SETRLIMIT
+#undef MR_HAVE_FMA
/*
** We use mprotect() and signals to catch stack and heap overflows.
More information about the reviews
mailing list