diff mbox

[RFC,PR40921] Convert x + (-y * z * z) into x - y * z * z

Message ID 56D42341.5090607@linaro.org
State New
Headers show

Commit Message

Kugan Vivekanandarajah Feb. 29, 2016, 10:53 a.m. UTC
>

> Err.  I think the way you implement that in reassoc is ad-hoc and not

> related to reassoc at all.

>

> In fact what reassoc is missing is to handle

>

>   -y * z * (-w) * x -> y * x * w * x

>

> thus optimize negates as if they were additional * -1 entries in a

> multiplication chain.  And

> then optimize a single remaining * -1 in the result chain to a negate.

>

> Then match.pd handles x + (-y) -> x - y (independent of -frounding-math btw).

>

> So no, this isn't ok as-is, IMHO you want to expand the multiplication ops chain

> pulling in the * -1 ops (if single-use, of course).

>


I agree. Here is the updated patch along what you suggested. Does this 
look better ?

Thanks,
Kugan

Comments

Kugan Vivekanandarajah April 21, 2016, 11:12 a.m. UTC | #1
Hi Richard,

On 19/04/16 22:11, Richard Biener wrote:
> On Tue, Apr 19, 2016 at 1:36 PM, Richard Biener

> <richard.guenther@gmail.com> wrote:

>> On Tue, Apr 19, 2016 at 1:35 PM, Richard Biener

>> <richard.guenther@gmail.com> wrote:

>>> On Mon, Feb 29, 2016 at 11:53 AM, kugan

>>> <kugan.vivekanandarajah@linaro.org> wrote:

>>>>>

>>>>> Err.  I think the way you implement that in reassoc is ad-hoc and not

>>>>> related to reassoc at all.

>>>>>

>>>>> In fact what reassoc is missing is to handle

>>>>>

>>>>>    -y * z * (-w) * x -> y * x * w * x

>>>>>

>>>>> thus optimize negates as if they were additional * -1 entries in a

>>>>> multiplication chain.  And

>>>>> then optimize a single remaining * -1 in the result chain to a negate.

>>>>>

>>>>> Then match.pd handles x + (-y) -> x - y (independent of -frounding-math

>>>>> btw).

>>>>>

>>>>> So no, this isn't ok as-is, IMHO you want to expand the multiplication ops

>>>>> chain

>>>>> pulling in the * -1 ops (if single-use, of course).

>>>>>

>>>>

>>>> I agree. Here is the updated patch along what you suggested. Does this look

>>>> better ?

>>>

>>> It looks better but I think you want to do factor_out_negate_expr before the

>>> first qsort/optimize_ops_list call to catch -1. * z * (-w) which also means you

>>> want to simply append a -1. to the ops list rather than adjusting the result

>>> with a negate stmt.

>>>

>>> You also need to guard all this with ! HONOR_SNANS (type) && (!

>>> HONOR_SIGNED_ZEROS (type)

>>> || ! COMPLEX_FLOAT_TYPE_P (type)) (see match.pd pattern transforming x

>>> * -1. to -x).

>>

>> And please add at least one testcase.

>

> And it appears to me that you could handle this in linearize_expr_tree

> as well, similar

> to how we handle MULT_EXPR with acceptable_pow_call there by adding -1. and

> op into the ops vec.

>



I am not sure I understand this. I tried doing this. If I add  -1 and 
rhs1 for the NEGATE_EXPR to ops list,  when it come to rewrite_expr_tree 
constant will be sorted early and would make it hard to generate:
  x + (-y * z * z) => x - y * z * z

Do you want to swap the constant in MULT_EXPR chain (if present) like in 
swap_ops_for_binary_stmt and then create a NEGATE_EXPR ?


Thanks,
Kugan

> Similar for the x + x + x -> 3 * x case we'd want to add a repeat op when seeing

> x + 3 * x + x and use ->count in that patch as well.

>

> Best split out the

>

>    if (rhscode == MULT_EXPR

>        && TREE_CODE (binrhs) == SSA_NAME

>        && acceptable_pow_call (SSA_NAME_DEF_STMT (binrhs), &base, &exponent))

>      {

>        add_repeat_to_ops_vec (ops, base, exponent);

>        gimple_set_visited (SSA_NAME_DEF_STMT (binrhs), true);

>      }

>    else

>      add_to_ops_vec (ops, binrhs);

>

> pattern into a helper that handles the other cases.

>

> Richard.

>

>> Richard.

>>

>>> Richard.

>>>

>>>> Thanks,

>>>> Kugan
diff mbox

Patch

diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 17eb64f..bbb5ffb 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -4674,6 +4674,41 @@  attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *ops)
   return result;
 }
 
+/* Factor out NEGATE_EXPR from the multiplication operands.  */
+static void
+factor_out_negate_expr (gimple_stmt_iterator *gsi,
+			gimple *stmt, vec<operand_entry *> *ops)
+{
+  operand_entry *oe;
+  unsigned int i;
+  int neg_count = 0;
+
+  FOR_EACH_VEC_ELT (*ops, i, oe)
+    {
+      if (TREE_CODE (oe->op) != SSA_NAME
+	  || !has_single_use (oe->op))
+	continue;
+      gimple *def_stmt = SSA_NAME_DEF_STMT (oe->op);
+      if (!is_gimple_assign (def_stmt)
+	  || gimple_assign_rhs_code (def_stmt) != NEGATE_EXPR)
+	continue;
+      oe->op = gimple_assign_rhs1 (def_stmt);
+      neg_count ++;
+    }
+
+  if (neg_count % 2)
+    {
+      tree lhs = gimple_assign_lhs (stmt);
+      tree tmp = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "reassocneg");
+      gimple_set_lhs (stmt, tmp);
+      gassign *neg_stmt = gimple_build_assign (lhs, NEGATE_EXPR,
+					       tmp);
+      gimple_set_location (neg_stmt, gimple_location (stmt));
+      gimple_set_uid (neg_stmt, gimple_uid (stmt));
+      gsi_insert_after (gsi, neg_stmt, GSI_SAME_STMT);
+    }
+}
+
 /* Attempt to optimize
    CST1 * copysign (CST2, y) -> copysign (CST1 * CST2, y) if CST1 > 0, or
    CST1 * copysign (CST2, y) -> -copysign (CST1 * CST2, y) if CST1 < 0.  */
@@ -4917,6 +4952,12 @@  reassociate_bb (basic_block bb)
 	      if (rhs_code == MULT_EXPR)
 		attempt_builtin_copysign (&ops);
 
+	      if (rhs_code == MULT_EXPR)
+		{
+		  factor_out_negate_expr (&gsi, stmt, &ops);
+		  ops.qsort (sort_by_operand_rank);
+		}
+
 	      if (reassoc_insert_powi_p
 		  && rhs_code == MULT_EXPR
 		  && flag_unsafe_math_optimizations)