Commit 4adfc9a5 by Richard Sandiford Committed by Richard Sandiford

Remove fold_strip_sign_ops

This patch deletes fold_strip_sign_ops in favour of the
gimple-ssa-backprop.c pass.

Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.

gcc/
	* fold-const.h (fold_strip_sign_ops): Delete.
	* fold-const.c (fold_strip_sign_ops): Likewise.
	(fold_unary_loc, fold_binary_loc): Remove calls to it.
	* builtins.c (fold_builtin_cos, fold_builtin_cosh)
	(fold_builtin_ccos): Delete.
	(fold_builtin_pow): Don't call fold_strip_sign_ops.
	(fold_builtin_hypot, fold_builtin_copysign): Likewise.
	Remove fndecl argument.
	(fold_builtin_1): Update calls accordingly.  Handle constant
	cos, cosh, ccos and ccosh here.

gcc/testsuite/
	* gcc.dg/torture/builtin-symmetric-1.c: Don't run at -O0.

From-SVN: r229140
parent 6a75d560
2015-10-21 Richard Sandiford <richard.sandiford@arm.com> 2015-10-21 Richard Sandiford <richard.sandiford@arm.com>
* fold-const.h (fold_strip_sign_ops): Delete.
* fold-const.c (fold_strip_sign_ops): Likewise.
(fold_unary_loc, fold_binary_loc): Remove calls to it.
* builtins.c (fold_builtin_cos, fold_builtin_cosh)
(fold_builtin_ccos): Delete.
(fold_builtin_pow): Don't call fold_strip_sign_ops.
(fold_builtin_hypot, fold_builtin_copysign): Likewise.
Remove fndecl argument.
(fold_builtin_1): Update calls accordingly. Handle constant
cos, cosh, ccos and ccosh here.
2015-10-21 Richard Sandiford <richard.sandiford@arm.com>
* doc/invoke.texi (-fdump-tree-backprop, -fssa-backprop): Document. * doc/invoke.texi (-fdump-tree-backprop, -fssa-backprop): Document.
* Makefile.in (OBJS): Add gimple-ssa-backprop.o. * Makefile.in (OBJS): Add gimple-ssa-backprop.o.
* common.opt (fssa-backprop): New option. * common.opt (fssa-backprop): New option.
...@@ -160,8 +160,6 @@ static rtx expand_builtin_fabs (tree, rtx, rtx); ...@@ -160,8 +160,6 @@ static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_signbit (tree, rtx); static rtx expand_builtin_signbit (tree, rtx);
static tree fold_builtin_pow (location_t, tree, tree, tree, tree); static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
static tree fold_builtin_powi (location_t, tree, tree, tree, tree); static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
static tree fold_builtin_cos (location_t, tree, tree, tree);
static tree fold_builtin_cosh (location_t, tree, tree, tree);
static tree fold_builtin_tan (tree, tree); static tree fold_builtin_tan (tree, tree);
static tree fold_builtin_trunc (location_t, tree, tree); static tree fold_builtin_trunc (location_t, tree, tree);
static tree fold_builtin_floor (location_t, tree, tree); static tree fold_builtin_floor (location_t, tree, tree);
...@@ -175,7 +173,6 @@ static tree fold_builtin_memcmp (location_t, tree, tree, tree); ...@@ -175,7 +173,6 @@ static tree fold_builtin_memcmp (location_t, tree, tree, tree);
static tree fold_builtin_strcmp (location_t, tree, tree); static tree fold_builtin_strcmp (location_t, tree, tree);
static tree fold_builtin_strncmp (location_t, tree, tree, tree); static tree fold_builtin_strncmp (location_t, tree, tree, tree);
static tree fold_builtin_signbit (location_t, tree, tree); static tree fold_builtin_signbit (location_t, tree, tree);
static tree fold_builtin_copysign (location_t, tree, tree, tree, tree);
static tree fold_builtin_isascii (location_t, tree); static tree fold_builtin_isascii (location_t, tree);
static tree fold_builtin_toascii (location_t, tree); static tree fold_builtin_toascii (location_t, tree);
static tree fold_builtin_isdigit (location_t, tree); static tree fold_builtin_isdigit (location_t, tree);
...@@ -7661,77 +7658,6 @@ fold_builtin_cproj (location_t loc, tree arg, tree type) ...@@ -7661,77 +7658,6 @@ fold_builtin_cproj (location_t loc, tree arg, tree type)
return NULL_TREE; return NULL_TREE;
} }
/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
TYPE is the type of the return value. Return NULL_TREE if no
simplification can be made. */
static tree
fold_builtin_cos (location_t loc,
tree arg, tree type, tree fndecl)
{
tree res, narg;
if (!validate_arg (arg, REAL_TYPE))
return NULL_TREE;
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
return res;
/* Optimize cos(-x) into cos (x). */
if ((narg = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, narg);
return NULL_TREE;
}
/* Fold function call to builtin cosh, coshf, or coshl with argument ARG.
Return NULL_TREE if no simplification can be made. */
static tree
fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl)
{
if (validate_arg (arg, REAL_TYPE))
{
tree res, narg;
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
return res;
/* Optimize cosh(-x) into cosh (x). */
if ((narg = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, narg);
}
return NULL_TREE;
}
/* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with
argument ARG. TYPE is the type of the return value. Return
NULL_TREE if no simplification can be made. */
static tree
fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
bool hyper)
{
if (validate_arg (arg, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree tmp;
/* Calculate the result when the argument is a constant. */
if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
return tmp;
/* Optimize fn(-x) into fn(x). */
if ((tmp = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, tmp);
}
return NULL_TREE;
}
/* Fold function call to builtin tan, tanf, or tanl with argument ARG. /* Fold function call to builtin tan, tanf, or tanl with argument ARG.
Return NULL_TREE if no simplification can be made. */ Return NULL_TREE if no simplification can be made. */
...@@ -8147,10 +8073,9 @@ fold_builtin_bswap (tree fndecl, tree arg) ...@@ -8147,10 +8073,9 @@ fold_builtin_bswap (tree fndecl, tree arg)
NULL_TREE if no simplification can be made. */ NULL_TREE if no simplification can be made. */
static tree static tree
fold_builtin_hypot (location_t loc, tree fndecl, fold_builtin_hypot (location_t loc, tree arg0, tree arg1, tree type)
tree arg0, tree arg1, tree type)
{ {
tree res, narg0, narg1; tree res;
if (!validate_arg (arg0, REAL_TYPE) if (!validate_arg (arg0, REAL_TYPE)
|| !validate_arg (arg1, REAL_TYPE)) || !validate_arg (arg1, REAL_TYPE))
...@@ -8160,16 +8085,6 @@ fold_builtin_hypot (location_t loc, tree fndecl, ...@@ -8160,16 +8085,6 @@ fold_builtin_hypot (location_t loc, tree fndecl,
if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot))) if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
return res; return res;
/* If either argument to hypot has a negate or abs, strip that off.
E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
narg0 = fold_strip_sign_ops (arg0);
narg1 = fold_strip_sign_ops (arg1);
if (narg0 || narg1)
{
return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
narg1 ? narg1 : arg1);
}
/* If either argument is zero, hypot is fabs of the other. */ /* If either argument is zero, hypot is fabs of the other. */
if (real_zerop (arg0)) if (real_zerop (arg0))
return fold_build1_loc (loc, ABS_EXPR, type, arg1); return fold_build1_loc (loc, ABS_EXPR, type, arg1);
...@@ -8274,14 +8189,6 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type) ...@@ -8274,14 +8189,6 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
if (flag_unsafe_math_optimizations || !inexact) if (flag_unsafe_math_optimizations || !inexact)
return build_real (type, x); return build_real (type, x);
} }
/* Strip sign ops from even integer powers. */
if ((n & 1) == 0 && flag_unsafe_math_optimizations)
{
tree narg0 = fold_strip_sign_ops (arg0);
if (narg0)
return build_call_expr_loc (loc, fndecl, 2, narg0, arg1);
}
} }
} }
...@@ -8729,11 +8636,8 @@ fold_builtin_signbit (location_t loc, tree arg, tree type) ...@@ -8729,11 +8636,8 @@ fold_builtin_signbit (location_t loc, tree arg, tree type)
be made. */ be made. */
static tree static tree
fold_builtin_copysign (location_t loc, tree fndecl, fold_builtin_copysign (location_t loc, tree arg1, tree arg2, tree type)
tree arg1, tree arg2, tree type)
{ {
tree tem;
if (!validate_arg (arg1, REAL_TYPE) if (!validate_arg (arg1, REAL_TYPE)
|| !validate_arg (arg2, REAL_TYPE)) || !validate_arg (arg2, REAL_TYPE))
return NULL_TREE; return NULL_TREE;
...@@ -8764,11 +8668,6 @@ fold_builtin_copysign (location_t loc, tree fndecl, ...@@ -8764,11 +8668,6 @@ fold_builtin_copysign (location_t loc, tree fndecl,
fold_build1_loc (loc, ABS_EXPR, type, arg1), fold_build1_loc (loc, ABS_EXPR, type, arg1),
arg2); arg2);
/* Strip sign changing operations for the first argument. */
tem = fold_strip_sign_ops (arg1);
if (tem)
return build_call_expr_loc (loc, fndecl, 2, tem, arg2);
return NULL_TREE; return NULL_TREE;
} }
...@@ -9669,10 +9568,16 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) ...@@ -9669,10 +9568,16 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
break; break;
CASE_FLT_FN (BUILT_IN_CCOS): CASE_FLT_FN (BUILT_IN_CCOS):
return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ false); if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_cos);
break;
CASE_FLT_FN (BUILT_IN_CCOSH): CASE_FLT_FN (BUILT_IN_CCOSH):
return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ true); if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_cosh);
break;
CASE_FLT_FN (BUILT_IN_CPROJ): CASE_FLT_FN (BUILT_IN_CPROJ):
return fold_builtin_cproj (loc, arg0, type); return fold_builtin_cproj (loc, arg0, type);
...@@ -9805,7 +9710,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) ...@@ -9805,7 +9710,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
break; break;
CASE_FLT_FN (BUILT_IN_COS): CASE_FLT_FN (BUILT_IN_COS):
return fold_builtin_cos (loc, arg0, type, fndecl); if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_cos, NULL, NULL, 0);
break;
CASE_FLT_FN (BUILT_IN_TAN): CASE_FLT_FN (BUILT_IN_TAN):
return fold_builtin_tan (arg0, type); return fold_builtin_tan (arg0, type);
...@@ -9824,7 +9731,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) ...@@ -9824,7 +9731,9 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
break; break;
CASE_FLT_FN (BUILT_IN_COSH): CASE_FLT_FN (BUILT_IN_COSH):
return fold_builtin_cosh (loc, arg0, type, fndecl); if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_cosh, NULL, NULL, 0);
break;
CASE_FLT_FN (BUILT_IN_TANH): CASE_FLT_FN (BUILT_IN_TANH):
if (validate_arg (arg0, REAL_TYPE)) if (validate_arg (arg0, REAL_TYPE))
...@@ -10078,7 +9987,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1) ...@@ -10078,7 +9987,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
break; break;
CASE_FLT_FN (BUILT_IN_HYPOT): CASE_FLT_FN (BUILT_IN_HYPOT):
return fold_builtin_hypot (loc, fndecl, arg0, arg1, type); return fold_builtin_hypot (loc, arg0, arg1, type);
CASE_FLT_FN (BUILT_IN_CPOW): CASE_FLT_FN (BUILT_IN_CPOW):
if (validate_arg (arg0, COMPLEX_TYPE) if (validate_arg (arg0, COMPLEX_TYPE)
...@@ -10134,7 +10043,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1) ...@@ -10134,7 +10043,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
return fold_builtin_powi (loc, fndecl, arg0, arg1, type); return fold_builtin_powi (loc, fndecl, arg0, arg1, type);
CASE_FLT_FN (BUILT_IN_COPYSIGN): CASE_FLT_FN (BUILT_IN_COPYSIGN):
return fold_builtin_copysign (loc, fndecl, arg0, arg1, type); return fold_builtin_copysign (loc, arg0, arg1, type);
CASE_FLT_FN (BUILT_IN_FMIN): CASE_FLT_FN (BUILT_IN_FMIN):
return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false); return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false);
......
...@@ -7803,15 +7803,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) ...@@ -7803,15 +7803,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
TREE_TYPE (targ0), TREE_TYPE (targ0),
targ0)); targ0));
} }
/* Strip sign ops from argument. */
if (TREE_CODE (type) == REAL_TYPE)
{
tem = fold_strip_sign_ops (arg0);
if (tem)
return fold_build1_loc (loc, ABS_EXPR, type,
fold_convert_loc (loc, type, tem));
}
return NULL_TREE; return NULL_TREE;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
...@@ -9859,17 +9850,6 @@ fold_binary_loc (location_t loc, ...@@ -9859,17 +9850,6 @@ fold_binary_loc (location_t loc,
} }
else else
{ {
/* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */
if (operand_equal_p (arg0, arg1, 0))
{
tree tem = fold_strip_sign_ops (arg0);
if (tem != NULL_TREE)
{
tem = fold_convert_loc (loc, type, tem);
return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
}
}
/* Fold z * +-I to __complex__ (-+__imag z, +-__real z). /* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
This is not the same for NaNs or if signed zeros are This is not the same for NaNs or if signed zeros are
involved. */ involved. */
...@@ -14252,82 +14232,6 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff) ...@@ -14252,82 +14232,6 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
return true; return true;
} }
/* Simplify the floating point expression EXP when the sign of the
result is not significant. Return NULL_TREE if no simplification
is possible. */
tree
fold_strip_sign_ops (tree exp)
{
tree arg0, arg1;
location_t loc = EXPR_LOCATION (exp);
switch (TREE_CODE (exp))
{
case ABS_EXPR:
case NEGATE_EXPR:
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
return arg0 ? arg0 : TREE_OPERAND (exp, 0);
case MULT_EXPR:
case RDIV_EXPR:
if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (exp)))
return NULL_TREE;
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
if (arg0 != NULL_TREE || arg1 != NULL_TREE)
return fold_build2_loc (loc, TREE_CODE (exp), TREE_TYPE (exp),
arg0 ? arg0 : TREE_OPERAND (exp, 0),
arg1 ? arg1 : TREE_OPERAND (exp, 1));
break;
case COMPOUND_EXPR:
arg0 = TREE_OPERAND (exp, 0);
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
if (arg1)
return fold_build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
break;
case COND_EXPR:
arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 2));
if (arg0 || arg1)
return fold_build3_loc (loc,
COND_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0),
arg0 ? arg0 : TREE_OPERAND (exp, 1),
arg1 ? arg1 : TREE_OPERAND (exp, 2));
break;
case CALL_EXPR:
{
const enum built_in_function fcode = builtin_mathfn_code (exp);
switch (fcode)
{
CASE_FLT_FN (BUILT_IN_COPYSIGN):
/* Strip copysign function call, return the 1st argument. */
arg0 = CALL_EXPR_ARG (exp, 0);
arg1 = CALL_EXPR_ARG (exp, 1);
return omit_one_operand_loc (loc, TREE_TYPE (exp), arg0, arg1);
default:
/* Strip sign ops from the argument of "odd" math functions. */
if (negate_mathfn_p (fcode))
{
arg0 = fold_strip_sign_ops (CALL_EXPR_ARG (exp, 0));
if (arg0)
return build_call_expr_loc (loc, get_callee_fndecl (exp), 1, arg0);
}
break;
}
}
break;
default:
break;
}
return NULL_TREE;
}
/* Return OFF converted to a pointer offset type suitable as offset for /* Return OFF converted to a pointer offset type suitable as offset for
POINTER_PLUS_EXPR. Use location LOC for this conversion. */ POINTER_PLUS_EXPR. Use location LOC for this conversion. */
tree tree
......
...@@ -107,7 +107,6 @@ extern tree build_fold_addr_expr_loc (location_t, tree); ...@@ -107,7 +107,6 @@ extern tree build_fold_addr_expr_loc (location_t, tree);
build_fold_addr_expr_with_type_loc (UNKNOWN_LOCATION, (T), TYPE) build_fold_addr_expr_with_type_loc (UNKNOWN_LOCATION, (T), TYPE)
extern tree build_fold_addr_expr_with_type_loc (location_t, tree, tree); extern tree build_fold_addr_expr_with_type_loc (location_t, tree, tree);
extern tree fold_build_cleanup_point_expr (tree type, tree expr); extern tree fold_build_cleanup_point_expr (tree type, tree expr);
extern tree fold_strip_sign_ops (tree);
#define build_fold_indirect_ref(T)\ #define build_fold_indirect_ref(T)\
build_fold_indirect_ref_loc (UNKNOWN_LOCATION, T) build_fold_indirect_ref_loc (UNKNOWN_LOCATION, T)
extern tree build_fold_indirect_ref_loc (location_t, tree); extern tree build_fold_indirect_ref_loc (location_t, tree);
......
2015-10-21 Richard Sandiford <richard.sandiford@arm.com> 2015-10-21 Richard Sandiford <richard.sandiford@arm.com>
* gcc.dg/torture/builtin-symmetric-1.c: Don't run at -O0.
2015-10-21 Richard Sandiford <richard.sandiford@arm.com>
* gcc.dg/tree-ssa/backprop-1.c, gcc.dg/tree-ssa/backprop-2.c, * gcc.dg/tree-ssa/backprop-1.c, gcc.dg/tree-ssa/backprop-2.c,
gcc.dg/tree-ssa/backprop-3.c, gcc.dg/tree-ssa/backprop-4.c, gcc.dg/tree-ssa/backprop-3.c, gcc.dg/tree-ssa/backprop-4.c,
gcc.dg/tree-ssa/backprop-5.c, gcc.dg/tree-ssa/backprop-6.c: New tests. gcc.dg/tree-ssa/backprop-5.c, gcc.dg/tree-ssa/backprop-6.c: New tests.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
/* { dg-do link } */ /* { dg-do link } */
/* { dg-options "-ffast-math" } */ /* { dg-options "-ffast-math" } */
/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
/* All references to link_error should go away at compile-time. */ /* All references to link_error should go away at compile-time. */
extern void link_error(int); extern void link_error(int);
......
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