gimple-ssa-store-merging.c (struct store_immediate_info): Add bit_not_p field.
authorJakub Jelinek <jakub@redhat.com>
Thu, 9 Nov 2017 19:24:59 +0000 (20:24 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 9 Nov 2017 19:24:59 +0000 (20:24 +0100)
* 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.

From-SVN: r254606

gcc/ChangeLog
gcc/gimple-ssa-store-merging.c

index b5106cfc93ec739a05e7e80bca2a4940d896e2ee..0dc2057c08d49558357a8062c7000daec6ad79ec 100644 (file)
@@ -1,3 +1,18 @@
+2017-11-09  Jakub Jelinek  <jakub@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.
+
 2017-11-09  Jim Wilson  <jimw@sifive.com>
 
        * collect2.c (OBJECT_FORMAT_COFF): Remove EXTENDED_COFF support.
index 4bae70dc7ac6fd3bdd6344b9fa9ffa377be4a376..421498beafb7093128c5ab3b73d5c47c5ba7a4bd 100644 (file)
@@ -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_info (unsigned HOST_WIDE_INT bs,
                                            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_stores ()
         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_info *info)
     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, bool allow_unaligned_store,
        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, bool allow_unaligned_store,
        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_store (merged_store_group *group)
              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_operand_info *op,
          && 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 (gimple *stmt)
                  || ((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 (gimple *stmt)
       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 (gimple *stmt)
       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 (gimple *stmt)
     = 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))