On Wed, 2019-02-13 at 00:09 +0100, Jakub Jelinek wrote:
> Hi!
>
> As discussed recently on the mailing list, the norm2 simplification
> doesn't
> work if we limit mpfr emin/emax to some values derived from maximum
> floating
> exponents (and precision for denormals).
>
> The following patch adjusts the computation, so that it is scaled
> down if
> needed.  In particular, if any value in the array is so large that
> **2 will
> overflow on it or will be very close to it, the scale down is set to
> 2**(max_exponent/2+4), and if the result during computation gets
> close to
> overflowing, it is scaled down a little bit too.  The scaling is
> always done
> using powers of two, operands by that and the sum by **2 of that, and
> at the
> end it multiplies the sqrt back.  I had to change
> simplify_transformation_to_array, so that post_op is done immediately
> after
> finishing ops corresponding to that, so that there can be just one
> global
> variable for the scale.  From my understanding of e.g. the
> libgfortran norm2
> code where sqrt is done basically in this spot I hope it isn't
> possible that
> the same *dest is updated multiple times with dest
> increments/decrements in
> between.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux (together with
> Richard's patch), ok for trunk?
>
> 2019-02-12  Jakub Jelinek  <ja...@redhat.com>
>
>       PR middle-end/88074
>       * simplify.c (simplify_transformation_to_array): Run post_op
>       immediately after processing corresponding row, rather than at
> the
>       end.
>       (norm2_scale): New variable.
>       (add_squared): Rename to ...
>       (norm2_add_squared): ... this.  Scale down operand and/or
> result
>       if needed.
>       (do_sqrt): Rename to ...
>       (norm2_do_sqrt): ... this.  Handle the result == e case.  Scale
> up
>       result and clear norm2_scale.
>       (gfc_simplify_norm2): Clear norm2_scale.  Change add_squared to
>       norm2_add_squared and &do_sqrt to norm2_do_sqrt.  Scale up
> result
>       and clear norm2_scale again.
>

[...]

>  static gfc_expr *
> -add_squared (gfc_expr *result, gfc_expr *e)
> +norm2_add_squared (gfc_expr *result, gfc_expr *e)
>  {
>    mpfr_t tmp;
>
> @@ -6059,8 +6060,45 @@ add_squared (gfc_expr *result, gfc_expr
>             && result->expr_type == EXPR_CONSTANT);
>
>    gfc_set_model_kind (result->ts.kind);
> +  int index = gfc_validate_kind (BT_REAL, result->ts.kind, false);
> +  mpfr_exp_t exp;
> +  if (mpfr_regular_p (result->value.real))
> +    {

I've started seeing build failures in my testing setup here, apparently
introduced with this patch:

../../../src/gcc/fortran/simplify.c: In function ‘gfc_expr* 
norm2_add_squared(gfc_expr*, gfc_expr*)’:
../../../src/gcc/fortran/simplify.c:6064:3: error: ‘mpfr_exp_t’ was not 
declared in this scope; did you mean ‘mpfr_expm1’?
 6064 |   mpfr_exp_t exp;
      |   ^~~~~~~~~~
      |   mpfr_expm1

I'm using mpfr-2.4.2.tar.bz2, which is the minimum version stated at:
  https://gcc.gnu.org/install/prerequisites.html
which says "MPFR Library version 2.4.2 (or later)"; that
version doesn't seem to have that type.

However, I see on:
  https://www.mpfr.org/mpfr-3.0.1/mpfr.html#API-Compatibility
that "The official type for exponent values changed from mp_exp_t to
mpfr_exp_t in MPFR 3.0."

So should the patch be tweaked to use the old type name, like in the
following patch (caveat: not tested yet), or do we need to update
the minimum version of mpfr, and if so, to what version?

[...]

Dave

gcc/fortran/ChangeLog:
        PR middle-end/88074
        * simplify.c (norm2_add_squared): Use mp_exp_t rather than
        mpfr_exp_t.
---
 gcc/fortran/simplify.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index fa6396b..a1df735 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -6061,7 +6061,7 @@ norm2_add_squared (gfc_expr *result, gfc_expr *e)
 
   gfc_set_model_kind (result->ts.kind);
   int index = gfc_validate_kind (BT_REAL, result->ts.kind, false);
-  mpfr_exp_t exp;
+  mp_exp_t exp;
   if (mpfr_regular_p (result->value.real))
     {
       exp = mpfr_get_exp (result->value.real);
-- 
1.8.5.3

Reply via email to