The following limits mpfr operations to the maximum exponent range as
determined by available float modes.  This avoids excessive work
for evaluating functions like ctan for large arguments.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2019-02-19  Richard Biener  <rguent...@suse.de>

        PR middle-end/88074
        * toplev.c (do_compile): Initialize mpfr's exponent range
        based on available float modes.

        * gcc.dg/pr88074.c: New testcase.

diff --git a/gcc/testsuite/gcc.dg/pr88074.c b/gcc/testsuite/gcc.dg/pr88074.c
new file mode 100644
index 00000000000..9f64cc11424
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr88074.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+#include <complex.h>
+
+int main()
+{
+  _Complex double x;
+  __real x = 3.091e+8;
+  __imag x = -4.045e+8;
+  /* This used to spend huge amounts of compile-time inside mpc.  */
+  volatile _Complex double y = ctan (x);
+  return 0;
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ab20cd98969..fa8e1b78c99 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2153,6 +2153,30 @@ do_compile ()
        else
          int_n_enabled_p[i] = false;
 
+      /* Initialize mpfrs exponent range.  This is important to get
+         underflow/overflow in a reasonable timeframe.  */
+      machine_mode mode;
+      int min_exp = -1;
+      int max_exp = 1;
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+       if (SCALAR_FLOAT_MODE_P (mode))
+         {
+           const real_format *fmt = REAL_MODE_FORMAT (mode);
+           if (fmt)
+             {
+               /* fmt->emin - fmt->p + 1 should be enough but the
+                  back-and-forth dance in real_to_decimal_for_mode we
+                  do for checking fails due to rounding effects then.  */
+               if ((fmt->emin - fmt->p) < min_exp)
+                 min_exp = fmt->emin - fmt->p;
+               if (fmt->emax > max_exp)
+                 max_exp = fmt->emax;
+             }
+         }
+      if (mpfr_set_emin (min_exp)
+         || mpfr_set_emax (max_exp))
+       sorry ("mpfr not configured to handle all float modes");
+
       /* Set up the back-end if requested.  */
       if (!no_backend)
        backend_init ();

Reply via email to