Bug 101835 - Fortran 128-bit float support, __float128/c_float128 / Supporting PowerPC's three 128-bit / 16-byte REAL data types
Summary: Fortran 128-bit float support, __float128/c_float128 / Supporting PowerPC's ...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-08-09 23:25 UTC by sandra
Modified: 2021-08-11 08:04 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-08-11 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description sandra 2021-08-09 23:25:31 UTC
Per discussion here

https://gcc.gnu.org/pipermail/fortran/2021-August/056334.html

there seems to be some confusion in the Fortran front end re gfc_real16_is_float128 and gfc_float128_type_node.  The C __float128 type must correspond to an IEEE representation and that isn't being checked where those variables are being set.  In cases where __float128 interoperability is required, it should be using float128_type_node with some additional check to make sure Fortran recognizes that mode (as in the patch for c_float128 and c_float128_complex attached to the mail linked above).  In cases where all that matters is that it's kind=16 and not the same kind as long double, it would be less confusing to rename gfc_float128_type_node to gfc_real16_type_node.

Also, note that on PowerPC there are 3 different 128-bit float modes, and the one that is defined to have precision 128 is the explicit IBM encoding, not IEEE, so the check for mode_precision == 128 in gfc_build_real_type is guaranteed not to find the __float128 equivalent on that target.  (The long double size on that target is configurable by command-line option but I don't know what actually makes sense from an ABI/CPU support point of view; it's at least conceivable that it could trip over that test, though.)
Comment 1 Tobias Burnus 2021-08-11 08:04:20 UTC
See linked thread for a longer description,
  https://gcc.gnu.org/pipermail/fortran/2021-August/thread.html#56315
  (the link in comment 0 is in the same thread)

However, the following issues exist:

* ISO_C_Binding's c_float128  (gfortran vendor extension)
  has to match __float128  (cf. also comment 0)

* ISO_Fortran_env provides:
  - REAL128 (whose storage size expressed in bits is 128)  [since Fortran 2008]
  - REAL_KINDS - array with supported real kinds (Fortran: no order requirements)
  In gfortran, it is ordered; e.g. on x86-64 w/ libquadmath: [4,8,10,16]. 

* gfortran currently uses:
  – float, double and long double – which used
    GCC's builtins, the 'f','','l' suffixes (sinf, sin, sinl) and uses in
    libgfortran those data types
  - TFmode
  - Other real types are filtered out.

* If long double's mode != TFmode, the FE assumes that TFmode is for
  __float128 – and sets info->c_float128 / yield gfc_real16_is_float128() = true
  However, this assumption is wrong in the general case, e.g. PowerPC has
  __float128 == KFmode and TFmode == 'long double'
  (There is currently no clash as KFmode is filtered out and TFmode == long double's mode).

  If a real type is regarded as float128, the FE calls the functions with 'q'
  suffix (such as sinq), libgfortran uses __float128 for those and there is some
  implicit assumption that libquadmath is available, which provides those 'q'
  functions.

* Kind values: Currently supported are
  4, 8, 10 (80bits; i387), 11 (82bits; IA-64, RFmode), 16
  However, kind=11 does not seem to be tested for (and could be better documented)
  The kind value is generated as:
    kind = (GET_MODE_PRECISION (mode) + 7) / 8;
  (The '+ 7' is for IA-64's RFmode to map to kind=11.)

  Fortran itself does not require IEEE support and the kind numbers are arbitrary,
  albeit users expect that 4 and 8 exists (and match float/double), some expect that
  16 exists and – only with gfortran – kind=10.
  The proper use is to use either the constants like:  REAL128, use REAL_KINDS
  and the function SELECTED_REAL_KIND
  [IEEE has to be supported for types where IEEE_SUPPORT_DATATYPE () returns .true.]

* Plus PowerPC:
    #define FLOAT_PRECISION_IFmode  128
    #define FLOAT_PRECISION_TFmode  127
    #define FLOAT_PRECISION_KFmode  126
  with IFmode (IBM 128-bit floating point),
       TFmode (long double mode),
       KFmode (explicit __float128).
  - The current 'kind =' calculation above has kind=16 for all of them.
    (except that IFmode and TFmode are filtered out)
  - When adding support for IFmode/KFmode PowerPC mode, the proper library
    function has to be called (suffix? ABI in libgfortran?)
  - PowerPC (rs6000) has the command line flags:
     -mfloat128
         Enable/disable the __float128 keyword for IEEE 128-bit floating point and
         use either software emulation for IEEE 128-bit floating point or hardware
         instructions.
     -mabi=ibmlongdouble
         Change the current ABI to use IBM extended-precision long double.
         This is not likely to work if your system defaults to using
         IEEE extended-precision long double.
     -mabi=ieeelongdouble
         Change the current ABI to use IEEE extended-precision long double.
         This is not likely to work if your system defaults to using
         IBM extended-precision long double.
  - As kind=16 is explicitly used, it should be supported but, otherwise,
    the other kinds can be mapped to any kind value, e.g. 15,16,17.
    There are ABI and compatibility issues – but they should be similar to
    C/C++.