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.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

        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 | 19 +++++++++++++++++++
 gcc/tree-ssa-loop-ivopts.cc             | 13 +++++++------
 2 files changed, 26 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr121844.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr121844.c 
b/gcc/testsuite/gcc.dg/torture/pr121844.c
new file mode 100644
index 00000000000..df7137b788b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121844.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+#include <stdint.h>
+
+typedef uint64_t a;
+int32_t b[] = {};
+int32_t **c;
+int16_t d() {
+  a *e;
+  int32_t f;
+  *c = &f;
+  for (;;)
+    asm goto("" : : : : g);
+  for (; f; f--) {
+    asm goto("" : : : : g);
+  g:
+    *e ^= b[f + 1];
+  }
+}
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index 2fe2655220b..ba727adc808 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -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:
-- 
2.43.0

Reply via email to