[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