]> gcc.gnu.org Git - gcc.git/commitdiff
middle-end: Fix dominators updates when peeling with multiple exits [PR113144]
authorTamar Christina <tamar.christina@arm.com>
Wed, 10 Jan 2024 12:51:54 +0000 (12:51 +0000)
committerTamar Christina <tamar.christina@arm.com>
Wed, 10 Jan 2024 12:52:25 +0000 (12:52 +0000)
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.

gcc/testsuite/gcc.dg/vect/vect-early-break_94-pr113144.c [new file with mode: 0644]
gcc/tree-vect-loop-manip.cc

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 (file)
index 0000000..903fe7b
--- /dev/null
@@ -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;
+}
index f0ea7fc069bdccd58b6964f830e89cbdb5e76899..8aa7575a0e39b51215610d21e5ba81dd271bdd47 100644 (file)
@@ -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.  */
This page took 0.085009 seconds and 5 git commands to generate.