The following fixes a bug in genmatch exposed by adding :s flags to
the (X & C2) >> C1 into (X >> C1) & (C2 >> C1) transform which
hurts PR66948.  We were not properly handling captures of captures
resulting from (convert?:s (bit_and:s ...)) when the convert is
dropped.

This also causes quite some bugs in generic-match.c code generation
with respect to required TREE_SIDE_EFFECTS checks and omit-one-operand
calls.  Thus I am also backporting this to the 4.5 branch (a single
patter is affected there).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
and branch.

Richard.

2015-07-21  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/66948
        * genmatch.c (capture_info::walk_match): Also recurse to
        captures.  Properly compute expr state from captures of
        captures.
        * match.pd: Add single-use guards to
        (X & C2) >> C1 into (X >> C1) & (C2 >> C1) transform.

Index: gcc/genmatch.c
===================================================================
*** gcc/genmatch.c      (revision 226028)
--- gcc/genmatch.c      (working copy)
*************** capture_info::walk_match (operand *o, un
*** 1622,1638 ****
  {
    if (capture *c = dyn_cast <capture *> (o))
      {
!       info[c->where].toplevel_msk |= 1 << toplevel_arg;
!       info[c->where].force_no_side_effects_p |= conditional_p;
!       info[c->where].cond_expr_cond_p |= cond_expr_cond_p;
!       /* Mark expr (non-leaf) captures and recurse.  */
        expr *e;
        if (c->what
          && (e = dyn_cast <expr *> (c->what)))
        {
!         info[c->where].expr_p = true;
!         info[c->where].force_single_use |= e->force_single_use;
!         walk_match (c->what, toplevel_arg, conditional_p, false);
        }
      }
    else if (expr *e = dyn_cast <expr *> (o))
--- 1622,1649 ----
  {
    if (capture *c = dyn_cast <capture *> (o))
      {
!       unsigned where = c->where;
!       info[where].toplevel_msk |= 1 << toplevel_arg;
!       info[where].force_no_side_effects_p |= conditional_p;
!       info[where].cond_expr_cond_p |= cond_expr_cond_p;
!       if (!c->what)
!       return;
!       /* Recurse to exprs and captures.  */
!       if (is_a <capture *> (c->what)
!         || is_a <expr *> (c->what))
!       walk_match (c->what, toplevel_arg, conditional_p, false);
!       /* We need to look past multiple captures to find a captured
!        expression as with conditional converts two captures
!        can be collapsed onto the same expression.  */
!       while (c->what && is_a <capture *> (c->what))
!       c = as_a <capture *> (c->what);
!       /* Mark expr (non-leaf) captures and forced single-use exprs.  */
        expr *e;
        if (c->what
          && (e = dyn_cast <expr *> (c->what)))
        {
!         info[where].expr_p = true;
!         info[where].force_single_use |= e->force_single_use;
        }
      }
    else if (expr *e = dyn_cast <expr *> (o))
Index: gcc/match.pd
===================================================================
*** gcc/match.pd        (revision 226028)
--- gcc/match.pd        (working copy)
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 1052,1058 ****
     (X & C2) >> C1 into (X >> C1) & (C2 >> C1).  */
  (for shift (lshift rshift)
   (simplify
!   (shift (convert? (bit_and @0 INTEGER_CST@2)) INTEGER_CST@1)
    (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
     (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
      (bit_and (shift (convert @0) @1) { mask; })))))
--- 1052,1058 ----
     (X & C2) >> C1 into (X >> C1) & (C2 >> C1).  */
  (for shift (lshift rshift)
   (simplify
!   (shift (convert?:s (bit_and:s @0 INTEGER_CST@2)) INTEGER_CST@1)
    (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
     (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
      (bit_and (shift (convert @0) @1) { mask; })))))

Reply via email to