Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Maciej W. Rozycki
On Thu, 26 Nov 2020, Thomas Koenig wrote:

> If you want to look at something quite close to the standard, you can
> check out https://j3-fortran.org/doc/year/18/18-007r1.pdf  .

 Thanks!

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Maciej W. Rozycki
On Thu, 26 Nov 2020, Thomas Koenig wrote:

> >   What do you need this information for anyway?
> 
> It's a check if the simplification to constants of these
> floating point types is done correctly.

 Well, GCC's handling of the various FP formats is in the middle end (see 
gcc/real.c and the various instances of `struct real_format' there), so 
all the language frontends are supposed to be getting this right as long 
as the backend has wired the correct structs to its FP data types.  E.g. 
the VAX backend does it in gcc/config/vax/vax-modes.def:

RESET_FLOAT_FORMAT (SF, vax_f_format);
RESET_FLOAT_FORMAT (DF, vax_d_format);

and then `-mg' overrides it further:

  if (TARGET_G_FLOAT)
REAL_MODE_FORMAT (DFmode) = _g_format;

and this:

#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_G_FLOAT

has made it the default with my VAX/Linux work (still overridable with 
`-md', though I can see the GCC manual is badly behind here now that I had 
a look there).

> Another interesting thing to look at would be selected_real_kind.
> 
> selected_real_kind(precision, range) will give you the kind
> number of a real type with at least precision digits and a range
> from 10**-range to 10**range, or -1 if there is nothing that
> matches.  There should be a runtime version and a compile-time
> version, both of which should be correct :-)

 A compile-time version is handled by the middle end, so it is supposed to 
be always right, as noted above.  Now a run-time version might be another 
matter, although usually you'd just use the compile-time if possible, e.g. 
(using an example with C, which I am more familiar with) the `nan' library 
function will typically be implemented as a call to `__builtin_nan' on the 
GNU system, so it will produce the same as the said intrinsic.

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Thomas Koenig via Gcc-patches

Am 26.11.20 um 19:05 schrieb Maciej W. Rozycki:

  What do you need this information for anyway?


It's a check if the simplification to constants of these
floating point types is done correctly.

Another interesting thing to look at would be selected_real_kind.

selected_real_kind(precision, range) will give you the kind
number of a real type with at least precision digits and a range
from 10**-range to 10**range, or -1 if there is nothing that
matches.  There should be a runtime version and a compile-time
version, both of which should be correct :-)

Regards

Thomas


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Thomas Koenig via Gcc-patches

Am 26.11.20 um 18:34 schrieb Maciej W. Rozycki:

  Yeah, I've seen it my Fortran reference (not an official standard though;
I don't remember where to get them from and given I don't seem to have a
copy, I suspect they are charged for).


If you want to look at something quite close to the standard, you can
check out https://j3-fortran.org/doc/year/18/18-007r1.pdf  .

Best regards

Thomas


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Maciej W. Rozycki
On Thu, 26 Nov 2020, Thomas Koenig wrote:

> On my (IEEE) box, this prints
> 
> r = 3.402823e+38 d = 1.797693e+308 i = 4
> 
> so if you have a working printf (or some other way to display
> floating-point-variables) for C, you can examine the
> values.

 This prints:

r = 1.701412e+38 d = 1.701412e+38 i = 4

(unsurprisingly the values are the same as the F-floating and the 
D-floating formats only differ by precision).  Alternatively say:

  printf ("r = %.10e d = %.10e i = %d\n", r, d, i);

prints:

r = 1.7014117332e+38 d = 1.7014118346e+38 i = 4

Finally:

  printf ("r = %a d = %a i = %d\n", r, d, i);

prints:

r = 0x.0p+126 d = 0x.0p+126 i = 4

(passed through `less' as otherwise  is rendered as gibberish here and 
frankly I don't know what the 0xd4 character encoding is supposed to stand 
for as the %a format is supposed to produce hexadecimal digits, possibly 
for machine parsing; LANG is unset implying the POSIX C locale across my 
systems).

 What do you need this information for anyway?

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Maciej W. Rozycki
On Wed, 25 Nov 2020, Tobias Burnus wrote:

> > Well, it does not link, for the somewhat unsurprising reason of a missing
> > libgfortran runtime.  I have modified the program with whatever little
> > Fortran skills I gained a while ago to get something that can be parseable
> > for a human being in the assembly form:
> 
> You could also try -fdump-tree-original or -fdump-parse-tree
> which might be a bit more readable than assembler – at least
> it avoids the problem of D-floating format.
> 
> >real(8) :: h = HUGE(1.0)
> >real(8) :: e = EPSILON(1.0)
> >
> >print *,h
> >print *,e
> > end

 Umm, my bad: 1.0 is Fortran single while 1d0 is a double literal.  So the 
raw values produced are correct for the VAX F-floating format, and for the 
D-floating I get:

.align 2
.type   h.2, @object
.size   h.2, 8
h.2:
.long   -32769
.long   -1
.align 2
.type   e.1, @object
.size   e.1, 8
e.1:
.long   9472
.long   0

which look right to me too.  Mind that VAX FP data are encoded in 16-bit
(word in DEC-speak) rather than 32-bit (longword in DEC-speak) chunks in 
memory.

 The options you mention (thanks for the hint) report:

  static real(kind=4) e = 1.1920928955078125e-7;
  static real(kind=4) h = 1.7014117331926442990585209174225846272e+38;

and:

  static real(kind=8) e = 2.77555756156289135105907917022705078125e-17;
  static real(kind=8) h = 1.7014118346046922937050406228106149888e+38;

respectively and reflect the 8-bit exponent.  For the G-floating format, 
produced with the `-mg' GCC option (a multilib candidate I would guess):

  static real(kind=8) e = 2.220446049250313080847263336181640625e-16;
  static real(kind=8) h = 
8.98846567431157854072637118658521783990352837629224982994e+307;

> huge and epsilon are defined as:
>   huge(x) = (1 - b**(-p)) * b**(emax-1) * b
>   epsilon(x) = b**(1-p)
> with
>   b = radix = REAL_MODE_FORMAT (mode)->b
>   p = digits = REAL_MODE_FORMAT (mode)->p
>   emax = max_exponent = REAL_MODE_FORMAT (mode)->emax

 Yeah, I've seen it my Fortran reference (not an official standard though; 
I don't remember where to get them from and given I don't seem to have a 
copy, I suspect they are charged for).

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-26 Thread Maciej W. Rozycki
On Wed, 25 Nov 2020, Tobias Burnus wrote:

> LGTM.

 Applied now, thank you for your review.

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Thomas Koenig via Gcc-patches

Am 25.11.20 um 23:02 schrieb Maciej W. Rozycki:

The Fortran intrinsis like HUGE, EPSILON, SELECTED_REAL_KIND etc
would have to be handled correctly, both for simplification in
the front end and in the library.

Does the program

   print *,HUGE(1.0)
   print *,EPSILON(1.0)
end

print correct values?

  Well, it does not link, for the somewhat unsurprising reason of a missing
libgfortran runtime.


OK.

What you can do instead is to use the C interpoerability feature
to make a Fortran subroutine which does not depend on
libgfortran, like this:

subroutine read_val (r, d, i) bind(c)
  use iso_c_binding, only : c_float, c_double, c_int
  real(kind=c_float), intent(out) :: r
  real(kind=c_double), intent(out) :: d
  integer(kind=c_int), intent(out) :: i
  r = huge(1._c_float)
  d = huge(1._c_double)
  i = selected_real_kind(6)
end subroutine read_val

and then call it from C, like this:

#include 

void read_val (float *, double *, int *);

int main ()
{
  float r;
  double d;
  int i;
  read_val (, , );
  printf ("r = %e d = %e i = %d\n", r, d, i);
  return 0;
}

On my (IEEE) box, this prints

r = 3.402823e+38 d = 1.797693e+308 i = 4

so if you have a working printf (or some other way to display
floating-point-variables) for C, you can examine the
values.

Best regards

Thomas


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Tobias Burnus

On 25.11.20 23:02, Maciej W. Rozycki wrote:


Well, it does not link, for the somewhat unsurprising reason of a missing
libgfortran runtime.  I have modified the program with whatever little
Fortran skills I gained a while ago to get something that can be parseable
for a human being in the assembly form:


You could also try -fdump-tree-original or -fdump-parse-tree
which might be a bit more readable than assembler – at least
it avoids the problem of D-floating format.


   real(8) :: h = HUGE(1.0)
   real(8) :: e = EPSILON(1.0)

   print *,h
   print *,e
end


huge and epsilon are defined as:
  huge(x) = (1 - b**(-p)) * b**(emax-1) * b
  epsilon(x) = b**(1-p)
with
  b = radix = REAL_MODE_FORMAT (mode)->b
  p = digits = REAL_MODE_FORMAT (mode)->p
  emax = max_exponent = REAL_MODE_FORMAT (mode)->emax

For C/C++, it is defined with
  %s = FLT, DBL, LDBL + FLT%d%s with %d e.g. 128 and %s = "" or "X" if extended
as
  __%s_MAX__ = builtin_define_with_hex_fp_value (... decimal_dig ...)
with
  decimal_dig = 1 + fmt->p * log10_b
and
  __%s_EPSILON__
as
  if (fmt->pnan < fmt->p)
/* This is an IBM extended double format, so 1.0 + any double is
   representable precisely.  */
  sprintf (buf, "0x1p%d", fmt->emin - fmt->p);
else
  sprintf (buf, "0x1p%d", 1 - fmt->p);


Tobias

-
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Maciej W. Rozycki
On Wed, 25 Nov 2020, Thomas Koenig wrote:

> >xbig = 26.543, xhuge = 6.71e+7, xmax = 2.53e+307;
> 
> The Fortran intrinsis like HUGE, EPSILON, SELECTED_REAL_KIND etc
> would have to be handled correctly, both for simplification in
> the front end and in the library.
> 
> Does the program
> 
>   print *,HUGE(1.0)
>   print *,EPSILON(1.0)
> end
> 
> print correct values?

 Well, it does not link, for the somewhat unsurprising reason of a missing 
libgfortran runtime.  I have modified the program with whatever little 
Fortran skills I gained a while ago to get something that can be parseable 
for a human being in the assembly form:

  real(8) :: h = HUGE(1.0)
  real(8) :: e = EPSILON(1.0)

  print *,h
  print *,e
end

This yields the following data produced for the real literals referred:

.align 2
.type   h.2, @object
.size   h.2, 8
h.2:
.long   -32769
.long   0
.align 2
.type   e.1, @object
.size   e.1, 8
e.1:
.long   13568
.long   0

which made me realise the NetBSD target defaults to the D-floating format 
for some reason, which is significantly different in the range supported 
from IEEE 754 double; specifically it has 1 sign bit, 8 exponent bits 
(like IEEE 754 single) and 55 trailing significand bits.

 So I am going to give up on giving this format any support, sorry (for 
the VAX/Linux port I chose to use the G-floating format, which at least 
gives some hope for interchangeability, even though I realise in some uses 
the extra mantissa bits D-floating provides are useful).

 In any case the output above does not appear exactly right to me as I 
would expect:

h.2:
.long   -32769
.long   -1

(`e' seems right to me).

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Thomas Koenig via Gcc-patches

Hi Maciej,


  Infinity is the least of a problem, because as it turns out we have
numerous FP library functions in libgfortran that require explicit porting
to each FP format supported, like these settings:

  xbig = 26.543, xhuge = 6.71e+7, xmax = 2.53e+307;


The Fortran intrinsis like HUGE, EPSILON, SELECTED_REAL_KIND etc
would have to be handled correctly, both for simplification in
the front end and in the library.

Does the program

  print *,HUGE(1.0)
  print *,EPSILON(1.0)
end

print correct values?

Regards

Thomas



Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Maciej W. Rozycki
On Wed, 25 Nov 2020, Tobias Burnus wrote:

> Does this solve all infinity issues? Or is there still code requiring it
> implicitly? From the previous exchange, it sounded as if there are still
> issues.

 Infinity is the least of a problem, because as it turns out we have 
numerous FP library functions in libgfortran that require explicit porting 
to each FP format supported, like these settings:

  xbig = 26.543, xhuge = 6.71e+7, xmax = 2.53e+307;

which need to be adjusted for the different representable ranges provided, 
by the VAX format in this case.  Fortunately the VAX encoding is quite 
similar to IEEE 754 as far as the encodings of regular FP data are, but 
the bias of the exponent is bumped up by 2, that is for example with the 
double format using the VAX G-floating data type it is 1025 rather than 
1023 -- 1 by the encoding of the exponent itself and 1 by the value of the 
implicit mantissa bit.  Some of my previous work on the libm part of glibc 
can possibly be reused; see my other message here:



 BTW there's an interesting story available online regarding the VAX vs 
IEEE 754 (Intel) FP format, which does explain the similarities: 

.

  Maciej


Re: [PATCH] libgfortran: Correct FP feature macro checks

2020-11-25 Thread Tobias Burnus

LGTM.

Does this solve all infinity issues? Or is there still code requiring it
implicitly? From the previous exchange, it sounded as if there are still
issues.

Tobias

On 25.11.20 19:14, Maciej W. Rozycki wrote:

The *_HAS_* floating-point feature macros are defined as 0/1 rather than
#undef/#define settings by gcc/c-family/c-cppbuiltin.c.  Consequently we
choose to use infinity and NaN features even with non-IEEE-754 targets
such as `vax-netbsdelf' that lack them, causing build warnings and
failures like:

In file included from .../libgfortran/generated/maxval_r4.c:26:
.../libgfortran/generated/maxval_r4.c: In function 'maxval_r4':
.../libgfortran/libgfortran.h:292:30: warning: target format does not support 
infinity
   292 | # define GFC_REAL_4_INFINITY __builtin_inff ()
   |  ^~
.../libgfortran/generated/maxval_r4.c:149:19:
note: in expansion of macro 'GFC_REAL_4_INFINITY'
   149 | result = -GFC_REAL_4_INFINITY;
   |   ^~~
.../libgfortran/generated/maxval_r4.c: In function 'mmaxval_r4':
.../libgfortran/libgfortran.h:292:30: warning: target format does not support 
infinity
   292 | # define GFC_REAL_4_INFINITY __builtin_inff ()
   |  ^~
.../libgfortran/generated/maxval_r4.c:363:19:
note: in expansion of macro 'GFC_REAL_4_INFINITY'
   363 | result = -GFC_REAL_4_INFINITY;
   |   ^~~
{standard input}: Assembler messages:
{standard input}:204: Fatal error: Can't relocate expression
make[3]: *** [Makefile:3358: maxval_r4.lo] Error 1

Correct the checks then for __FLT_HAS_INFINITY__, __DBL_HAS_INFINITY__,
__LDBL_HAS_INFINITY__, __FLT_HAS_QUIET_NAN__, __DBL_HAS_QUIET_NAN__, and
__LDBL_HAS_QUIET_NAN__ to match semantics and remove build issues coming
from the misinterpretation of these macros.

  libgfortran/
  * libgfortran.h: Use #if rather than #ifdef with
  __FLT_HAS_INFINITY__, __DBL_HAS_INFINITY__,
  __LDBL_HAS_INFINITY__, __FLT_HAS_QUIET_NAN__,
  __DBL_HAS_QUIET_NAN__, and __LDBL_HAS_QUIET_NAN__.
---
  libgfortran/libgfortran.h |   12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)

gcc-libgfortran-fp-has.diff
Index: gcc/libgfortran/libgfortran.h
===
--- gcc.orig/libgfortran/libgfortran.h
+++ gcc/libgfortran/libgfortran.h
@@ -288,13 +288,13 @@ typedef GFC_UINTEGER_4 gfc_char4_t;

  /* M{IN,AX}{LOC,VAL} need also infinities and NaNs if supported.  */

-#ifdef __FLT_HAS_INFINITY__
+#if __FLT_HAS_INFINITY__
  # define GFC_REAL_4_INFINITY __builtin_inff ()
  #endif
-#ifdef __DBL_HAS_INFINITY__
+#if __DBL_HAS_INFINITY__
  # define GFC_REAL_8_INFINITY __builtin_inf ()
  #endif
-#ifdef __LDBL_HAS_INFINITY__
+#if __LDBL_HAS_INFINITY__
  # ifdef HAVE_GFC_REAL_10
  #  define GFC_REAL_10_INFINITY __builtin_infl ()
  # endif
@@ -306,13 +306,13 @@ typedef GFC_UINTEGER_4 gfc_char4_t;
  #  endif
  # endif
  #endif
-#ifdef __FLT_HAS_QUIET_NAN__
+#if __FLT_HAS_QUIET_NAN__
  # define GFC_REAL_4_QUIET_NAN __builtin_nanf ("")
  #endif
-#ifdef __DBL_HAS_QUIET_NAN__
+#if __DBL_HAS_QUIET_NAN__
  # define GFC_REAL_8_QUIET_NAN __builtin_nan ("")
  #endif
-#ifdef __LDBL_HAS_QUIET_NAN__
+#if __LDBL_HAS_QUIET_NAN__
  # ifdef HAVE_GFC_REAL_10
  #  define GFC_REAL_10_QUIET_NAN __builtin_nanl ("")
  # endif

-
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter