This moves make_forwarders_with_degenerate_phis to tree-cfg.cc
from tree-ssa-dce.cc to be able to use in a different pass.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

        * tree-ssa-dce.cc (sort_phi_args): Move to tree-cfg.cc.
        (make_forwarders_with_degenerate_phis): Move to tree-cfg.cc.
        (perform_tree_ssa_dce): Update for the updated return type
        of make_forwarders_with_degenerate_phis.
        * tree-cfg.cc (sort_phi_args): Moved from tree-ssa-dce.cc.
        (make_forwarders_with_degenerate_phis): Moved from tree-ssa-dce.cc.
        Update return type to bool and return true if an edge was split.
        * tree-cfg.h (make_forwarders_with_degenerate_phis): New decl.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/tree-cfg.cc     | 211 +++++++++++++++++++++++++++++++++++++++++++
 gcc/tree-cfg.h      |   1 +
 gcc/tree-ssa-dce.cc | 212 +-------------------------------------------
 3 files changed, 214 insertions(+), 210 deletions(-)

diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index 1d20e6ab6ba..243740e8e21 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -10173,6 +10173,217 @@ make_pass_fixup_cfg (gcc::context *ctxt)
   return new pass_fixup_cfg (ctxt);
 }
 
+
+/* Sort PHI argument values for make_forwarders_with_degenerate_phis.  */
+
+static int
+sort_phi_args (const void *a_, const void *b_)
+{
+  auto *a = (const std::pair<edge, hashval_t> *) a_;
+  auto *b = (const std::pair<edge, hashval_t> *) b_;
+  hashval_t ha = a->second;
+  hashval_t hb = b->second;
+  if (ha < hb)
+    return -1;
+  else if (ha > hb)
+    return 1;
+  else if (a->first->dest_idx < b->first->dest_idx)
+    return -1;
+  else if (a->first->dest_idx > b->first->dest_idx)
+    return 1;
+  else
+    return 0;
+}
+
+/* Look for a non-virtual PHIs and make a forwarder block when all PHIs
+   have the same argument on a set of edges.  This is to not consider
+   control dependences of individual edges for same values but only for
+   the common set.  Returns true if changed the CFG.  */
+
+bool
+make_forwarders_with_degenerate_phis (function *fn)
+{
+  bool didsomething = false;
+
+  basic_block bb;
+  FOR_EACH_BB_FN (bb, fn)
+    {
+      /* Only PHIs with three or more arguments have opportunities.  */
+      if (EDGE_COUNT (bb->preds) < 3)
+       continue;
+      /* Do not touch loop headers or blocks with abnormal predecessors.
+        ???  This is to avoid creating valid loops here, see PR103458.
+        We might want to improve things to either explicitely add those
+        loops or at least consider blocks with no backedges.  */
+      if (bb->loop_father->header == bb
+         || bb_has_abnormal_pred (bb))
+       continue;
+
+      /* Take one PHI node as template to look for identical
+        arguments.  Build a vector of candidates forming sets
+        of argument edges with equal values.  Note optimality
+        depends on the particular choice of the template PHI
+        since equal arguments are unordered leaving other PHIs
+        with more than one set of equal arguments within this
+        argument range unsorted.  We'd have to break ties by
+        looking at other PHI nodes.  */
+      gphi_iterator gsi = gsi_start_nonvirtual_phis (bb);
+      if (gsi_end_p (gsi))
+       continue;
+      gphi *phi = gsi.phi ();
+      auto_vec<std::pair<edge, hashval_t>, 8> args;
+      bool need_resort = false;
+      for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
+       {
+         edge e = gimple_phi_arg_edge (phi, i);
+         /* Skip abnormal edges since we cannot redirect them.  */
+         if (e->flags & EDGE_ABNORMAL)
+           continue;
+         /* Skip loop exit edges when we are in loop-closed SSA form
+            since the forwarder we'd create does not have a PHI node.  */
+         if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
+             && loop_exit_edge_p (e->src->loop_father, e))
+           continue;
+
+         tree arg = gimple_phi_arg_def (phi, i);
+         if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME)
+           need_resort = true;
+         args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0)));
+       }
+      if (args.length () < 2)
+       continue;
+      args.qsort (sort_phi_args);
+      /* The above sorting can be different between -g and -g0, as e.g. decls
+        can have different uids (-g could have bigger gaps in between them).
+        So, only use that to determine which args are equal, then change
+        second from hash value to smallest dest_idx of the edges which have
+        equal argument and sort again.  If all the phi arguments are
+        constants or SSA_NAME, there is no need for the second sort, the hash
+        values are stable in that case.  */
+      hashval_t hash = args[0].second;
+      args[0].second = args[0].first->dest_idx;
+      bool any_equal = false;
+      for (unsigned i = 1; i < args.length (); ++i)
+       if (hash == args[i].second
+           && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first),
+                               PHI_ARG_DEF_FROM_EDGE (phi, args[i].first)))
+         {
+           args[i].second = args[i - 1].second;
+           any_equal = true;
+         }
+       else
+         {
+           hash = args[i].second;
+           args[i].second = args[i].first->dest_idx;
+         }
+      if (!any_equal)
+       continue;
+      if (need_resort)
+       args.qsort (sort_phi_args);
+
+      /* From the candidates vector now verify true candidates for
+        forwarders and create them.  */
+      gphi *vphi = get_virtual_phi (bb);
+      unsigned start = 0;
+      while (start < args.length () - 1)
+       {
+         unsigned i;
+         for (i = start + 1; i < args.length (); ++i)
+           if (args[start].second != args[i].second)
+             break;
+         /* args[start]..args[i-1] are equal.  */
+         if (start != i - 1)
+           {
+             /* Check all PHI nodes for argument equality
+                except for vops.  */
+             bool equal = true;
+             gphi_iterator gsi2 = gsi;
+             gsi_next (&gsi2);
+             for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
+               {
+                 gphi *phi2 = gsi2.phi ();
+                 if (virtual_operand_p (gimple_phi_result (phi2)))
+                   continue;
+                 tree start_arg
+                   = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first);
+                 for (unsigned j = start + 1; j < i; ++j)
+                   {
+                     if (!operand_equal_p (start_arg,
+                                           PHI_ARG_DEF_FROM_EDGE
+                                             (phi2, args[j].first)))
+                       {
+                         /* Another PHI might have a shorter set of
+                            equivalent args.  Go for that.  */
+                         i = j;
+                         if (j == start + 1)
+                           equal = false;
+                         break;
+                       }
+                   }
+                 if (!equal)
+                   break;
+               }
+             if (equal)
+               {
+                 /* If we are asked to forward all edges the block
+                    has all degenerate PHIs.  Do nothing in that case.  */
+                 if (start == 0
+                     && i == args.length ()
+                     && args.length () == gimple_phi_num_args (phi))
+                   break;
+                 /* Instead of using make_forwarder_block we are
+                    rolling our own variant knowing that the forwarder
+                    does not need PHI nodes apart from eventually
+                    a virtual one.  */
+                 auto_vec<tree, 8> vphi_args;
+                 if (vphi)
+                   {
+                     vphi_args.reserve_exact (i - start);
+                     for (unsigned j = start; j < i; ++j)
+                       vphi_args.quick_push
+                         (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first));
+                   }
+                 free_dominance_info (fn, CDI_DOMINATORS);
+                 basic_block forwarder = split_edge (args[start].first);
+                 profile_count count = profile_count::zero ();
+                 bool irr = false;
+                 for (unsigned j = start + 1; j < i; ++j)
+                   {
+                     edge e = args[j].first;
+                     if (e->flags & EDGE_IRREDUCIBLE_LOOP)
+                       irr = true;
+                     redirect_edge_and_branch_force (e, forwarder);
+                     redirect_edge_var_map_clear (e);
+                     count += e->count ();
+                   }
+                 forwarder->count = count;
+                 if (irr)
+                   {
+                     forwarder->flags |= BB_IRREDUCIBLE_LOOP;
+                     single_succ_edge (forwarder)->flags
+                       |= EDGE_IRREDUCIBLE_LOOP;
+                   }
+
+                 if (vphi)
+                   {
+                     tree def = copy_ssa_name (vphi_args[0]);
+                     gphi *vphi_copy = create_phi_node (def, forwarder);
+                     for (unsigned j = start; j < i; ++j)
+                       add_phi_arg (vphi_copy, vphi_args[j - start],
+                                    args[j].first, UNKNOWN_LOCATION);
+                     SET_PHI_ARG_DEF
+                       (vphi, single_succ_edge (forwarder)->dest_idx, def);
+                   }
+                 didsomething = true;
+               }
+           }
+         /* Continue searching for more opportunities.  */
+         start = i;
+       }
+    }
+  return didsomething;
+}
+
 /* Garbage collection support for edge_def.  */
 
 extern void gt_ggc_mx (tree&);
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index 520bb3aefbd..2e01762f04b 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -114,6 +114,7 @@ extern edge gimple_switch_edge (function *, gswitch *, 
unsigned);
 extern edge gimple_switch_default_edge (function *, gswitch *);
 extern bool cond_only_block_p (basic_block);
 extern void copy_phi_arg_into_existing_phi (edge, edge, bool = false);
+extern bool make_forwarders_with_degenerate_phis (function *);
 
 /* Return true if the LHS of a call should be removed.  */
 
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index 317a0d6179b..9a9f6f93fce 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -1940,214 +1940,6 @@ tree_dce_done (bool aggressive)
   worklist.release ();
 }
 
-/* Sort PHI argument values for make_forwarders_with_degenerate_phis.  */
-
-static int
-sort_phi_args (const void *a_, const void *b_)
-{
-  auto *a = (const std::pair<edge, hashval_t> *) a_;
-  auto *b = (const std::pair<edge, hashval_t> *) b_;
-  hashval_t ha = a->second;
-  hashval_t hb = b->second;
-  if (ha < hb)
-    return -1;
-  else if (ha > hb)
-    return 1;
-  else if (a->first->dest_idx < b->first->dest_idx)
-    return -1;
-  else if (a->first->dest_idx > b->first->dest_idx)
-    return 1;
-  else
-    return 0;
-}
-
-/* Look for a non-virtual PHIs and make a forwarder block when all PHIs
-   have the same argument on a set of edges.  This is to not consider
-   control dependences of individual edges for same values but only for
-   the common set.  */
-
-static unsigned
-make_forwarders_with_degenerate_phis (function *fn)
-{
-  unsigned todo = 0;
-
-  basic_block bb;
-  FOR_EACH_BB_FN (bb, fn)
-    {
-      /* Only PHIs with three or more arguments have opportunities.  */
-      if (EDGE_COUNT (bb->preds) < 3)
-       continue;
-      /* Do not touch loop headers or blocks with abnormal predecessors.
-        ???  This is to avoid creating valid loops here, see PR103458.
-        We might want to improve things to either explicitely add those
-        loops or at least consider blocks with no backedges.  */
-      if (bb->loop_father->header == bb
-         || bb_has_abnormal_pred (bb))
-       continue;
-
-      /* Take one PHI node as template to look for identical
-        arguments.  Build a vector of candidates forming sets
-        of argument edges with equal values.  Note optimality
-        depends on the particular choice of the template PHI
-        since equal arguments are unordered leaving other PHIs
-        with more than one set of equal arguments within this
-        argument range unsorted.  We'd have to break ties by
-        looking at other PHI nodes.  */
-      gphi_iterator gsi = gsi_start_nonvirtual_phis (bb);
-      if (gsi_end_p (gsi))
-       continue;
-      gphi *phi = gsi.phi ();
-      auto_vec<std::pair<edge, hashval_t>, 8> args;
-      bool need_resort = false;
-      for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
-       {
-         edge e = gimple_phi_arg_edge (phi, i);
-         /* Skip abnormal edges since we cannot redirect them.  */
-         if (e->flags & EDGE_ABNORMAL)
-           continue;
-         /* Skip loop exit edges when we are in loop-closed SSA form
-            since the forwarder we'd create does not have a PHI node.  */
-         if (loops_state_satisfies_p (LOOP_CLOSED_SSA)
-             && loop_exit_edge_p (e->src->loop_father, e))
-           continue;
-
-         tree arg = gimple_phi_arg_def (phi, i);
-         if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME)
-           need_resort = true;
-         args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0)));
-       }
-      if (args.length () < 2)
-       continue;
-      args.qsort (sort_phi_args);
-      /* The above sorting can be different between -g and -g0, as e.g. decls
-        can have different uids (-g could have bigger gaps in between them).
-        So, only use that to determine which args are equal, then change
-        second from hash value to smallest dest_idx of the edges which have
-        equal argument and sort again.  If all the phi arguments are
-        constants or SSA_NAME, there is no need for the second sort, the hash
-        values are stable in that case.  */
-      hashval_t hash = args[0].second;
-      args[0].second = args[0].first->dest_idx;
-      bool any_equal = false;
-      for (unsigned i = 1; i < args.length (); ++i)
-       if (hash == args[i].second
-           && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first),
-                               PHI_ARG_DEF_FROM_EDGE (phi, args[i].first)))
-         {
-           args[i].second = args[i - 1].second;
-           any_equal = true;
-         }
-       else
-         {
-           hash = args[i].second;
-           args[i].second = args[i].first->dest_idx;
-         }
-      if (!any_equal)
-       continue;
-      if (need_resort)
-       args.qsort (sort_phi_args);
-
-      /* From the candidates vector now verify true candidates for
-        forwarders and create them.  */
-      gphi *vphi = get_virtual_phi (bb);
-      unsigned start = 0;
-      while (start < args.length () - 1)
-       {
-         unsigned i;
-         for (i = start + 1; i < args.length (); ++i)
-           if (args[start].second != args[i].second)
-             break;
-         /* args[start]..args[i-1] are equal.  */
-         if (start != i - 1)
-           {
-             /* Check all PHI nodes for argument equality.  */
-             bool equal = true;
-             gphi_iterator gsi2 = gsi;
-             gsi_next (&gsi2);
-             for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
-               {
-                 gphi *phi2 = gsi2.phi ();
-                 if (virtual_operand_p (gimple_phi_result (phi2)))
-                   continue;
-                 tree start_arg
-                   = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first);
-                 for (unsigned j = start + 1; j < i; ++j)
-                   {
-                     if (!operand_equal_p (start_arg,
-                                           PHI_ARG_DEF_FROM_EDGE
-                                             (phi2, args[j].first)))
-                       {
-                         /* Another PHI might have a shorter set of
-                            equivalent args.  Go for that.  */
-                         i = j;
-                         if (j == start + 1)
-                           equal = false;
-                         break;
-                       }
-                   }
-                 if (!equal)
-                   break;
-               }
-             if (equal)
-               {
-                 /* If we are asked to forward all edges the block
-                    has all degenerate PHIs.  Do nothing in that case.  */
-                 if (start == 0
-                     && i == args.length ()
-                     && args.length () == gimple_phi_num_args (phi))
-                   break;
-                 /* Instead of using make_forwarder_block we are
-                    rolling our own variant knowing that the forwarder
-                    does not need PHI nodes apart from eventually
-                    a virtual one.  */
-                 auto_vec<tree, 8> vphi_args;
-                 if (vphi)
-                   {
-                     vphi_args.reserve_exact (i - start);
-                     for (unsigned j = start; j < i; ++j)
-                       vphi_args.quick_push
-                         (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first));
-                   }
-                 free_dominance_info (fn, CDI_DOMINATORS);
-                 basic_block forwarder = split_edge (args[start].first);
-                 profile_count count = profile_count::zero ();
-                 bool irr = false;
-                 for (unsigned j = start + 1; j < i; ++j)
-                   {
-                     edge e = args[j].first;
-                     if (e->flags & EDGE_IRREDUCIBLE_LOOP)
-                       irr = true;
-                     redirect_edge_and_branch_force (e, forwarder);
-                     redirect_edge_var_map_clear (e);
-                     count += e->count ();
-                   }
-                 forwarder->count = count;
-                 if (irr)
-                   {
-                     forwarder->flags |= BB_IRREDUCIBLE_LOOP;
-                     single_succ_edge (forwarder)->flags
-                       |= EDGE_IRREDUCIBLE_LOOP;
-                   }
-
-                 if (vphi)
-                   {
-                     tree def = copy_ssa_name (vphi_args[0]);
-                     gphi *vphi_copy = create_phi_node (def, forwarder);
-                     for (unsigned j = start; j < i; ++j)
-                       add_phi_arg (vphi_copy, vphi_args[j - start],
-                                    args[j].first, UNKNOWN_LOCATION);
-                     SET_PHI_ARG_DEF
-                       (vphi, single_succ_edge (forwarder)->dest_idx, def);
-                   }
-                 todo |= TODO_cleanup_cfg;
-               }
-           }
-         /* Continue searching for more opportunities.  */
-         start = i;
-       }
-    }
-  return todo;
-}
 
 /* Main routine to eliminate dead code.
 
@@ -2174,8 +1966,8 @@ perform_tree_ssa_dce (bool aggressive)
       scev_initialize ();
     }
 
-  if (aggressive)
-    todo |= make_forwarders_with_degenerate_phis (cfun);
+  if (aggressive && make_forwarders_with_degenerate_phis (cfun))
+    todo |= TODO_cleanup_cfg;
 
   calculate_dominance_info (CDI_DOMINATORS);
 
-- 
2.43.0

Reply via email to