Hi,

  There is a match-folding issue derived from pr94234.  A piece of code like:

  int foo (int n)
  {
     int t1 = 8 * n;
     int t2 = 8 * (n - 1);

     return t1 - t2;
  }

 It can be perfectly caught by the rule "(A * C) +- (B * C) -> (A +- B) * C", 
and
 be folded to constant "8". But this folding will fail if both v1 and v2 have
multiple uses, as the following code.

  int foo (int n)
  {
     int t1 = 8 * n;
     int t2 = 8 * (n - 1);

     use_fn (t1, t2);
     return t1 - t2;
  }

Given an expression with non-single-use operands, folding it will introduce
duplicated computation in most situations, and is deemed to be unprofitable.
But it is always beneficial if final result is a constant or existing SSA value.

And the rule is:
  (simplify
   (plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
   (if ((!ANY_INTEGRAL_TYPE_P (type)
         || TYPE_OVERFLOW_WRAPS (type)
         || (INTEGRAL_TYPE_P (type)
             && tree_expr_nonzero_p (@0)
             && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
        /* If @1 +- @2 is constant require a hard single-use on either
           original operand (but not on both).  */
        && (single_use (@3) || single_use (@4)))   <----- control whether match 
or not
    (mult (plusminus @1 @2) @0)))

Current matcher only provides a way to check something before folding,
but no mechanism to affect decision after folding. If has, for the above
case, we can let it go when we find result is a constant.

Like the way to describe input operand using flags, we could also add
a new flag to specify this kind of constraint on output that we expect
it is a simple gimple value.

Proposed syntax is

  (opcode:v{ condition } ....)

The char "v" stands for gimple value, if more descriptive, other char is
preferred. "condition" enclosed by { } is an optional c-syntax condition
expression. If present, only when "condition" is met, matcher will check
whether folding result is a gimple value using
gimple_simplified_result_is_gimple_val ().

Since there is no SSA concept in GENERIC, this is only for GIMPLE-match,
not GENERIC-match.

With this syntax, the rule is changed to

#Form 1:
  (simplify
   (plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
   (if ((!ANY_INTEGRAL_TYPE_P (type)
         || TYPE_OVERFLOW_WRAPS (type)
         || (INTEGRAL_TYPE_P (type)
             && tree_expr_nonzero_p (@0)
             && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type))))))
       ( if (!single_use (@3) && !single_use (@4))
          (mult:v (plusminus @1 @2) @0)))
          (mult (plusminus @1 @2) @0)))))

#Form 2:
  (simplify
   (plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
   (if ((!ANY_INTEGRAL_TYPE_P (type)
         || TYPE_OVERFLOW_WRAPS (type)
         || (INTEGRAL_TYPE_P (type)
             && tree_expr_nonzero_p (@0)
             && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type))))))
      (mult:v{ !single_use (@3) && !single_use (@4 } (plusminus @1 @2) @0))))

This is just a proposal, has not been implemented. Hope your comments
on this.

Best Regards,
Feng

Reply via email to