On Wed, Oct 22, 2014 at 04:20:09PM +0200, Richard Biener wrote:
> 2014-10-22  Richard Biener  <rguent...@suse.de>
> 
>       * genmatch.c (count_captures): New function.
>       (dt_simplify::gen): Handle preserving side-effects for
>       GENERIC code generation.
>       (decision_tree::gen_generic): Do not reject operands
>       with TREE_SIDE_EFFECTS.
> 
> Index: gcc/genmatch.c
> ===================================================================
> --- gcc/genmatch.c    (revision 216549)
> +++ gcc/genmatch.c    (working copy)
> @@ -1861,6 +1861,46 @@ dt_operand::gen (FILE *f, bool gimple)
>      fprintf (f, "}\n");
>  }
>  
> +/* Count how many times captures are substituted in O and put the
> +   result in the array of counters CPT.  Return false if the
> +   counting isn't precise.  */
> +
> +static bool
> +count_captures (operand *o, int *cpt)
> +{
> +  if (capture *c = dyn_cast <capture *> (o))
> +    {
> +      /* Give up for non-leafs (CSEs).  */
> +      if (c->what)
> +     return false;
> +      cpt[c->where]++;
> +    }
> +  else if (expr *e = dyn_cast <expr *> (o))
> +    {
> +      /* Give up for conditionally executed operands.  */
> +      if (*e->operation == COND_EXPR
> +       || *e->operation == TRUTH_ANDIF_EXPR
> +       || *e->operation == TRUTH_ORIF_EXPR)
> +     return false;

As discussed on IRC, the problem is only captures inside of 2nd and 3rd
operand of COND_EXPR or 2nd operand of TRUTH_*IF_EXPR if the
first operand of those isn't constant (if it is constant, then depending
on the zero/nonzero value it should be either counted or ignored).
Captures in first operands of those are not a problem.

> @@ -1983,10 +2042,21 @@ dt_simplify::gen (FILE *f, bool gimple)
>      }
>    else /* GENERIC */
>      {
> +      bool is_predicate = false;
>        if (result->type == operand::OP_EXPR)
>       {
>         expr *e = as_a <expr *> (result);
> -       bool is_predicate = is_a <predicate_id *> (e->operation);
> +       is_predicate = is_a <predicate_id *> (e->operation);
> +       /* Search for captures used multiple times in the result expression
> +          and dependent on TREE_SIDE_EFFECTS emit a SAVE_EXPR.  */
> +       if (!is_predicate && cpt[0] != -1)
> +         for (int i = 0; i < s->capture_max + 1; ++i)
> +           {
> +             if (cpt[i] > 1)
> +               fprintf (f, "  if (TREE_SIDE_EFFECTS (captures[%d]))\n"
> +                        "    captures[%d] = save_expr (captures[%d]);\n",
> +                        i, i, i);
> +           }

For SAVE_EXPRs this will not do anything, which is right.

> +      if (!is_predicate)
> +     {
> +       /* Search for captures not used in the result expression and dependent
> +          on TREE_SIDE_EFFECTS emit omit_one_operand.  */
> +       if (cpt[0] != -1)
> +         for (int i = 0; i < s->capture_max + 1; ++i)
> +           {
> +             if (cpt[i] == 0)
> +               fprintf (f, "  if (TREE_SIDE_EFFECTS (captures[%d]))\n"
> +                        "    res = build2_loc (loc, COMPOUND_EXPR, "
> +                        "TREE_TYPE (captures[%d]), "
> +                        "fold_ignored_result (captures[%d]), res);\n",
> +                        i, i, i);
> +           }
> +       fprintf (f, "  return res;\n");
> +     }

For this case if captures[%d] happens to be a SAVE_EXPR, you
could perhaps avoid the COMPOUND_EXPR addition if the SAVE_EXPR is already
present somewhere else in the res (in unconditional context).  Not sure
if it is worth the check (pretty much it would want a function which would
only add the COMPOUND_EXPR if the capture is not SAVE_EXPR or not found in
the expression).

Also, don't you want TREE_NO_WARNING on the COMPOUND_EXPR to avoid
-Wunused-value warnings (at least temporarily until C++ FE is fixed not to
fold everything early)?

And, perhaps it is better to queue all side-effects in lhs of toplevel
COMPOUND_EXPR, rather than having a chain of COMPOUND_EXPRs on the rhs?
I.e. first queue all side-effects into some temporary and if that temporary
is non-NULL, just add a single COMPOUND_EXPR with res as rhs and that
temporary as lhs.

Do we want to special case COMPOUND_EXPRs in further optimizations, or will
it be handled automatically (I mean, if trying to simplify
(something, expr1) op expr2
where expr1 op expr2 simplifies into something into
(something, result_of_simplification (expr1 op expr2)).

        Jakub

Reply via email to