On Thu, 9 Nov 2017, Jakub Jelinek wrote:

> Hi!
> 
> The gcc.dg/store_merging_13.c testcase worked when I was bootstrapping the
> patch that introduced it, but doesn't anymore, because match.pd had
> a ~X ^ Y -> ~(X ^ Y) transformation, the code was handling only ~ on
> the loads (== arguments of &/|/^) but not on the result of the bitwise
> binary operation.  The following patch handles inversion of the result
> too, after all even ~X & ~Y is ~(X | Y) and ~X | ~Y is ~(X & Y).
> In addition to this, I've added just in case some earlier passes wouldn't
> do good enough job a check that we don't recognize
> _1 = load; _2 = ~1; _3 = ~1; store = _3; and similar (or arbitrarily more
> chained BIT_NOT_EXPRs), while we'd emit a working code, the has_single_use
> accounting wouldn't be prepared for more than one BIT_NOT_EXPR on one
> operand.
> 
> Ok for trunk if it passes bootstrap/regtest?

Nice.

Ok.
Thanks,
Richard.

> Just managed to reproduce the profiledbootstrap issue, so working on that
> next.
> 
> 2017-11-09  Jakub Jelinek  <ja...@redhat.com>
> 
>       * gimple-ssa-store-merging.c (struct store_immediate_info): Add
>       bit_not_p field.
>       (store_immediate_info::store_immediate_info): Add bitnotp argument,
>       set bit_not_p to it.
>       (imm_store_chain_info::coalesce_immediate_stores): Break group
>       if bit_not_p is different.
>       (count_multiple_uses, split_group,
>       imm_store_chain_info::output_merged_store): Handle info->bit_not_p.
>       (handled_load): Avoid multiple chained BIT_NOT_EXPRs.
>       (pass_store_merging::process_store): Handle BIT_{AND,IOR,XOR}_EXPR
>       result inverted using BIT_NOT_EXPR, compute bit_not_p, pass it
>       to store_immediate_info ctor.
> 
> --- gcc/gimple-ssa-store-merging.c.jj 2017-11-09 12:40:27.000000000 +0100
> +++ gcc/gimple-ssa-store-merging.c    2017-11-09 14:00:46.269673305 +0100
> @@ -209,12 +209,13 @@ struct store_immediate_info
>    /* INTEGER_CST for constant stores, MEM_REF for memory copy or
>       BIT_*_EXPR for logical bitwise operation.  */
>    enum tree_code rhs_code;
> +  bool bit_not_p;
>    /* Operands.  For BIT_*_EXPR rhs_code both operands are used, otherwise
>       just the first one.  */
>    store_operand_info ops[2];
>    store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
>                       unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
> -                     gimple *, unsigned int, enum tree_code,
> +                     gimple *, unsigned int, enum tree_code, bool,
>                       const store_operand_info &,
>                       const store_operand_info &);
>  };
> @@ -226,10 +227,11 @@ store_immediate_info::store_immediate_in
>                                           gimple *st,
>                                           unsigned int ord,
>                                           enum tree_code rhscode,
> +                                         bool bitnotp,
>                                           const store_operand_info &op0r,
>                                           const store_operand_info &op1r)
>    : bitsize (bs), bitpos (bp), bitregion_start (brs), bitregion_end (bre),
> -    stmt (st), order (ord), rhs_code (rhscode)
> +    stmt (st), order (ord), rhs_code (rhscode), bit_not_p (bitnotp)
>  #if __cplusplus >= 201103L
>      , ops { op0r, op1r }
>  {
> @@ -1169,7 +1171,8 @@ imm_store_chain_info::coalesce_immediate
>        Merge it into the current store group.  There can be gaps in between
>        the stores, but there can't be gaps in between bitregions.  */
>        else if (info->bitregion_start <= merged_store->bitregion_end
> -            && info->rhs_code == merged_store->stores[0]->rhs_code)
> +            && info->rhs_code == merged_store->stores[0]->rhs_code
> +            && info->bit_not_p == merged_store->stores[0]->bit_not_p)
>       {
>         store_immediate_info *infof = merged_store->stores[0];
>  
> @@ -1386,6 +1389,17 @@ count_multiple_uses (store_immediate_inf
>      case BIT_AND_EXPR:
>      case BIT_IOR_EXPR:
>      case BIT_XOR_EXPR:
> +      if (info->bit_not_p)
> +     {
> +       if (!has_single_use (gimple_assign_rhs1 (stmt)))
> +         ret = 1; /* Fall through below to return
> +                     the BIT_NOT_EXPR stmt and then
> +                     BIT_{AND,IOR,XOR}_EXPR and anything it
> +                     uses.  */
> +       else
> +         /* stmt is after this the BIT_NOT_EXPR.  */
> +         stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
> +     }
>        if (!has_single_use (gimple_assign_rhs1 (stmt)))
>       {
>         ret += 1 + info->ops[0].bit_not_p;
> @@ -1479,6 +1493,8 @@ split_group (merged_store_group *group,
>       case BIT_AND_EXPR:
>       case BIT_IOR_EXPR:
>       case BIT_XOR_EXPR:
> +       if (info->bit_not_p)
> +         total_orig[0]++; /* The orig BIT_NOT_EXPR stmt.  */
>         total_orig[0]++; /* The orig BIT_*_EXPR stmt.  */
>         break;
>       default:
> @@ -1649,6 +1665,8 @@ split_group (merged_store_group *group,
>       case BIT_AND_EXPR:
>       case BIT_IOR_EXPR:
>       case BIT_XOR_EXPR:
> +       if (info->bit_not_p)
> +         total_new[0] += ret; /* The new BIT_NOT_EXPR stmt.  */
>         total_new[0] += ret; /* The new BIT_*_EXPR stmt.  */
>         break;
>       default:
> @@ -1918,6 +1936,17 @@ imm_store_chain_info::output_merged_stor
>             else
>               gimple_seq_add_stmt_without_update (&seq, stmt);
>             src = gimple_assign_lhs (stmt);
> +           if (split_store->orig_stores[0]->bit_not_p)
> +             {
> +               stmt = gimple_build_assign (make_ssa_name (int_type),
> +                                           BIT_NOT_EXPR, src);
> +               gimple_set_location (stmt, bit_loc);
> +               if (load_addr[1] == NULL_TREE && gsi_bb (load_gsi[0]))
> +                 gimple_seq_add_stmt_without_update (&load_seq[0], stmt);
> +               else
> +                 gimple_seq_add_stmt_without_update (&seq, stmt);
> +               src = gimple_assign_lhs (stmt);
> +             }
>             break;
>           default:
>             src = ops[0];
> @@ -2232,6 +2261,11 @@ handled_load (gimple *stmt, store_operan
>         && handled_load (SSA_NAME_DEF_STMT (rhs1), op, bitsize, bitpos,
>                          bitregion_start, bitregion_end))
>       {
> +       /* Don't allow _1 = load; _2 = ~1; _3 = ~_2; which should have
> +          been optimized earlier, but if allowed here, would confuse the
> +          multiple uses counting.  */
> +       if (op->bit_not_p)
> +         return false;
>         op->bit_not_p = !op->bit_not_p;
>         return true;
>       }
> @@ -2283,6 +2317,7 @@ pass_store_merging::process_store (gimpl
>                 || ((bitsize > MAX_BITSIZE_MODE_ANY_INT)
>                      && (TREE_CODE (rhs) != INTEGER_CST)));
>    enum tree_code rhs_code = ERROR_MARK;
> +  bool bit_not_p = false;
>    store_operand_info ops[2];
>    if (invalid)
>      ;
> @@ -2301,7 +2336,17 @@ pass_store_merging::process_store (gimpl
>        else if (handled_load (def_stmt, &ops[0], bitsize, bitpos,
>                            bitregion_start, bitregion_end))
>       rhs_code = MEM_REF;
> -      else
> +      else if (gimple_assign_rhs_code (def_stmt) == BIT_NOT_EXPR) 
> +     {
> +       tree rhs1 = gimple_assign_rhs1 (def_stmt);
> +       if (TREE_CODE (rhs1) == SSA_NAME
> +           && is_gimple_assign (SSA_NAME_DEF_STMT (rhs1)))
> +         {
> +           bit_not_p = true;
> +           def_stmt = SSA_NAME_DEF_STMT (rhs1);
> +         }
> +     }
> +      if (rhs_code == ERROR_MARK && !invalid)
>       switch ((rhs_code = gimple_assign_rhs_code (def_stmt)))
>         {
>         case BIT_AND_EXPR:
> @@ -2355,7 +2400,7 @@ pass_store_merging::process_store (gimpl
>        unsigned int ord = (*chain_info)->m_store_info.length ();
>        info = new store_immediate_info (bitsize, bitpos, bitregion_start,
>                                      bitregion_end, stmt, ord, rhs_code,
> -                                    ops[0], ops[1]);
> +                                    bit_not_p, ops[0], ops[1]);
>        if (dump_file && (dump_flags & TDF_DETAILS))
>       {
>         fprintf (dump_file, "Recording immediate store from stmt:\n");
> @@ -2383,7 +2428,7 @@ pass_store_merging::process_store (gimpl
>      = new imm_store_chain_info (m_stores_head, base_addr);
>    info = new store_immediate_info (bitsize, bitpos, bitregion_start,
>                                  bitregion_end, stmt, 0, rhs_code,
> -                                ops[0], ops[1]);
> +                                bit_not_p, ops[0], ops[1]);
>    new_chain->m_store_info.safe_push (info);
>    m_stores.put (base_addr, new_chain);
>    if (dump_file && (dump_flags & TDF_DETAILS))
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to