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
>