Commit 143597ff by Michael Matz Committed by Michael Matz

tree-ssa-reassoc.c (repropagate_negates): Merge negates also into MINUS_EXPRs.

	* tree-ssa-reassoc.c (repropagate_negates): Merge negates also
	into MINUS_EXPRs.
	(can_reassociate_p): New function.
	(break_up_subtract_bb, reassociate_bb): Use it.

testsuite/
	* gcc.dg/tree-ssa/negate.c: New testcase.

From-SVN: r158265
parent 54c5ec4f
2010-04-13 Michael Matz <matz@suse.de>
* tree-ssa-reassoc.c (repropagate_negates): Merge negates also
into MINUS_EXPRs.
(can_reassociate_p): New function.
(break_up_subtract_bb, reassociate_bb): Use it.
2010-04-13 Richard Guenther <rguenther@suse.de> 2010-04-13 Richard Guenther <rguenther@suse.de>
PR bootstrap/43737 PR bootstrap/43737
......
2010-04-13 Michael Matz <matz@suse.de>
* gcc.dg/tree-ssa/negate.c: New testcase.
2010-04-13 Richard Guenther <rguenther@suse.de> 2010-04-13 Richard Guenther <rguenther@suse.de>
PR testsuite/43735 PR testsuite/43735
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-reassoc1" } */
int f (int a, int b)
{
int x = -a;
int y = b - x;
return y;
}
int g (int a, int b)
{
int x = -a;
int y = x - b;
return y;
}
/* There should be two additions now. */
/* { dg-final { scan-tree-dump-times "\\+" 2 "reassoc1"} } */
/* { dg-final { cleanup-tree-dump "reassoc1" } } */
...@@ -1707,14 +1707,15 @@ repropagate_negates (void) ...@@ -1707,14 +1707,15 @@ repropagate_negates (void)
{ {
gimple user = get_single_immediate_use (negate); gimple user = get_single_immediate_use (negate);
if (!user || !is_gimple_assign (user))
continue;
/* The negate operand can be either operand of a PLUS_EXPR /* The negate operand can be either operand of a PLUS_EXPR
(it can be the LHS if the RHS is a constant for example). (it can be the LHS if the RHS is a constant for example).
Force the negate operand to the RHS of the PLUS_EXPR, then Force the negate operand to the RHS of the PLUS_EXPR, then
transform the PLUS_EXPR into a MINUS_EXPR. */ transform the PLUS_EXPR into a MINUS_EXPR. */
if (user if (gimple_assign_rhs_code (user) == PLUS_EXPR)
&& is_gimple_assign (user)
&& gimple_assign_rhs_code (user) == PLUS_EXPR)
{ {
/* If the negated operand appears on the LHS of the /* If the negated operand appears on the LHS of the
PLUS_EXPR, exchange the operands of the PLUS_EXPR PLUS_EXPR, exchange the operands of the PLUS_EXPR
...@@ -1737,9 +1738,63 @@ repropagate_negates (void) ...@@ -1737,9 +1738,63 @@ repropagate_negates (void)
update_stmt (user); update_stmt (user);
} }
} }
else if (gimple_assign_rhs_code (user) == MINUS_EXPR)
{
if (gimple_assign_rhs1 (user) == negate)
{
/* We have
x = -a
y = x - b
which we transform into
x = a + b
y = -x .
This pushes down the negate which we possibly can merge
into some other operation, hence insert it into the
plus_negates vector. */
gimple feed = SSA_NAME_DEF_STMT (negate);
tree a = gimple_assign_rhs1 (feed);
tree rhs2 = gimple_assign_rhs2 (user);
gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2;
gimple_replace_lhs (feed, negate);
gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2);
update_stmt (gsi_stmt (gsi));
gsi2 = gsi_for_stmt (user);
gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, negate, NULL);
update_stmt (gsi_stmt (gsi2));
gsi_move_before (&gsi, &gsi2);
VEC_safe_push (tree, heap, plus_negates,
gimple_assign_lhs (gsi_stmt (gsi2)));
}
else
{
/* Transform "x = -a; y = b - x" into "y = b + a", getting
rid of one operation. */
gimple feed = SSA_NAME_DEF_STMT (negate);
tree a = gimple_assign_rhs1 (feed);
tree rhs1 = gimple_assign_rhs1 (user);
gimple_stmt_iterator gsi = gsi_for_stmt (user);
gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, rhs1, a);
update_stmt (gsi_stmt (gsi));
}
}
} }
} }
/* Returns true if OP is of a type for which we can do reassociation.
That is for integral or non-saturating fixed-point types, and for
floating point type when associative-math is enabled. */
static bool
can_reassociate_p (tree op)
{
tree type = TREE_TYPE (op);
if (INTEGRAL_TYPE_P (type)
|| NON_SAT_FIXED_POINT_TYPE_P (type)
|| (flag_associative_math && SCALAR_FLOAT_TYPE_P (type)))
return true;
return false;
}
/* Break up subtract operations in block BB. /* Break up subtract operations in block BB.
We do this top down because we don't know whether the subtract is We do this top down because we don't know whether the subtract is
...@@ -1768,27 +1823,15 @@ break_up_subtract_bb (basic_block bb) ...@@ -1768,27 +1823,15 @@ break_up_subtract_bb (basic_block bb)
gimple stmt = gsi_stmt (gsi); gimple stmt = gsi_stmt (gsi);
gimple_set_visited (stmt, false); gimple_set_visited (stmt, false);
if (!is_gimple_assign (stmt)
|| !can_reassociate_p (gimple_assign_lhs (stmt)))
continue;
/* Look for simple gimple subtract operations. */ /* Look for simple gimple subtract operations. */
if (is_gimple_assign (stmt) if (gimple_assign_rhs_code (stmt) == MINUS_EXPR)
&& gimple_assign_rhs_code (stmt) == MINUS_EXPR)
{ {
tree lhs = gimple_assign_lhs (stmt); if (!can_reassociate_p (gimple_assign_rhs1 (stmt))
tree rhs1 = gimple_assign_rhs1 (stmt); || !can_reassociate_p (gimple_assign_rhs2 (stmt)))
tree rhs2 = gimple_assign_rhs2 (stmt);
/* If associative-math we can do reassociation for
non-integral types. Or, we can do reassociation for
non-saturating fixed-point types. */
if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
&& (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs1))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs2))
|| !flag_associative_math)
&& (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (lhs))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs1))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs2))))
continue; continue;
/* Check for a subtract used only in an addition. If this /* Check for a subtract used only in an addition. If this
...@@ -1798,6 +1841,9 @@ break_up_subtract_bb (basic_block bb) ...@@ -1798,6 +1841,9 @@ break_up_subtract_bb (basic_block bb)
if (should_break_up_subtract (stmt)) if (should_break_up_subtract (stmt))
break_up_subtract (stmt, &gsi); break_up_subtract (stmt, &gsi);
} }
else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR
&& can_reassociate_p (gimple_assign_rhs1 (stmt)))
VEC_safe_push (tree, heap, plus_negates, gimple_assign_lhs (stmt));
} }
for (son = first_dom_son (CDI_DOMINATORS, bb); for (son = first_dom_son (CDI_DOMINATORS, bb);
son; son;
...@@ -1858,19 +1904,9 @@ reassociate_bb (basic_block bb) ...@@ -1858,19 +1904,9 @@ reassociate_bb (basic_block bb)
rhs1 = gimple_assign_rhs1 (stmt); rhs1 = gimple_assign_rhs1 (stmt);
rhs2 = gimple_assign_rhs2 (stmt); rhs2 = gimple_assign_rhs2 (stmt);
/* If associative-math we can do reassociation for if (!can_reassociate_p (lhs)
non-integral types. Or, we can do reassociation for || !can_reassociate_p (rhs1)
non-saturating fixed-point types. */ || !can_reassociate_p (rhs2))
if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
&& (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs1))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs2))
|| !flag_associative_math)
&& (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (lhs))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs1))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs2))))
continue; continue;
if (associative_tree_code (rhs_code)) if (associative_tree_code (rhs_code))
......
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