On Mon, Oct 5, 2026 at 12:30 PM Aldy Hernandez <[email protected]> wrote:
>
> 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?

OK!

> (*) 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