summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-13 12:39:53 +0000
committermatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>2010-04-13 12:39:53 +0000
commitc07e5b8b23ee24d8beedae3817de0543490f40e5 (patch)
tree05699a395708e0a401d3e3d5b87f880893f20ac8
parente212f99af8c85906522c1fe1140a7a1a4bc06d19 (diff)
downloadgcc-c07e5b8b23ee24d8beedae3817de0543490f40e5.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158265 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/negate.c20
-rw-r--r--gcc/tree-ssa-reassoc.c106
4 files changed, 102 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6ba3eca7a99..dfeebd89739 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+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>
PR bootstrap/43737
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d6787752043..2c370c07143 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-04-13 Michael Matz <matz@suse.de>
+
+ * gcc.dg/tree-ssa/negate.c: New testcase.
+
2010-04-13 Richard Guenther <rguenther@suse.de>
PR testsuite/43735
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/negate.c b/gcc/testsuite/gcc.dg/tree-ssa/negate.c
new file mode 100644
index 00000000000..c51f323e710
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/negate.c
@@ -0,0 +1,20 @@
+/* { 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" } } */
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index cf05de5be71..9a623bb3d59 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1707,14 +1707,15 @@ repropagate_negates (void)
{
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
(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
transform the PLUS_EXPR into a MINUS_EXPR. */
- if (user
- && is_gimple_assign (user)
- && gimple_assign_rhs_code (user) == PLUS_EXPR)
+ if (gimple_assign_rhs_code (user) == PLUS_EXPR)
{
/* If the negated operand appears on the LHS of the
PLUS_EXPR, exchange the operands of the PLUS_EXPR
@@ -1737,9 +1738,63 @@ repropagate_negates (void)
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.
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)
gimple stmt = gsi_stmt (gsi);
gimple_set_visited (stmt, false);
+ if (!is_gimple_assign (stmt)
+ || !can_reassociate_p (gimple_assign_lhs (stmt)))
+ continue;
+
/* Look for simple gimple subtract operations. */
- if (is_gimple_assign (stmt)
- && gimple_assign_rhs_code (stmt) == MINUS_EXPR)
+ if (gimple_assign_rhs_code (stmt) == MINUS_EXPR)
{
- tree lhs = gimple_assign_lhs (stmt);
- tree rhs1 = gimple_assign_rhs1 (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))))
+ if (!can_reassociate_p (gimple_assign_rhs1 (stmt))
+ || !can_reassociate_p (gimple_assign_rhs2 (stmt)))
continue;
/* Check for a subtract used only in an addition. If this
@@ -1798,6 +1841,9 @@ break_up_subtract_bb (basic_block bb)
if (should_break_up_subtract (stmt))
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);
son;
@@ -1858,19 +1904,9 @@ reassociate_bb (basic_block bb)
rhs1 = gimple_assign_rhs1 (stmt);
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))))
+ if (!can_reassociate_p (lhs)
+ || !can_reassociate_p (rhs1)
+ || !can_reassociate_p (rhs2))
continue;
if (associative_tree_code (rhs_code))