> 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' >
Confirmed.
Any update on a fix for this? (The original customer is asking.)
> 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.
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.
Original customer is asking again...
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.
Inquiry from the original site: "Does GCC provide a timeline for when they will conform to F2018?"
(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.
(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
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 .
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.
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?
(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.
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.
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.
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
GCC 12.2 is being released, retargeting bugs to GCC 12.3.
GCC 12.3 is being released, retargeting bugs to GCC 12.4.
Not sure why this was not cross-posted here automatically, but it was fixed a year ago, and part of GCC 13 release: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7c4c65d11469d29403d5a88316445ec95cd3c3f8 commit 7c4c65d11469d29403d5a88316445ec95cd3c3f8 Author: Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> Date: Wed Aug 31 15:22:50 2022 +0200 fortran: Add IEEE_SIGNBIT and IEEE_FMA functions The functions are added to the IEEE_ARITHMETIC module, but are entirely expanded in the front-end, using GCC built-ins. 2022-08-31 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> PR fortran/95644 gcc/fortran/ * f95-lang.cc (gfc_init_builtin_functions): Declare FMA built-ins. * mathbuiltins.def: Declare FMA built-ins. * trans-intrinsic.cc (conv_intrinsic_ieee_fma): New function. (conv_intrinsic_ieee_signbit): New function. (gfc_build_intrinsic_lib_fndecls): Add cases for FMA and SIGNBIT. gcc/testsuite/ * gfortran.dg/ieee/fma_1.f90: New test. * gfortran.dg/ieee/signbit_1.f90: New test. libgfortran/ * ieee/ieee_arithmetic.F90: Add IEEE_SIGNBIT and IEEE_FMA.