On Mon, 8 Sep 2025, Jakub Jelinek wrote:

> On Mon, Sep 08, 2025 at 02:38:48PM +0200, Richard Biener wrote:
> > 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.
> 
> LGTM.
> >     * gcc.dg/torture/pr121844.c: New testcase.
> 
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/torture/pr121844.c
> > @@ -0,0 +1,19 @@
> > +/* { dg-do compile } */
> > +
> > +#include <stdint.h>
> 
> Why?  Does it rely on the size of any of those types in any way?
> Can't you s/int32_t/int/ and s/int16_t/void/ and probably
> unsigned long long * for type of e?

I've used unsigned long, this reproduces the failure.

> > +
> > +typedef uint64_t a;
> > +int32_t b[] = {};
> > +int32_t **c;
> > +int16_t d() {
> > +  a *e;
> 
> This one is uninitialized, is that needed for the repro?
> Can't it be e.g. argument to the function instead?

Yes, both 'e' and 'f' can be made function args.

I'll push the following.

Richard.

>From 3d777d03bb8c22204de1457cb2dae6a22fb2ed7a Mon Sep 17 00:00:00 2001
From: Richard Biener <rguent...@suse.de>
Date: Mon, 8 Sep 2025 14:32:38 +0200
Subject: [PATCH] tree-optimization/121844 - IVOPTs and asm goto in latch
To: gcc-patches@gcc.gnu.org

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 | 16 ++++++++++++++++
 gcc/tree-ssa-loop-ivopts.cc             | 13 +++++++------
 2 files changed, 23 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..149d5eaab64
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121844.c
@@ -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];
+  }
+}
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