Commit 73463c5e by Richard Sandiford Committed by Richard Sandiford

Add a build_real_truncate helper function

...which simplifies the match.pd patterns I'm about to add.

Bootstrapped & regression-tested on x86_64-linux-gnu.

gcc/
	* real.h (build_real_truncate): Declare.
	* tree.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.

From-SVN: r228483
parent 5b295a81
2015-10-05 Richard Sandiford <richard.sandiford@arm.com>
* real.h (build_real_truncate): Declare.
* tree.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.
2015-10-05 James Greenhalgh <james.greenhalgh@arm.com> 2015-10-05 James Greenhalgh <james.greenhalgh@arm.com>
Jiong Wang <jiong.wang@arm.com> Jiong Wang <jiong.wang@arm.com>
...@@ -7592,12 +7592,10 @@ fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl) ...@@ -7592,12 +7592,10 @@ fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
if (flag_unsafe_math_optimizations if (flag_unsafe_math_optimizations
&& operand_equal_p (real, imag, OEP_PURE_SAME)) && 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); STRIP_NOPS (real);
return fold_build2_loc (loc, MULT_EXPR, type, return fold_build2_loc (loc, MULT_EXPR, type,
fold_build1_loc (loc, ABS_EXPR, type, real), fold_build1_loc (loc, ABS_EXPR, type, real),
build_real (type, sqrt2_trunc)); build_real_truncate (type, dconst_sqrt2 ()));
} }
} }
...@@ -7756,8 +7754,7 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type) ...@@ -7756,8 +7754,7 @@ fold_builtin_sqrt (location_t loc, tree arg, tree type)
/* Adjust for the outer root. */ /* Adjust for the outer root. */
SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real_truncate (type, dconstroot);
tree_root = build_real (type, dconstroot);
return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
} }
} }
...@@ -7804,11 +7801,9 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type) ...@@ -7804,11 +7801,9 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
if (BUILTIN_EXPONENT_P (fcode)) if (BUILTIN_EXPONENT_P (fcode))
{ {
tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); 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, arg = fold_build2_loc (loc, MULT_EXPR, type,
CALL_EXPR_ARG (arg, 0), CALL_EXPR_ARG (arg, 0),
build_real (type, third_trunc)); build_real_truncate (type, dconst_third ()));
return build_call_expr_loc (loc, expfn, 1, arg); return build_call_expr_loc (loc, expfn, 1, arg);
} }
...@@ -7824,8 +7819,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type) ...@@ -7824,8 +7819,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
REAL_VALUE_TYPE dconstroot = dconst_third (); REAL_VALUE_TYPE dconstroot = dconst_third ();
SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real_truncate (type, dconstroot);
tree_root = build_real (type, dconstroot);
return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
} }
} }
...@@ -7845,8 +7839,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type) ...@@ -7845,8 +7839,7 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
real_arithmetic (&dconstroot, MULT_EXPR, real_arithmetic (&dconstroot, MULT_EXPR,
dconst_third_ptr (), dconst_third_ptr ()); dconst_third_ptr (), dconst_third_ptr ());
dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); tree_root = build_real_truncate (type, dconstroot);
tree_root = build_real (type, dconstroot);
return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
} }
} }
...@@ -7862,10 +7855,8 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type) ...@@ -7862,10 +7855,8 @@ fold_builtin_cbrt (location_t loc, tree arg, tree type)
if (tree_expr_nonnegative_p (arg00)) if (tree_expr_nonnegative_p (arg00))
{ {
tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
const REAL_VALUE_TYPE dconstroot tree c = build_real_truncate (type, dconst_third ());
= real_value_truncate (TYPE_MODE (type), dconst_third ()); tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, c);
tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01,
build_real (type, dconstroot));
return build_call_expr_loc (loc, powfn, 2, arg00, narg01); return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
} }
} }
...@@ -8391,13 +8382,9 @@ fold_builtin_hypot (location_t loc, tree fndecl, ...@@ -8391,13 +8382,9 @@ fold_builtin_hypot (location_t loc, tree fndecl,
/* hypot(x,x) -> fabs(x)*sqrt(2). */ /* hypot(x,x) -> fabs(x)*sqrt(2). */
if (flag_unsafe_math_optimizations if (flag_unsafe_math_optimizations
&& operand_equal_p (arg0, arg1, OEP_PURE_SAME)) && operand_equal_p (arg0, arg1, OEP_PURE_SAME))
{ return fold_build2_loc (loc, MULT_EXPR, type,
const REAL_VALUE_TYPE sqrt2_trunc fold_build1_loc (loc, ABS_EXPR, type, arg0),
= real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ()); build_real_truncate (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 NULL_TREE; return NULL_TREE;
} }
...@@ -8529,10 +8516,8 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type) ...@@ -8529,10 +8516,8 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
tree arg = CALL_EXPR_ARG (arg0, 0); tree arg = CALL_EXPR_ARG (arg0, 0);
if (tree_expr_nonnegative_p (arg)) if (tree_expr_nonnegative_p (arg))
{ {
const REAL_VALUE_TYPE dconstroot tree c = build_real_truncate (type, dconst_third ());
= real_value_truncate (TYPE_MODE (type), dconst_third ()); tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, c);
tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
build_real (type, dconstroot));
return build_call_expr_loc (loc, fndecl, 2, arg, narg1); return build_call_expr_loc (loc, fndecl, 2, arg, narg1);
} }
} }
......
...@@ -2189,8 +2189,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -2189,8 +2189,7 @@ along with GCC; see the file COPYING3. If not see
{ {
CASE_FLT_FN (BUILT_IN_EXP): CASE_FLT_FN (BUILT_IN_EXP):
/* Prepare to do logN(exp(exponent) -> exponent*logN(e). */ /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
x = build_real (type, real_value_truncate (TYPE_MODE (type), x = build_real_truncate (type, dconst_e ());
dconst_e ()));
break; break;
CASE_FLT_FN (BUILT_IN_EXP2): CASE_FLT_FN (BUILT_IN_EXP2):
/* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */ /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
...@@ -2226,8 +2225,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -2226,8 +2225,7 @@ along with GCC; see the file COPYING3. If not see
break; break;
CASE_FLT_FN (BUILT_IN_CBRT): CASE_FLT_FN (BUILT_IN_CBRT):
/* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */ /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
x = build_real (type, real_value_truncate (TYPE_MODE (type), x = build_real_truncate (type, dconst_third ());
dconst_third ()));
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
......
...@@ -440,6 +440,9 @@ bool real_can_shorten_arithmetic (machine_mode, machine_mode); ...@@ -440,6 +440,9 @@ bool real_can_shorten_arithmetic (machine_mode, machine_mode);
/* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */ /* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */
extern tree build_real (tree, REAL_VALUE_TYPE); 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. */ /* Calculate R as X raised to the integer exponent N in mode MODE. */
extern bool real_powi (REAL_VALUE_TYPE *, machine_mode, extern bool real_powi (REAL_VALUE_TYPE *, machine_mode,
const REAL_VALUE_TYPE *, HOST_WIDE_INT); const REAL_VALUE_TYPE *, HOST_WIDE_INT);
......
...@@ -1877,6 +1877,14 @@ build_real (tree type, REAL_VALUE_TYPE d) ...@@ -1877,6 +1877,14 @@ build_real (tree type, REAL_VALUE_TYPE d)
return v; 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 /* Return a new REAL_CST node whose type is TYPE
and whose value is the integer value of the INTEGER_CST node I. */ and whose value is the integer value of the INTEGER_CST node I. */
...@@ -12093,7 +12101,7 @@ strip_float_extensions (tree exp) ...@@ -12093,7 +12101,7 @@ strip_float_extensions (tree exp)
&& exact_real_truncate (TYPE_MODE (double_type_node), &orig)) && exact_real_truncate (TYPE_MODE (double_type_node), &orig))
type = double_type_node; type = double_type_node;
if (type) if (type)
return build_real (type, real_value_truncate (TYPE_MODE (type), orig)); return build_real_truncate (type, orig);
} }
if (!CONVERT_EXPR_P (exp)) if (!CONVERT_EXPR_P (exp))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment