[PATCH, gfortran] libgfortran: implement fpu-macppc for Darwin, support IEEE arithmetic

2024-07-04 Thread Sergey Fedorov
>From 50fc05566ba7479844949d727233c04a5e8151e8 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov 
Date: Sat, 29 Apr 2023 14:55:44 +0800
Subject: [PATCH] libgfortran: implement fpu-macppc for Darwin, support IEEE
 arithmetic

Signed-off-by: Sergey Fedorov 
---
 .../gfortran.dg/ieee/signaling_2_c.c  |   9 +
 libgfortran/config/fpu-macppc.h   | 414 ++
 libgfortran/configure.host|   9 +
 3 files changed, 432 insertions(+)
 create mode 100644 libgfortran/config/fpu-macppc.h

diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
index ea7fc0467bd..4a8f72c5bf2 100644
--- a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
+++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
@@ -1,3 +1,11 @@
+#ifdef __POWERPC__ // No support for issignaling in math.h on Darwin PPC
+
+int isnansf (float x)   { return __builtin_issignaling (x) ? 1 : 0; }
+int isnans  (double x)  { return __builtin_issignaling (x) ? 1 : 0; }
+int isnansl (long double x) { return __builtin_issignaling (x) ? 1 : 0; }
+
+#else
+
 #define _GNU_SOURCE
 #include 
 #include 
@@ -6,3 +14,4 @@ int isnansf (float x)   { return issignaling (x) ? 1 :
0; }
 int isnans  (double x)  { return issignaling (x) ? 1 : 0; }
 int isnansl (long double x) { return issignaling (x) ? 1 : 0; }

+#endif
diff --git a/libgfortran/config/fpu-macppc.h
b/libgfortran/config/fpu-macppc.h
new file mode 100644
index 000..d43d3caa3dd
--- /dev/null
+++ b/libgfortran/config/fpu-macppc.h
@@ -0,0 +1,414 @@
+/* FPU-related code for PowerPC.
+   Copyright (C) 2023-2024 Free Software Foundation, Inc.
+   Contributed by Sergey Fedorov 
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version 3.1,
+as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+. */
+
+/* While some of the definitions and functions used here are available
+   with Apple libm, we on purpose avoid pulling it in: to avoid potential
+   conflicts and not self-impose unnecessary constraints. */
+
+/* FP exception flags */
+#define FE_INEXACT  0x0200
+#define FE_DIVBYZERO0x0400
+#define FE_UNDERFLOW0x0800
+#define FE_OVERFLOW 0x1000
+#define FE_INVALID  0x2000
+
+#define FE_ALL_EXCEPT   0x3E00
+#define FE_NO_EXCEPT0xC1FF
+
+/* Extra invalid flags */
+#define FE_INVALID_SNAN 0x0100
+#define FE_INVALID_ISI  0x0080
+#define FE_INVALID_IDI  0x0040
+#define FE_INVALID_ZDZ  0x0020
+#define FE_INVALID_IMZ  0x0010
+#define FE_INVALID_XVC  0x0008
+#define FE_INVALID_SOFT 0x0400
+#define FE_INVALID_SQRT 0x0200
+#define FE_INVALID_CVI  0x0100
+
+/* Rounding modes */
+#define FE_TONEAREST0x
+#define FE_TOWARDZERO   0x0001
+#define FE_UPWARD   0x0002
+#define FE_DOWNWARD 0x0003
+
+/* There is no consistency re what is to be included in all_invalid.
+   Apple libm has 0x01f80300, Openlibm/FreeBSD/NetBSD has 0x21f80700
+   and OpenBSD has 0x01f80700. In particular, FE_INVALID_SOFT and
+   FE_INVALID are contested. */
+#define FE_ALL_INVALID  0x01F80700
+#define FE_NO_INVALID   0xFE07F8FF
+
+/* Apple libm has 0xFFF80300 and 0x0007FCFF here. */
+#define FE_ALL_FLAGS0xFFF80700
+#define FE_NO_FLAGS 0x0007F8FF
+
+#define FE_ALL_RND  0x0003
+#define FE_NO_RND   0xFFFC
+
+/* Floating-point exception summary (FX) bit. */
+#define FE_SET_FX   0x8000
+#define FE_CLR_FX   0x7FFF
+
+/* Some implementations use FE_INVALID_SOFT here. */
+#define SET_INVALID 0x0100
+
+#define FE_EXCEPT_SHIFT 22
+#define EXCEPT_MASK FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
+
+typedef unsigned intfenv_t;
+typedef unsigned intfexcept_t;
+
+/* default environment object */
+extern const fenv_t _FE_DFL_ENV;
+/* pointer to default environment */
+#define FE_DFL_ENV  &_FE_DFL_ENV
+
+typedef union {
+struct {
+unsigned int hi;
+fenv_t   lo;
+} i;
+double   d;
+} hexdouble;
+
+#define HEXDOUBLE(hi, lo) {{ hi, lo }}
+
+
+/* Check we can actually store the FPU state in the allocated size. */
+_S

Re: [PATCH, gfortran] libgfortran: implement fpu-macppc for Darwin, support IEEE arithmetic

2024-07-04 Thread Sergey Fedorov
Below is the diff of tests for gfortran on powerpc-apple-darwin10.8.0
without (unmodified gcc upstream) vs with the gfortran patch being added.

 === gfortran Summary ===

-# of expected passes69273
-# of unexpected failures36
+# of expected passes69646
+# of unexpected failures85
 # of unexpected successes12
 # of expected failures287
-# of unsupported tests357
+# of unsupported tests363

I.e., we get +373 passes and +49 failures. With one exception (see below),
failures are due to tests which were not run before.
AFAICT, present failures are not specific to my patch, but rather caused by
constraints of 32-bit powerpc or some existing darwin-specific issues: I
have tried a few versions of my patch, including almost copy-paste of SysV
code, which is substantially different, and test results were either
identical or a few extra tests failed (SysV-based version was marginally
worse, for instance), but those which fail here, failed consistently for
every version.

There is one test which changes from PASS to FAIL (round_4), however I
think this is not a real regression, and the test in its present form is
expected to fail.
See comments in the test code in the source and my post:
https://gcc.gnu.org/pipermail/fortran/2024-July/060612.html

---
/Users/svacchanda/Develop/FORTRAN/gfortran_15.0.0_20240608_no_ieee.sum
2024-06-29 00:25:18.0 +0800
+++
/Users/svacchanda/Develop/FORTRAN/gfortran_15.0.0_20240608_ieee_added.sum
2024-06-29 08:11:29.0 +0800
@@ -1,4 +1,4 @@
-Test run by svacchanda on Fri Jun 28 23:25:22 2024
+Test run by svacchanda on Sat Jun 29 07:02:39 2024
 Native configuration is powerpc-apple-darwin10.8.0

 === gfortran tests ===
@@ -48800,17 +48800,17 @@
 PASS: gfortran.dg/round_3.f08   -Os  (test for excess errors)
 PASS: gfortran.dg/round_3.f08   -Os  execution test
 PASS: gfortran.dg/round_4.f90   -O0  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -O0  execution test
+FAIL: gfortran.dg/round_4.f90   -O0  execution test
 PASS: gfortran.dg/round_4.f90   -O1  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -O1  execution test
+FAIL: gfortran.dg/round_4.f90   -O1  execution test
 PASS: gfortran.dg/round_4.f90   -O2  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -O2  execution test
+FAIL: gfortran.dg/round_4.f90   -O2  execution test
 PASS: gfortran.dg/round_4.f90   -O3 -fomit-frame-pointer -funroll-loops
-fpeel-loops -ftracer -finline-functions  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -O3 -fomit-frame-pointer -funroll-loops
-fpeel-loops -ftracer -finline-functions  execution test
+FAIL: gfortran.dg/round_4.f90   -O3 -fomit-frame-pointer -funroll-loops
-fpeel-loops -ftracer -finline-functions  execution test
 PASS: gfortran.dg/round_4.f90   -O3 -g  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -O3 -g  execution test
+FAIL: gfortran.dg/round_4.f90   -O3 -g  execution test
 PASS: gfortran.dg/round_4.f90   -Os  (test for excess errors)
-PASS: gfortran.dg/round_4.f90   -Os  execution test
+FAIL: gfortran.dg/round_4.f90   -Os  execution test
 PASS: gfortran.dg/rrspacing_1.f90   -O0  (test for excess errors)
 PASS: gfortran.dg/rrspacing_1.f90   -O0  execution test
 PASS: gfortran.dg/rrspacing_1.f90   -O1  (test for excess errors)
@@ -49289,8 +49289,7 @@
 PASS: gfortran.dg/select_type_2.f03   -O1  execution test
 PASS: gfortran.dg/select_type_2.f03   -O2  (test for excess errors)
 PASS: gfortran.dg/select_type_2.f03   -O2  execution test
-WARNING: gfortran.dg/select_type_2.f03   -O3 -fomit-frame-pointer
-funroll-loops -fpeel-loops -ftracer -finline-functions  (test for excess
errors) program timed out.
-FAIL: gfortran.dg/select_type_2.f03   -O3 -fomit-frame-pointer
-funroll-loops -fpeel-loops -ftracer -finline-functions  (test for excess
errors)
+PASS: gfortran.dg/select_type_2.f03   -O3 -fomit-frame-pointer
-funroll-loops -fpeel-loops -ftracer -finline-functions  (test for excess
errors)
 PASS: gfortran.dg/select_type_2.f03   -O3 -fomit-frame-pointer
-funroll-loops -fpeel-loops -ftracer -finline-functions  execution test
 PASS: gfortran.dg/select_type_2.f03   -O3 -g  (test for excess errors)
 PASS: gfortran.dg/select_type_2.f03   -O3 -g  execution test
@@ -64745,6 +64744,434 @@
 PASS: gfortran.dg/graphite/vect-pr94043.f90   -O  (test for excess errors)
 Running
/Users/svacchanda/Develop/gcc-git/gcc/testsuite/gfortran.dg/guality/guality.exp
...
 Running
/Users/svacchanda/Develop/gcc-git/gcc/testsuite/gfortran.dg/ieee/ieee.exp
...
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O0  (test for excess errors)
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O0  execution test
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O1  (test for excess errors)
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O1  execution test
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O2  (test for excess errors)
+PASS: gfortran.dg/ieee/comparisons_1.f90   -O2  execution test
+PASS: gfortran.dg/ieee/compa

Re: [PATCH, gfortran] libgfortran: implement fpu-macppc for Darwin, support IEEE arithmetic

2024-07-04 Thread FX Coudert
Hi,

The core of the powerpc-FPU manipulation is okay for me. Some comments below.


> --- a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
> +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
> @@ -1,3 +1,11 @@
> +#ifdef __POWERPC__ // No support for issignaling in math.h on Darwin PPC

Two things:

1. I don’t understand why that needs to be added. The companion test in 
signaling_2.f90 has:

! { dg-require-effective-target issignaling } */
! The companion C source needs access to the issignaling macro.

Therefore, if the issignaling macro is not available, the test should not even 
be run.

2. Maybe this is actually moot. Is the __builtin_issignaling() macro available 
on all targets? The test was written before it was added to the middle-end. If 
the answer to the previous question is yes, we should simply use it in instead 
of the macro.


> +/* There is no consistency re what is to be included in all_invalid.
> +   Apple libm has 0x01f80300, Openlibm/FreeBSD/NetBSD has 0x21f80700
> +   and OpenBSD has 0x01f80700. In particular, FE_INVALID_SOFT and
> +   FE_INVALID are contested. */
> +#define FE_ALL_INVALID  0x01F80700
> +#define FE_NO_INVALID   0xFE07F8FF
> +
> +/* Apple libm has 0xFFF80300 and 0x0007FCFF here. */
> +#define FE_ALL_FLAGS0xFFF80700
> +#define FE_NO_FLAGS 0x0007F8FF

Since it’s a darwin-only file, why not follow Apple libm conventions?


> There is one test which changes from PASS to FAIL (round_4), however I think 
> this is not a real regression, and the test in its present form is expected 
> to fail.
> See comments in the test code in the source and my post: 
> https://gcc.gnu.org/pipermail/fortran/2024-July/060612.html


I agree that round_4.f90 should be added to the dg-skip-if.
But I’d like to understand better what are the other new failures, and why 
there arise?

FX

Re: [PATCH, gfortran] libgfortran: implement fpu-macppc for Darwin, support IEEE arithmetic

2024-07-04 Thread Sergey Fedorov
On Fri, Jul 5, 2024 at 5:23 AM FX Coudert  wrote:

> Hi,
> The core of the powerpc-FPU manipulation is okay for me. Some comments
> below.
>

Thank you for reviewing!


> > --- a/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
> > +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2_c.c
> > @@ -1,3 +1,11 @@
> > +#ifdef __POWERPC__ // No support for issignaling in math.h on Darwin PPC
>
> Two things:
>
> 1. I don’t understand why that needs to be added. The companion test in
> signaling_2.f90 has:
>
> ! { dg-require-effective-target issignaling } */
> ! The companion C source needs access to the issignaling macro.
>
> Therefore, if the issignaling macro is not available, the test should not
> even be run.
>

This part of the patch is quite old, but from the remaining log it looks I
got an error here:
```
issignaling2483.c: In function 'main':
issignaling2483.c:6:18: warning: implicit declaration of function
'issignaling' [-Wimplicit-function-declaration]
Undefined symbols:
  "_issignaling", referenced from:
  _main in ccORNr9V.o
ld: symbol(s) not found
collect2: error: ld returned 1 exit status
```
Now on a second thought, this did not require a fix perhaps. We can drop it.

2. Maybe this is actually moot. Is the __builtin_issignaling() macro
> available on all targets? The test was written before it was added to the
> middle-end. If the answer to the previous question is yes, we should simply
> use it in instead of the macro.
>

I am not really sure about support for it across targets. (If we are
unclear on this, changes to tests themselves could be moved to a separate
issue, I guess.)

> +/* There is no consistency re what is to be included in all_invalid.
> > +   Apple libm has 0x01f80300, Openlibm/FreeBSD/NetBSD has 0x21f80700
> > +   and OpenBSD has 0x01f80700. In particular, FE_INVALID_SOFT and
> > +   FE_INVALID are contested. */
> > +#define FE_ALL_INVALID  0x01F80700
> > +#define FE_NO_INVALID   0xFE07F8FF
> > +
> > +/* Apple libm has 0xFFF80300 and 0x0007FCFF here. */
> > +#define FE_ALL_FLAGS0xFFF80700
> > +#define FE_NO_FLAGS 0x0007F8FF
>
> Since it’s a darwin-only file, why not follow Apple libm conventions?
>

I arrived at a conclusion that they are not exactly correct, and moreover
look somewhat inconsistent internally (i.e. different Apple headers between
each other in regard to assumptions for powerpc hardware capabilities).
However I am no expert here, so please take it with a grain of salt.

Do we know exactly whether FE_ALL_INVALID should or should not include a)
VX and b) VX_SOFT bits?

(This could be a matter of purely academic relevance though, since I did
try switching the values for those macros to add/remove questionable bits,
and the only one to make a difference, FWIW, was SET_INVALID define.)

> There is one test which changes from PASS to FAIL (round_4), however I
> think this is not a real regression, and the test in its present form is
> expected to fail.
> > See comments in the test code in the source and my post:
> https://gcc.gnu.org/pipermail/fortran/2024-July/060612.html
>
>
> I agree that round_4.f90 should be added to the dg-skip-if.
> But I’d like to understand better what are the other new failures, and why
> there arise?
>
> FX


I suspect that a chunk of failures are due to incorrect assumptions for
precision; there are also some obscure differences between Power and
PowerPC architectures in regard of floating point, which might not be
accounted for in the tests.
Since I was getting consistent failures with different versions of the
patch, I am reasonably sure that failures are not caused by fine details of
the implementation here; at least these tests failed on every attempt (and
aside from one version, extra failures, if present, were in single digit
numbers), and whenever the output contained numerical values, those also
matched, AFAICT.

I think I cannot attach a log here, even compressed, but I have put it
here:
http://macos-powerpc.org/gcc/gfortran/gfortran_macos_ppc_2024.06.28_ieee_added.log.zip

If you or anyone could help me to debug, I can rerun tests, modify
something etc. It is desirable to have it working correctly, of course.

By the way, do we have some point of comparison from other ppc32 platforms,
Linux or BSD (for the recent gcc master)?

Sergey