]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/68609 (PowerPC reciprocal estimate missed opportunities)
authorDavid Edelsohn <dje.gcc@gmail.com>
Fri, 15 Jan 2016 16:38:08 +0000 (16:38 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Fri, 15 Jan 2016 16:38:08 +0000 (11:38 -0500)
        PR target/68609
        * config/rs6000/rs6000.c (rs6000_emit_msub): Delete.
        (rs6000_emit_swsqrt): Convert to Goldschmidt's Algorithm
        * config/rs6000/rs6000.md (sqrt<mode>2): Limit swsqrt to high
        precision estimate.

From-SVN: r232439

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 067fb0757952fca73e4d0e6fd4c8933a4d7e7a7f..609b135dbb5b1bb1c1f435d1fab65eb06cd757e7 100644 (file)
@@ -1,3 +1,11 @@
+2016-01-15  David Edelsohn  <dje.gcc@gmail.com>
+
+       PR target/68609
+       * config/rs6000/rs6000.c (rs6000_emit_msub): Delete.
+       (rs6000_emit_swsqrt): Convert to Goldschmidt's Algorithm
+       * config/rs6000/rs6000.md (sqrt<mode>2): Limit swsqrt to high
+       precision estimate.
+
 2016-01-15  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/66856
index 4cd6a1b58cd8bcc484eeb8508c6b3948df0a6f0a..c589118a797752f276d3f3e830f96341ec273961 100644 (file)
@@ -32769,29 +32769,6 @@ rs6000_emit_madd (rtx target, rtx m1, rtx m2, rtx a)
     emit_move_insn (target, dst);
 }
 
-/* Generate a FMSUB instruction: dst = fma(m1, m2, -a).  */
-
-static void
-rs6000_emit_msub (rtx target, rtx m1, rtx m2, rtx a)
-{
-  machine_mode mode = GET_MODE (target);
-  rtx dst;
-
-  /* Altivec does not support fms directly;
-     generate in terms of fma in that case.  */
-  if (optab_handler (fms_optab, mode) != CODE_FOR_nothing)
-    dst = expand_ternary_op (mode, fms_optab, m1, m2, a, target, 0);
-  else
-    {
-      a = expand_unop (mode, neg_optab, a, NULL_RTX, 0);
-      dst = expand_ternary_op (mode, fma_optab, m1, m2, a, target, 0);
-    }
-  gcc_assert (dst != NULL);
-
-  if (dst != target)
-    emit_move_insn (target, dst);
-}
-    
 /* Generate a FNMSUB instruction: dst = -fma(m1, m2, -a).  */
 
 static void
@@ -32890,15 +32867,16 @@ rs6000_emit_swdiv (rtx dst, rtx n, rtx d, bool note_p)
     add_reg_note (get_last_insn (), REG_EQUAL, gen_rtx_DIV (mode, n, d));
 }
 
-/* Newton-Raphson approximation of single/double-precision floating point
-   rsqrt.  Assumes no trapping math and finite arguments.  */
+/* Goldschmidt's Algorithm for single/double-precision floating point
+   sqrt and rsqrt.  Assumes no trapping math and finite arguments.  */
 
 void
 rs6000_emit_swsqrt (rtx dst, rtx src, bool recip)
 {
   machine_mode mode = GET_MODE (src);
-  rtx x0 = gen_reg_rtx (mode);
-  rtx y = gen_reg_rtx (mode);
+  rtx e = gen_reg_rtx (mode);
+  rtx g = gen_reg_rtx (mode);
+  rtx h = gen_reg_rtx (mode);
 
   /* Low precision estimates guarantee 5 bits of accuracy.  High
      precision estimates guarantee 14 bits of accuracy.  SFmode
@@ -32909,55 +32887,68 @@ rs6000_emit_swsqrt (rtx dst, rtx src, bool recip)
   if (mode == DFmode || mode == V2DFmode)
     passes++;
 
-  REAL_VALUE_TYPE dconst3_2;
   int i;
-  rtx halfthree;
+  rtx mhalf;
   enum insn_code code = optab_handler (smul_optab, mode);
   insn_gen_fn gen_mul = GEN_FCN (code);
 
   gcc_assert (code != CODE_FOR_nothing);
 
-  /* Load up the constant 1.5 either as a scalar, or as a vector.  */
-  real_from_integer (&dconst3_2, VOIDmode, 3, SIGNED);
-  SET_REAL_EXP (&dconst3_2, REAL_EXP (&dconst3_2) - 1);
+  mhalf = rs6000_load_constant_and_splat (mode, dconsthalf);
 
-  halfthree = rs6000_load_constant_and_splat (mode, dconst3_2);
-
-  /* x0 = rsqrt estimate */
-  emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, src),
-                                             UNSPEC_RSQRT)));
+  /* e = rsqrt estimate */
+  emit_insn (gen_rtx_SET (e, gen_rtx_UNSPEC (mode, gen_rtvec (1, src),
+                                            UNSPEC_RSQRT)));
 
   /* If (src == 0.0) filter infinity to prevent NaN for sqrt(0.0).  */
   if (!recip)
     {
       rtx zero = force_reg (mode, CONST0_RTX (mode));
-      rtx target = emit_conditional_move (x0, GT, src, zero, mode,
-                                         x0, zero, mode, 0);
-      if (target != x0)
-       emit_move_insn (x0, target);
+      rtx target = emit_conditional_move (e, GT, src, zero, mode,
+                                         e, zero, mode, 0);
+      if (target != e)
+       emit_move_insn (e, target);
     }
 
-  /* y = 0.5 * src = 1.5 * src - src -> fewer constants */
-  rs6000_emit_msub (y, src, halfthree, src);
+  /* g = sqrt estimate.  */
+  emit_insn (gen_mul (g, e, src));
+  /* h = 1/(2*sqrt) estimate.  */
+  emit_insn (gen_mul (h, e, mhalf));
 
-  for (i = 0; i < passes; i++)
+  if (recip)
     {
-      rtx x1 = gen_reg_rtx (mode);
-      rtx u = gen_reg_rtx (mode);
-      rtx v = gen_reg_rtx (mode);
+      if (passes == 1)
+       {
+         rtx t = gen_reg_rtx (mode);
+         rs6000_emit_nmsub (t, g, h, mhalf);
+         /* Apply correction directly to 1/rsqrt estimate.  */
+         rs6000_emit_madd (dst, e, t, e);
+       }
+      else
+       {
+         for (i = 0; i < passes; i++)
+           {
+             rtx t1 = gen_reg_rtx (mode);
+             rtx g1 = gen_reg_rtx (mode);
+             rtx h1 = gen_reg_rtx (mode);
 
-      /* x1 = x0 * (1.5 - y * (x0 * x0)) */
-      emit_insn (gen_mul (u, x0, x0));
-      rs6000_emit_nmsub (v, y, u, halfthree);
-      emit_insn (gen_mul (x1, x0, v));
-      x0 = x1;
-    }
+             rs6000_emit_nmsub (t1, g, h, mhalf);
+             rs6000_emit_madd (g1, g, t1, g);
+             rs6000_emit_madd (h1, h, t1, h);
 
-  /* If not reciprocal, multiply by src to produce sqrt.  */
-  if (!recip)
-    emit_insn (gen_mul (dst, src, x0));
+             g = g1;
+             h = h1;
+           }
+         /* Multiply by 2 for 1/rsqrt.  */
+         emit_insn (gen_add3_insn (dst, h, h));
+       }
+    }
   else
-    emit_move_insn (dst, x0);
+    {
+      rtx t = gen_reg_rtx (mode);
+      rs6000_emit_nmsub (t, g, h, mhalf);
+      rs6000_emit_madd (dst, g, t, g);
+    }
 
   return;
 }
index dbcf583475d58abc31fda806e4cfb9171d6450ed..d8834a2731413b4d1726e0e3623b0438526f6db2 100644 (file)
    && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
 {
   if (<MODE>mode == SFmode
+      && TARGET_RECIP_PRECISION
       && RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)
       && !optimize_function_for_size_p (cfun)
       && flag_finite_math_only && !flag_trapping_math