From 9e7c77c7933b1bb0dd07214333e52a9a896fa349 Mon Sep 17 00:00:00 2001 From: Tamar Christina <tamar.christina@arm.com> Date: Wed, 10 Jan 2024 12:51:54 +0000 Subject: [PATCH] middle-end: Fix dominators updates when peeling with multiple exits [PR113144] When we peel at_exit we are moving the new loop at the exit of the previous loop. This means that the blocks outside the loop dat the previous loop used to dominate are no longer being dominated by it. The new dominators however are hard to predict since if the loop has multiple exits and all the exits are an "early" one then we always execute the scalar loop. In this case the scalar loop can completely dominate the new loop. If we later have skip_vector then there's an additional skip edge added that might change the dominators. The previous patch would force an update of all blocks reachable from the new exits. This one updates *only* blocks that we know the scalar exits dominated. For the examples this reduces the blocks to update from 18 to 3. gcc/ChangeLog: PR tree-optimization/113144 PR tree-optimization/113145 * tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg): Update all BB that the original exits dominated. gcc/testsuite/ChangeLog: PR tree-optimization/113144 PR tree-optimization/113145 * gcc.dg/vect/vect-early-break_94-pr113144.c: New test. --- .../vect/vect-early-break_94-pr113144.c | 41 +++++++++++++++++++ gcc/tree-vect-loop-manip.cc | 13 ++---- 2 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_94-pr113144.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_94-pr113144.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_94-pr113144.c new file mode 100644 index 000000000000..903fe7be6621 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_94-pr113144.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-add-options vect_early_break } */ +/* { dg-require-effective-target vect_early_break } */ +/* { dg-require-effective-target vect_int } */ + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ + +long tar_atol256_max, tar_atol256_size, tar_atosl_min; +char tar_atol256_s; +void __errno_location(); + + +inline static long tar_atol256(long min) { + char c; + int sign; + c = tar_atol256_s; + sign = c; + while (tar_atol256_size) { + if (c != sign) + return sign ? min : tar_atol256_max; + c = tar_atol256_size--; + } + if ((c & 128) != (sign & 128)) + return sign ? min : tar_atol256_max; + return 0; +} + +inline static long tar_atol(long min) { + return tar_atol256(min); +} + +long tar_atosl() { + long n = tar_atol(-1); + if (tar_atosl_min) { + __errno_location(); + return 0; + } + if (n > 0) + return 0; + return n; +} diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index f0ea7fc069bd..8aa7575a0e39 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -1716,8 +1716,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, /* Now link the alternative exits. */ if (multiple_exits_p) { - set_immediate_dominator (CDI_DOMINATORS, new_preheader, - main_loop_exit_block); for (auto gsi_from = gsi_start_phis (loop->header), gsi_to = gsi_start_phis (new_preheader); !gsi_end_p (gsi_from) && !gsi_end_p (gsi_to); @@ -1755,13 +1753,10 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, if (multiple_exits_p) { update_loop = new_loop; - for (edge e : get_loop_exit_edges (loop)) - doms.safe_push (e->dest); - doms.safe_push (exit_dest); - - /* Likely a fall-through edge, so update if needed. */ - if (single_succ_p (exit_dest)) - doms.safe_push (single_succ (exit_dest)); + doms = get_all_dominated_blocks (CDI_DOMINATORS, loop->header); + for (unsigned i = 0; i < doms.length (); ++i) + if (flow_bb_inside_loop_p (loop, doms[i])) + doms.unordered_remove (i); } } else /* Add the copy at entry. */ -- GitLab