]> 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 <rguenth@gcc.gnu.org>
Mon, 8 Sep 2025 14:01:22 +0000 (16:01 +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.

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 2fe2655220b7de0cd76b6c6b85c503ce002be098..ba727adc808de4bc03e90a6f61df63baae6e4952 100644 (file)
@@ -3200,6 +3200,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;
 
@@ -7222,12 +7228,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: