]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/121844 - IVOPTs and asm goto in latch
authorRichard Biener <rguenther@suse.de>
Mon, 8 Sep 2025 12:32:38 +0000 (14:32 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 24 Sep 2025 08:36:18 +0000 (10:36 +0200)
When there's an asm goto in the latch of a loop we may not use
IP_END IVs since instantiating those would (need to) split the
latch edge which in turn invalidates IP_NORMAL position handling.
This is a revision of the PR107997 fix.

PR tree-optimization/107997
PR tree-optimization/121844
* tree-ssa-loop-ivopts.cc (allow_ip_end_pos_p): Do not allow
IP_END for latches ending with a control stmt.
(create_new_iv): Do not split the latch edge, instead assert
that's not necessary.

* gcc.dg/torture/pr121844.c: New testcase.

(cherry picked from commit 00cd34b1046076a3272f8e8e85c97dc8f4d2ea44)

gcc/testsuite/gcc.dg/torture/pr121844.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivopts.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr121844.c b/gcc/testsuite/gcc.dg/torture/pr121844.c
new file mode 100644 (file)
index 0000000..149d5ea
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+typedef unsigned long a;
+int b[] = {};
+int **c;
+short d(a *e, int f)
+{
+  *c = &f;
+  for (;;)
+    asm goto("" : : : : g);
+  for (; f; f--) {
+    asm goto("" : : : : g);
+  g:
+    *e ^= b[f + 1];
+  }
+}
index e37b24062f730e490ae86bd9248e61102ad1a0f0..4469591e9e4c109004061b9abb07e3bee8ec9be9 100644 (file)
@@ -3195,6 +3195,12 @@ add_candidate_1 (struct ivopts_data *data, tree base, tree step, bool important,
 static bool
 allow_ip_end_pos_p (class loop *loop)
 {
+  /* Do not allow IP_END when creating the IV would need to split the
+     latch edge as that makes all IP_NORMAL invalid.  */
+  auto pos = gsi_last_bb (ip_end_pos (loop));
+  if (!gsi_end_p (pos) && stmt_ends_bb_p (*pos))
+    return false;
+
   if (!ip_normal_pos (loop))
     return true;
 
@@ -7211,12 +7217,7 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
     case IP_END:
       incr_pos = gsi_last_bb (ip_end_pos (data->current_loop));
       after = true;
-      if (!gsi_end_p (incr_pos) && stmt_ends_bb_p (gsi_stmt (incr_pos)))
-       {
-         edge e = find_edge (gsi_bb (incr_pos), data->current_loop->header);
-         incr_pos = gsi_after_labels (split_edge (e));
-         after = false;
-       }
+      gcc_assert (gsi_end_p (incr_pos) || !stmt_ends_bb_p (*incr_pos));
       break;
 
     case IP_AFTER_USE: