Bug 95644 - [F2018] IEEE_FMA is missing from the IEEE_ARITHMETIC module
Summary: [F2018] IEEE_FMA is missing from the IEEE_ARITHMETIC module
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 9.3.0
: P4 normal
Target Milestone: 12.2
Assignee: Francois-Xavier Coudert
URL:
Keywords:
Depends on:
Blocks: 105105
  Show dependency treegraph
 
Reported: 2020-06-11 16:55 UTC by Bill Long
Modified: 2022-05-06 08:30 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-06-11 00:00:00


Attachments
Tentative patch, adding IEEE_FMA and IEEE_SIGNBIT (2.19 KB, patch)
2021-12-30 17:15 UTC, Francois-Xavier Coudert
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Bill Long 2020-06-11 16:55:45 UTC
> cat test2.f90

program test

  use, intrinsic :: ieee_arithmetic, only : ieee_fma

  implicit none

end program test


Intel:

> ifort test2.f90

Cray:

> module swap PrgEnv-intel PrgEnv-cray
> ftn test2.f90
> ./a.out

gfortran:

> module swap PrgEnv-cray PrgEnv-gnu
> gfortran test2.f90
test2.f90:2:43:

2 | use, intrinsic :: ieee_arithmetic, only : ieee_fma
1
Error: Symbol 'ieee_fma' referenced at (1) not found in module 'ieee_arithmetic'
>
Comment 1 Dominique d'Humieres 2020-06-11 17:50:38 UTC
Confirmed.
Comment 2 Bill Long 2020-10-02 21:46:09 UTC
Any update on a fix for this?  (The original customer is asking.)
Comment 3 anlauf 2020-10-05 19:45:27 UTC
> Any update on a fix for this?  (The original customer is asking.)

I assume the customer or Cray didn't set a bounty on this?

Adding F2018 to summary.
Comment 4 Bill Long 2020-10-05 19:50:27 UTC
The customer has nuclear weapons.  They do not do "bounty". :)  Cray/HPE is just the messenger. I think they would be happy with a plan for including the routine.
Comment 5 Bill Long 2021-01-22 18:00:50 UTC
Original customer is asking again...
Comment 6 Jerry DeLisle 2021-01-23 03:07:19 UTC
Hi Bill, per our operational security procedure we can't talk about ieee_arithmetic, especially when we dont get paid.  However, I can go look at the code and see if Steve's patch got in or not.
Comment 7 Bill Long 2021-03-03 21:59:06 UTC
Inquiry from the original site:

"Does GCC provide a timeline for when they will conform to F2018?"
Comment 8 kargl 2021-03-04 00:51:21 UTC
(In reply to Bill Long from comment #7)
> Inquiry from the original site:
> 
> "Does GCC provide a timeline for when they will conform to F2018?"

gfortran is maintained mostly by a very, very, very, small group
of individuals who have very, very, very, limited free time.  Things
get fixed and implemented as time and whim permits.

The quickest way to ensure something is implemented/fixed is to
download the source code and dive in.

Short of someone diving in, there is always the kludge of

module kludge

   use iso_c_binding, only : fp => c_float
   use iso_c_binding, only : dp => c_double
   use iso_c_binding, only : lp => c_long_double

   implicit none

   private

   public ieee_fma

   interface ieee_fma

      function fmaf(x, y, z) bind(c, name='fmaf')
         import fp
         real(fp) fmaf
         real(fp), intent(in), value :: x, y, z
      end function fmaf
 
      function fma(x, y, z) bind(c, name='fma')
         import dp
         real(dp) fma
         real(dp), intent(in), value :: x, y, z
      end function fma

      function fmal(x, y, z) bind(c, name='fmal')
         import lp
         real(lp) fmal
         real(lp), intent(in), value :: x, y, z
      end function fmal
   end interface ieee_fma

end module

program foo
   use kludge, only : ieee_fma
   real x, y, z    ! Yeah, I should use fp from kludge.
   x = 1.
   y = 2. / 3.
   z = y
   print *, ieee_fma(x, y, z)
end program foo

Or, if the availability of IEEE_FMA is must have feature and someone
is incapability of implemented, someone could approach on of those
very, very, very, few individuals and pay for the work to be done.
Comment 9 kargl 2021-03-04 02:04:00 UTC
(In reply to kargl from comment #8)
> 
> Short of someone diving in, there is always the kludge of ...
> 

This is a better kludge, but is far from the correct approach
as gfortran should use the __builtin_fma() family of functions.
But, this works for at least static linking.  I did not update
the symbol map for dynamic linking.  I also did not test the
libquadmath portion.  ENOTIME.

diff --git a/libgfortran/ieee/ieee_arithmetic.F90 b/libgfortran/ieee/ieee_arithmetic.F90
index 35a16938f8e..3d686863e90 100644
--- a/libgfortran/ieee/ieee_arithmetic.F90
+++ b/libgfortran/ieee/ieee_arithmetic.F90
@@ -39,7 +39,7 @@ module IEEE_ARITHMETIC
     IEEE_DIVIDE_BY_ZERO, IEEE_UNDERFLOW, IEEE_INEXACT, IEEE_USUAL, &
     IEEE_ALL, IEEE_STATUS_TYPE, IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, &
     IEEE_GET_STATUS, IEEE_SET_FLAG, IEEE_SET_HALTING_MODE, &
-    IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
+    IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING, IEEE_FMA
 
   ! Derived types and named constants
 
@@ -88,6 +88,17 @@ module IEEE_ARITHMETIC
   end interface
   public :: operator (.ne.)
 
+  ! IEEE_FMA
+  interface ieee_fma
+      module procedure fma04
+      module procedure fma08
+#ifdef HAVE_GFC_REAL_10
+      module procedure fma10
+#endif
+#ifdef HAVE_GFC_REAL_16
+      module procedure fma16
+#endif
+  end interface ieee_fma
 
   ! IEEE_IS_FINITE
 
@@ -808,6 +819,65 @@ SUPPORTGENERIC(IEEE_SUPPORT_STANDARD)
 
 contains
 
+      impure elemental function fma04(x, y, z)
+         use iso_c_binding, only : knd => c_float
+         real(4) fma04
+         real(4), intent(in) :: x, y, z
+         interface
+            function fmaf(x, y, z) bind(c, name='fmaf')
+               import knd
+               real(knd) fmaf
+               real(knd), intent(in), value :: x, y, z
+            end function fmaf
+         end interface
+         fma04 = fmaf(real(x, knd), real(y, knd), real(z, knd))
+      end function fma04
+
+      impure elemental function fma08(x, y, z)
+         use iso_c_binding, only : knd => c_double
+         real(8) fma08
+         real(8), intent(in) :: x, y, z
+         interface
+            function fma(x, y, z) bind(c, name='fma')
+               import knd
+               real(knd) fma
+               real(knd), intent(in), value :: x, y, z
+            end function fma
+         end interface
+         fma08 = fma(real(x, knd), real(y, knd), real(z, knd))
+      end function fma08
+#ifdef HAVE_GFC_REAL_10
+      impure elemental function fma10(x, y, z)
+         use iso_c_binding, only : knd => c_long_double
+         real(10) fma10
+         real(10), intent(in) :: x, y, z
+         interface
+            function fmal(x, y, z) bind(c, name='fmal')
+               import knd
+               real(knd) fmal
+               real(knd), intent(in), value :: x, y, z
+            end function fmal
+         end interface
+         fma10 = fmal(real(x, knd), real(y, knd), real(z, knd))
+      end function fma10
+#endif
+#ifdef HAVE_GFC_REAL_16
+      impure elemental function fma16(x, y, z)
+         integer, parameter :: knd = 16
+         real(16) fma16
+         real(16), intent(in) :: x, y, z
+         interface
+            function fmaq(x, y, z) bind(c, name='fmaq')
+               import knd
+               real(knd) fmaq
+               real(knd), intent(in) :: x, y, z
+            end function fmaq
+         end interface
+         fma16 = fmaq(real(x, knd), real(y, knd), real(z, knd))
+      end function fma16
+#endif
+
+
   ! Equality operators for IEEE_CLASS_TYPE and IEEE_ROUNDING_MODE
   elemental logical function IEEE_CLASS_TYPE_EQ (X, Y) result(res)
     implicit none
Comment 10 Jerry DeLisle 2021-03-04 02:22:46 UTC
It is very likely that the gcc optimizers will actually convert the to fma machine instructions, but no guarantee.

I don't have much time, but it is likely some of the tricks we used in matmul can be used to get this to be "register" implemented .
Comment 11 Steve Kargl 2021-03-04 04:02:24 UTC
On Thu, Mar 04, 2021 at 02:22:46AM +0000, jvdelisle at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95644
> 
> --- Comment #10 from Jerry DeLisle <jvdelisle at gcc dot gnu.org> ---
> It is very likely that the gcc optimizers will actually convert the to fma
> machine instructions, but no guarantee.

That's what __builtin_fma() will do.  The second kludge I
posted would still have the layer of indirection of calling
on of fma04, fma08, fma10, or fma16.  Also, note that the
kludge declares these as IMPURE ELEMENTAL because of the
BIND(C) stuff.  This is technically incorrect.

> I don't have much time, but it is likely some of the tricks we used in matmul
> can be used to get this to be "register" implemented .

The correct approach would give interfaces in the
ieee_arithmetic so that argument checking can be
done.  The implementation details would be contained
in trans-intrinsic.c where conv_intrinsic_fma() is
called and __builtin_fma is directly emitted.  Another
approach, where conv_intrinsic_fma() is unneeded,
would be to register __builtin_fma() as builtin function
with gfortran.  This, however, requires more work because
gfortran currently does not have a mechanism for registering
a 3 argument builtin function.
Comment 12 Kombiatchu 2021-12-30 00:36:46 UTC
Bill you say you are a “master engineer” and have 25 years of Fortran experience and are a principal member of a Fortran committee.

Would it be unexpected for someone with that experience to offer a fix themselves rather than treating this like a free source of labor for their lucrative support contracts?
Comment 13 kargl 2021-12-30 00:44:24 UTC
(In reply to ally.alto.0z from comment #12)
> Bill you say you are a “master engineer” and have 25 years of Fortran
> experience and are a principal member of a Fortran committee.
> 
> Would it be unexpected for someone with that experience to offer a fix
> themselves rather than treating this like a free source of labor for their
> lucrative support contracts?

I'm not Bill.  Bill is employed by Cray to work on the Cray Fortran
compiler.  He has been quite helpful in reporting gfortran issues
found either by Cray or by Cray users.

That said, I see that you forgot to attach the patch that you have
developed to fix this issue.  For the record, the patch in comment 
#9 is mine.
Comment 14 Francois-Xavier Coudert 2021-12-30 16:30:07 UTC
Taking this, I have a tentative patch which:
  - declares the interface in libgfortran/ieee/ieee_arithmetic.f90
  - generates direct calls to GCC's FMA built-in in gcc/fortran/trans-intrinsic.c

This is how we handle many other IEEE intrinsics that don't need to depend on library support, like IEEE_RINT, IEEE_COPY_SIGN, and others.
Comment 15 Francois-Xavier Coudert 2021-12-30 17:15:45 UTC
Created attachment 52094 [details]
Tentative patch, adding IEEE_FMA and IEEE_SIGNBIT

I am attaching a tentative patch for the issue. I also added IEEE_SIGNBIT while I was at it, since it was relatively simple. Other new IEEE functions in Fortran 2018 will be more work.

The patch converts calls to IEEE_FMA and IEEE_SIGNBIT to the GCC builtins of the same name. For IEEE_FMA, it also works with _Float128, and there it will generate calls to the fmaq() function in libquadmath.

It generates the right code on simple examples, but I would welcome examples of test programs that check the output of both IEEE_SIGNBIT and IEEE_FMA on "interesting" cases.
Comment 16 Jakub Jelinek 2022-05-06 08:30:14 UTC
GCC 12.1 is being released, retargeting bugs to GCC 12.2.