On Mon, Aug 24, 2020 at 8:20 AM Feng Xue OS via Gcc <gcc@gcc.gnu.org> wrote: > > >> 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. > > > > :s already has a counter-measure where it still folds if the output is at > > most one operation. So this transformation has a counter-counter-measure > > of checking single_use explicitly. And now we want a counter^3-measure... > > > Counter-measure is key factor to matching-cost. ":s" seems to be somewhat > coarse-grained. And here we do need more control over it. > > But ideally, we could decouple these counter-measures from definitions of > match-rule, and let gimple-matcher get a more reasonable match-or-not > decision based on these counters. Anyway, it is another story. > > >> 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))))) > > > > That seems to match what you can do with '!' now (that's very recent).
It's also what :s does but a slight bit more "local". When any operand is marked :s and it has more than a single-use we only allow simplifications that do not require insertion of extra stmts. So basically the above pattern doesn't behave any different than if you omit your :v. Only if you'd place :v on an inner expression there would be a difference. Correlating the inner expression we'd not want to insert new expressions for with a specific :s (or multiple ones) would be a more natural extension of what :s provides. Thus, for the above case (Form 1), you do not need :v at all and :s works. Richard. > Thanks, > Feng