On Thu, 27 Aug 2026, Aldy Hernandez wrote:
> Per Richi's suggestion in the PR, making an irreducible region
> reducible is a good thing, so instead of preventing it just let loop
> fixup discover the new loop: set LOOPS_NEED_FIXUP when we changed the
> CFG, and drop preserves_loop_structure_p in favor of never duplicating
> a loop header.
>
> OK pending tests?
>
> PR tree-optimization/127085
>
> gcc/ChangeLog:
>
> * tree-ssa-phiopt.cc (preserves_loop_structure_p): Remove.
> (replicate_cond_into_pred): Refuse only loop headers.
> (replicate_conds_over_phis): Do not mark back edges; set
> LOOPS_NEED_FIXUP when the CFG changed.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr127085.c: New test.
> ---
> gcc/testsuite/gcc.dg/torture/pr127085.c | 22 +++++++++++++++++
> gcc/tree-ssa-phiopt.cc | 33 ++++++-------------------
> 2 files changed, 30 insertions(+), 25 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr127085.c
>
> diff --git a/gcc/testsuite/gcc.dg/torture/pr127085.c
> b/gcc/testsuite/gcc.dg/torture/pr127085.c
> new file mode 100644
> index 00000000000..22f01159736
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr127085.c
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/127085 */
> +/* { dg-do compile } */
> +
> +typedef unsigned char uint8_t;
> +typedef unsigned long long uint64_t;
> +uint8_t g26;
> +_Bool f19_c7, f19_c15;
> +void f19(uint64_t a0)
> +{
> + _Bool c4;
> +lbl_sw3:
> + if (f19_c7) goto lbl_bf30;
> + goto lbl_cont19;
> +lbl_sw14:
> + if (c4)
> + lbl_cont19:
> + if (f19_c15) goto lbl_sw14;
> + goto lbl_sw3;
> +lbl_bf30:
> + c4 = g26;
> + if (a0 == 80504447930037642) goto lbl_sw14;
> +}
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index f8dbd26abc1..1540fe34b86 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -4872,29 +4872,6 @@ execute_over_cond_phis (func_type func)
>
> where left and right are typically adjacent pointers in a tree structure.
> */
>
> -/* Return TRUE if duplicating E's destination with E redirected to
> - the copy leaves the loop structure unchanged. Requires
> - EDGE_DFS_BACK to be current. */
> -
> -static bool
> -preserves_loop_structure_p (edge e)
> -{
> - basic_block bb = e->dest;
> -
> - if ((e->flags & EDGE_DFS_BACK)
> - || e->src->loop_father != bb->loop_father)
> - return false;
> -
> - edge s;
> - edge_iterator ei;
> - FOR_EACH_EDGE (s, ei, bb->succs)
> - if ((s->flags & EDGE_DFS_BACK)
> - || s->dest->loop_father != bb->loop_father)
> - return false;
> -
> - return true;
> -}
> -
> /* Replicate the join block at E's destination into E's source. The copy's
> PHIs degenerate to their argument on E, so the copied conditional tests
> the
> predecessor's own value. The net effect after cleanups, for edge (3, 5)
> @@ -4919,8 +4896,9 @@ replicate_cond_into_pred (edge e)
> {
> basic_block bb = e->dest;
>
> + /* Never duplicate loop headers. */
> if (!can_duplicate_block_on_edge_p (e)
> - || !preserves_loop_structure_p (e))
> + || bb->loop_father->header == bb)
This seems better in the caller (which loops over all preds of bb).
OK with that change.
> return false;
>
> if (dump_file && (dump_flags & TDF_DETAILS))
> @@ -4958,7 +4936,6 @@ replicate_conds_over_phis (void)
> bool cfgchanged = false;
> basic_block bb;
>
> - mark_dfs_back_edges ();
> initialize_original_copy_tables ();
> FOR_EACH_BB_FN (bb, cfun)
> {
> @@ -4980,6 +4957,12 @@ replicate_conds_over_phis (void)
> }
> }
> free_original_copy_tables ();
> +
> + /* Removing an entry of an irreducible region can make it reducible,
> creating
> + a new loop. */
> + if (cfgchanged)
> + loops_state_set (LOOPS_NEED_FIXUP);
> +
> return cfgchanged;
> }
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)