{
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
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
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
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;
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))