]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/121829 - bogus CFG with asm goto
authorRichard Biener <rguenther@suse.de>
Mon, 8 Sep 2025 10:40:30 +0000 (12:40 +0200)
committerRichard Biener <rguenther@suse.de>
Thu, 11 Sep 2025 09:16:58 +0000 (11:16 +0200)
When the vectorizer removes a forwarder created earlier by split_edge
it uses redirect_edge_pred for convenience and efficiency.  That breaks
down when the edge split is originating from an asm goto as that is
a jump that needs adjustments from redirect_edge_and_branch.  The
following factores a simple vect_remove_forwarder handling this
situation appropriately.

PR tree-optimization/121829
* cfgloopmanip.cc (create_preheader): Ensure we can insert
at the end of a preheader.

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

gcc/cfgloopmanip.cc
gcc/testsuite/gcc.dg/torture/pr121829.c [new file with mode: 0644]

index 2c28437b34d99171bc189b7795ff8de076fa82f2..dda2fb661d8cc28bb96763faf03583c38b043104 100644 (file)
@@ -32,6 +32,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop-manip.h"
 #include "dumpfile.h"
 #include "sreal.h"
+#include "tree-cfg.h"
+#include "tree-pass.h"
 
 static void copy_loops_to (class loop **, int,
                           class loop *);
@@ -1615,7 +1617,15 @@ create_preheader (class loop *loop, int flags)
             just a single successor and a normal edge.  */
           if ((flags & CP_SIMPLE_PREHEADERS)
              && ((single_entry->flags & EDGE_COMPLEX)
-                 || !single_succ_p (single_entry->src)))
+                 || !single_succ_p (single_entry->src)
+                 /* We document LOOPS_HAVE_PREHEADERS as to forming a
+                    natural place to move code outside of the loop, so it
+                    should not end with a control instruction.  */
+                 /* ???  This, and below JUMP_P check needs to be a new
+                    CFG hook.  */
+                 || (cfun->curr_properties & PROP_gimple
+                     && !gsi_end_p (gsi_last_bb (single_entry->src))
+                     && stmt_ends_bb_p (*gsi_last_bb (single_entry->src)))))
             need_forwarder_block = true;
           /* If we want fallthru preheaders, also create forwarder block when
              preheader ends with a jump or has predecessors from loop.  */
diff --git a/gcc/testsuite/gcc.dg/torture/pr121829.c b/gcc/testsuite/gcc.dg/torture/pr121829.c
new file mode 100644 (file)
index 0000000..afcf759
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int a[1][1];
+int *b(int *);
+int c() {
+  int *d[4];
+  int **e = &d[3];
+  int f;
+  for (; f; f++)
+    d[f] = &a[1][0];
+  b(*e);
+}
+int *b(int *g) {
+  asm goto("" : : : : h);
+  int i[9];
+h:
+  int f;
+  for (f = 0; f < 9; f++)
+    i[f] = 1;
+  *g = i[4];
+}