diff mbox

Add a build_real_truncate helper function

Message ID 87y4fmya1j.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 1, 2015, 1:48 p.m. UTC
...which simplifies the match.pd patterns I'm about to add.

Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard

gcc/
	* real.h (build_real_truncate): Declare.
	* real.c (build_real_truncate): New function.
	(strip_float_extensions): Use it.
	* builtins.c (fold_builtin_cabs, fold_builtin_sqrt, fold_builtin_cbrt)
	(fold_builtin_hypot, fold_builtin_pow): Likewise.
	* match.pd: Likewise.

Comments

Bernd Schmidt Oct. 1, 2015, 1:52 p.m. UTC | #1
On 10/01/2015 03:48 PM, Richard Sandiford wrote:
> ...which simplifies the match.pd patterns I'm about to add.
>
> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Ok.


Bernd
Richard Biener Oct. 2, 2015, 8:07 a.m. UTC | #2
On Thu, Oct 1, 2015 at 3:52 PM, Bernd Schmidt <bschmidt@redhat.com> wrote:
> On 10/01/2015 03:48 PM, Richard Sandiford wrote:
>>
>> ...which simplifies the match.pd patterns I'm about to add.
>>
>> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?
>
>
> Ok.

I wonder if it's worth a separate function - why not truncate
unconditionally in build_real?
In fact it looks like we might have non-canonical REAL_CSTs with
excess precision?

Richard.

>
> Bernd
>
Richard Sandiford Oct. 2, 2015, 8:19 a.m. UTC | #3
Richard Biener <richard.guenther@gmail.com> writes:
> On Thu, Oct 1, 2015 at 3:52 PM, Bernd Schmidt <bschmidt@redhat.com> wrote:
>> On 10/01/2015 03:48 PM, Richard Sandiford wrote:
>>>
>>> ...which simplifies the match.pd patterns I'm about to add.
>>>
>>> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?
>>
>>
>> Ok.
>
> I wonder if it's worth a separate function - why not truncate
> unconditionally in build_real?

I suppose build_real would then be doing implicit rounding, whereas it
sounds like it should just be converting between representations.
The new function makes it explicit that the value is being changed
in the process.

> In fact it looks like we might have non-canonical REAL_CSTs with
> excess precision?

Maybe there should be an assert in build_real to catch that?
Although I don't really have time to offer to do that.
If you think we have a bug here then I can file a PR.

Thanks,
Richard
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2ff1a8c..1751b37 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -7593,12 +7593,10 @@  fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
       if (flag_unsafe_math_optimizations
 	  && operand_equal_p (real, imag, OEP_PURE_SAME))
         {
-	  const REAL_VALUE_TYPE sqrt2_trunc
-	    = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
 	  STRIP_NOPS (real);
 	  return fold_build2_loc (loc, MULT_EXPR, type,
-			      fold_build1_loc (loc, ABS_EXPR, type, real),
-			      build_real (type, sqrt2_trunc));
+				  fold_build1_loc (loc, ABS_EXPR, type, real),
+				  build_real_truncate (type, dconst_sqrt2 ()));
 	}
     }
 
@@ -7757,8 +7755,7 @@  fold_builtin_sqrt (location_t loc, tree arg, tree type)
 
 	  /* Adjust for the outer root.  */
 	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
-	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
-	  tree_root = build_real (type, dconstroot);
+	  tree_root = build_real_truncate (type, dconstroot);
 	  return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
 	}
     }
@@ -7805,11 +7802,9 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
       if (BUILTIN_EXPONENT_P (fcode))
 	{
 	  tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
-	  const REAL_VALUE_TYPE third_trunc =
-	    real_value_truncate (TYPE_MODE (type), dconst_third ());
 	  arg = fold_build2_loc (loc, MULT_EXPR, type,
-			     CALL_EXPR_ARG (arg, 0),
-			     build_real (type, third_trunc));
+				 CALL_EXPR_ARG (arg, 0),
+				 build_real_truncate (type, dconst_third ()));
 	  return build_call_expr_loc (loc, expfn, 1, arg);
 	}
 
@@ -7825,8 +7820,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 	      REAL_VALUE_TYPE dconstroot = dconst_third ();
 
 	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
-	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
-	      tree_root = build_real (type, dconstroot);
+	      tree_root = build_real_truncate (type, dconstroot);
 	      return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
 	    }
 	}
@@ -7846,8 +7840,7 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 
 		  real_arithmetic (&dconstroot, MULT_EXPR,
                                    dconst_third_ptr (), dconst_third_ptr ());
-		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
-		  tree_root = build_real (type, dconstroot);
+		  tree_root = build_real_truncate (type, dconstroot);
 		  return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
 		}
 	    }
@@ -7863,10 +7856,8 @@  fold_builtin_cbrt (location_t loc, tree arg, tree type)
 	  if (tree_expr_nonnegative_p (arg00))
 	    {
 	      tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
-	      const REAL_VALUE_TYPE dconstroot
-		= real_value_truncate (TYPE_MODE (type), dconst_third ());
-	      tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
-					 build_real (type, dconstroot));
+	      tree c = build_real_truncate (type, dconst_third ());
+	      tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, c);
 	      return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
 	    }
 	}
@@ -8392,13 +8383,9 @@  fold_builtin_hypot (location_t loc, tree fndecl,
   /* hypot(x,x) -> fabs(x)*sqrt(2).  */
   if (flag_unsafe_math_optimizations
       && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
-    {
-      const REAL_VALUE_TYPE sqrt2_trunc
-	= real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ());
-      return fold_build2_loc (loc, MULT_EXPR, type,
-			  fold_build1_loc (loc, ABS_EXPR, type, arg0),
-			  build_real (type, sqrt2_trunc));
-    }
+    return fold_build2_loc (loc, MULT_EXPR, type,
+			    fold_build1_loc (loc, ABS_EXPR, type, arg0),
+			    build_real_truncate (type, dconst_sqrt2 ()));
 
   return NULL_TREE;
 }
@@ -8530,10 +8517,8 @@  fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
 	  tree arg = CALL_EXPR_ARG (arg0, 0);
 	  if (tree_expr_nonnegative_p (arg))
 	    {
-	      const REAL_VALUE_TYPE dconstroot
-		= real_value_truncate (TYPE_MODE (type), dconst_third ());
-	      tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
-					build_real (type, dconstroot));
+	      tree c = build_real_truncate (type, dconst_third ());
+	      tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, c);
 	      return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
 	    }
 	}
diff --git a/gcc/match.pd b/gcc/match.pd
index bd5c267..d7f4e91 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2189,8 +2189,7 @@  along with GCC; see the file COPYING3.  If not see
        {
        CASE_FLT_FN (BUILT_IN_EXP):
          /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
-	 x = build_real (type, real_value_truncate (TYPE_MODE (type),
-						    dconst_e ()));
+	 x = build_real_truncate (type, dconst_e ());
          break;
        CASE_FLT_FN (BUILT_IN_EXP2):
          /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
@@ -2226,8 +2225,7 @@  along with GCC; see the file COPYING3.  If not see
          break;
        CASE_FLT_FN (BUILT_IN_CBRT):
 	 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
-         x = build_real (type, real_value_truncate (TYPE_MODE (type),
-						    dconst_third ()));
+         x = build_real_truncate (type, dconst_third ());
          break;
        default:
 	 gcc_unreachable ();
diff --git a/gcc/real.h b/gcc/real.h
index bd2a864..455d853 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -451,6 +451,9 @@  bool real_can_shorten_arithmetic (machine_mode, machine_mode);
 /* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node.  */
 extern tree build_real (tree, REAL_VALUE_TYPE);
 
+/* Likewise, but first truncate the value to the type.  */
+extern tree build_real_truncate (tree, REAL_VALUE_TYPE);
+
 /* Calculate R as X raised to the integer exponent N in mode MODE.  */
 extern bool real_powi (REAL_VALUE_TYPE *, machine_mode,
 		       const REAL_VALUE_TYPE *, HOST_WIDE_INT);
diff --git a/gcc/tree.c b/gcc/tree.c
index 84fd34d..49c6285 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1877,6 +1877,14 @@  build_real (tree type, REAL_VALUE_TYPE d)
   return v;
 }
 
+/* Like build_real, but first truncate D to the type.  */
+
+tree
+build_real_truncate (tree type, REAL_VALUE_TYPE d)
+{
+  return build_real (type, real_value_truncate (TYPE_MODE (type), d));
+}
+
 /* Return a new REAL_CST node whose type is TYPE
    and whose value is the integer value of the INTEGER_CST node I.  */
 
@@ -12091,7 +12099,7 @@  strip_float_extensions (tree exp)
 	       && exact_real_truncate (TYPE_MODE (double_type_node), &orig))
 	type = double_type_node;
       if (type)
-	return build_real (type, real_value_truncate (TYPE_MODE (type), orig));
+	return build_real_truncate (type, orig);
     }
 
   if (!CONVERT_EXPR_P (exp))