public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH]middle-end: Fix dominators updates when peeling with multiple exits [PR113144]
@ 2023-12-29 14:44 Tamar Christina
  2024-01-08 12:19 ` Richard Biener
  0 siblings, 1 reply; 9+ messages in thread
From: Tamar Christina @ 2023-12-29 14:44 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, rguenther, jlaw

[-- Attachment #1: Type: text/plain, Size: 3876 bytes --]

Hi All,

Only trying to update certain dominators doesn't seem to work very well
because as the loop gets versioned, peeled, or skip_vector then we end up with
very complicated control flow.  This means that the final merge blocks for the
loop exit are not easy to find or update.

Instead of trying to pick which exits to update, this changes it to update all
the blocks reachable by the new exits.  This is because they'll contain common
blocks with e.g. the versioned loop.  It's these blocks that need an update
most of the time.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

	PR middle-end/113144
	* tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg):
	Update all dominators reachable from exit.

gcc/testsuite/ChangeLog:

	PR middle-end/113144
	* gcc.dg/vect/vect-early-break_94-pr113144.c: New test.

--- inline copy of patch -- 
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 0000000000000000000000000000000000000000..903fe7be6621e81db6f29441e4309fa213d027c5
--- /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 1066ea17c5674e03412b3dcd8a62ddf4dd54cf31..3810983a80c8b989be9fd9a9993642069fd39b99 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);
@@ -1751,12 +1749,26 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit,
 
       /* Finally after wiring the new epilogue we need to update its main exit
 	 to the original function exit we recorded.  Other exits are already
-	 correct.  */
+	 correct.  Because of versioning, skip vectors and others we must update
+	 the dominators of every node reachable by the new exits.  */
       if (multiple_exits_p)
 	{
 	  update_loop = new_loop;
-	  for (edge e : get_loop_exit_edges (loop))
-	    doms.safe_push (e->dest);
+	  hash_set <basic_block> visited;
+	  auto_vec <edge> workset;
+	  edge ev;
+	  edge_iterator ei;
+	  workset.safe_splice (get_loop_exit_edges (loop));
+	  while (!workset.is_empty ())
+	    {
+	      auto bb = workset.pop ()->dest;
+	      if (visited.add (bb))
+		continue;
+	      doms.safe_push (bb);
+	      FOR_EACH_EDGE (ev, ei, bb->succs)
+		workset.safe_push (ev);
+	    }
+	  visited.empty ();
 	  doms.safe_push (exit_dest);
 
 	  /* Likely a fall-through edge, so update if needed.  */




-- 

[-- Attachment #2: rb18113.patch --]
[-- Type: text/plain, Size: 2953 bytes --]

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 0000000000000000000000000000000000000000..903fe7be6621e81db6f29441e4309fa213d027c5
--- /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 1066ea17c5674e03412b3dcd8a62ddf4dd54cf31..3810983a80c8b989be9fd9a9993642069fd39b99 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);
@@ -1751,12 +1749,26 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit,
 
       /* Finally after wiring the new epilogue we need to update its main exit
 	 to the original function exit we recorded.  Other exits are already
-	 correct.  */
+	 correct.  Because of versioning, skip vectors and others we must update
+	 the dominators of every node reachable by the new exits.  */
       if (multiple_exits_p)
 	{
 	  update_loop = new_loop;
-	  for (edge e : get_loop_exit_edges (loop))
-	    doms.safe_push (e->dest);
+	  hash_set <basic_block> visited;
+	  auto_vec <edge> workset;
+	  edge ev;
+	  edge_iterator ei;
+	  workset.safe_splice (get_loop_exit_edges (loop));
+	  while (!workset.is_empty ())
+	    {
+	      auto bb = workset.pop ()->dest;
+	      if (visited.add (bb))
+		continue;
+	      doms.safe_push (bb);
+	      FOR_EACH_EDGE (ev, ei, bb->succs)
+		workset.safe_push (ev);
+	    }
+	  visited.empty ();
 	  doms.safe_push (exit_dest);
 
 	  /* Likely a fall-through edge, so update if needed.  */




^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-01-09 14:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-29 14:44 [PATCH]middle-end: Fix dominators updates when peeling with multiple exits [PR113144] Tamar Christina
2024-01-08 12:19 ` Richard Biener
2024-01-09 11:47   ` Tamar Christina
2024-01-09 12:25     ` Richard Biener
2024-01-09 13:26       ` Tamar Christina
2024-01-09 13:34         ` Richard Biener
2024-01-09 13:50           ` Richard Biener
2024-01-09 13:58             ` Tamar Christina
2024-01-09 14:14               ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).