For single block loops whose exit test is loop invariant,
record_edge_info records an equivalence between each PHI result and
its argument on the entry edge, since this loop would either run once
or never leave.  This came from r13-3004-g1214196da79aab.  However,
the shape it looks for no longer reaches DOM, except when DOM itself
has just folded the exit test to a constant and needs no equivalence
to know what the loop does.  So this is dead code either way.

The loop it was written for (gcc.dg/infinite-loop.c) is handled by ch2
ever since r14-2623-gc11a3aedec2649.  Loop header copying recognizes a
loop invariant exit when it peels the header and removes it from the
loop body.

What does reach DOM in this shape are loops whose exit test DOM has
itself just folded to if (0 != 0) or if (1 != 0).  The code will fire
for those, but the equivalences it records have no effect downstream.
I have tested the equivalences are useless by recording them, not
recording them, and deliberately recording wrong PHI equivalences.  In
any of the cases, the assembly is the same over my benchmark suite.

Interestingly (*), where the exit block has a single predecessor the
walk does install them, but DOM already knows the induction variable's
value from the ranger and nothing after the loop reads it.  Where the
exit block is a join nothing installs them except a candidate jump
thread across the exit edge, and no surviving thread depends on them.

Tested on ppc64le Linux.

Boy this was fun :)...OK for trunk?

(*) I had the robots instrument all this, cause seriously, who does
all this analysis for code that is provably inert.

gcc/ChangeLog:

        * tree-ssa-dom.cc (single_block_loop_p): Remove.
        (record_edge_info): Do not record equivalences on the exit edge of
        a single block loop.
---
 gcc/tree-ssa-dom.cc | 124 --------------------------------------------
 1 file changed, 124 deletions(-)

diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 519661973ec..7a30983572b 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -416,74 +416,6 @@ free_all_edge_infos (void)
     }
 }
 
-/* Return TRUE if BB has precisely two preds, one of which
-   is a backedge from a forwarder block where the forwarder
-   block is a direct successor of BB.  Being a forwarder
-   block, it has no side effects other than transfer of
-   control.  Otherwise return FALSE.  */
-
-static bool
-single_block_loop_p (basic_block bb)
-{
-  /* Two preds.  */
-  if (EDGE_COUNT (bb->preds) != 2)
-    return false;
-
-  /* One and only one of the edges must be marked with
-     EDGE_DFS_BACK.  */
-  basic_block pred = NULL;
-  unsigned int count = 0;
-  if (EDGE_PRED (bb, 0)->flags & EDGE_DFS_BACK)
-    {
-      pred = EDGE_PRED (bb, 0)->src;
-      count++;
-    }
-  if (EDGE_PRED (bb, 1)->flags & EDGE_DFS_BACK)
-    {
-      pred = EDGE_PRED (bb, 1)->src;
-      count++;
-    }
-
-  if (count != 1)
-    return false;
-
-  /* Now examine PRED.  It should have a single predecessor which
-     is BB and a single successor that is also BB.  */
-  if (EDGE_COUNT (pred->preds) != 1
-      || EDGE_COUNT (pred->succs) != 1
-      || EDGE_PRED (pred, 0)->src != bb
-      || EDGE_SUCC (pred, 0)->dest != bb)
-    return false;
-
-  /* This looks good from a CFG standpoint.  Now look at the guts
-     of PRED.  Basically we want to verify there are no PHI nodes
-     and no real statements.  */
-  if (! gimple_seq_empty_p (phi_nodes (pred)))
-    return false;
-
-  gimple_stmt_iterator gsi;
-  for (gsi = gsi_last_bb (pred); !gsi_end_p (gsi); gsi_prev (&gsi))
-    {
-      gimple *stmt = gsi_stmt (gsi);
-
-      switch (gimple_code (stmt))
-       {
-         case GIMPLE_LABEL:
-           if (DECL_NONLOCAL (gimple_label_label (as_a <glabel *> (stmt))))
-             return false;
-           break;
-
-         case GIMPLE_DEBUG:
-           break;
-
-         default:
-           return false;
-       }
-    }
-
-  return true;
-}
-
 /* We have finished optimizing BB, record any information implied by
    taking a specific outgoing edge from BB.  */
 
@@ -655,62 +587,6 @@ record_edge_info (basic_block bb)
               if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
                edge_info->record_simple_equiv (op0, op1);
             }
-
-         /* If this block is a single block loop, then we may be able to
-            record some equivalences on the loop's exit edge.  */
-         if (single_block_loop_p (bb))
-           {
-             /* We know it's a single block loop.  Now look at the loop
-                exit condition.  What we're looking for is whether or not
-                the exit condition is loop invariant which we can detect
-                by checking if all the SSA_NAMEs referenced are defined
-                outside the loop.  */
-             if ((TREE_CODE (op0) != SSA_NAME
-                  || gimple_bb (SSA_NAME_DEF_STMT (op0)) != bb)
-                 && (TREE_CODE (op1) != SSA_NAME
-                     || gimple_bb (SSA_NAME_DEF_STMT (op1)) != bb))
-               {
-                 /* At this point we know the exit condition is loop
-                    invariant.  The only way to get out of the loop is
-                    if it never traverses the backedge to begin with.  This
-                    implies that any PHI nodes create equivalances that we
-                    can attach to the loop exit edge.  */
-                 bool alternative
-                   = (EDGE_PRED (bb, 0)->flags & EDGE_DFS_BACK) ? 1 : 0;
-
-                 gphi_iterator gsi;
-                 for (gsi = gsi_start_phis (bb);
-                      !gsi_end_p (gsi);
-                      gsi_next (&gsi))
-                   {
-                     /* Now get the EDGE_INFO class so we can append
-                        it to our list.  We want the successor edge
-                        where the destination is not the source of
-                        an incoming edge.  */
-                     gphi *phi = gsi.phi ();
-                     tree src = PHI_ARG_DEF (phi, alternative);
-                     tree dst = PHI_RESULT (phi);
-
-                     /* If the other alternative is the same as the result,
-                        then this is a degenerate and can be ignored.  */
-                     if (dst == PHI_ARG_DEF (phi, !alternative))
-                       continue;
-
-                     if (EDGE_SUCC (bb, 0)->dest
-                         != EDGE_PRED (bb, !alternative)->src)
-                       edge_info = (class edge_info *)EDGE_SUCC (bb, 0)->aux;
-                     else
-                       edge_info = (class edge_info *)EDGE_SUCC (bb, 1)->aux;
-
-                     /* Note that since this processing is done independently
-                        of other edge equivalency processing, we may not
-                        have an EDGE_INFO structure set up yet.  */
-                     if (edge_info == NULL)
-                       edge_info = new class edge_info (false_edge);
-                     edge_info->record_simple_equiv (dst, src);
-                   }
-               }
-           }
         }
     }
 }
-- 
2.53.0

Reply via email to