[gcc r16-3662] tree-optimization/121829 - bogus CFG with asm goto
Richard Biener
rguenth@gcc.gnu.org
Mon Sep 8 12:42:13 GMT 2025
https://gcc.gnu.org/g:a632becefad29206a980cc080eee74ed808f9cd3
commit r16-3662-ga632becefad29206a980cc080eee74ed808f9cd3
Author: Richard Biener <rguenther@suse.de>
Date: Mon Sep 8 12:40:30 2025 +0200
tree-optimization/121829 - bogus CFG with asm goto
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
* tree-vect-loop-manip.cc (vect_remove_forwarder): New
function.
(slpeel_tree_duplicate_loop_to_edge_cfg): Use it.
* gcc.dg/torture/pr121829.c: New testcase.
Diff:
---
gcc/testsuite/gcc.dg/torture/pr121829.c | 21 +++++++++++++++++++++
gcc/tree-vect-loop-manip.cc | 33 ++++++++++++++++++---------------
2 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/torture/pr121829.c b/gcc/testsuite/gcc.dg/torture/pr121829.c
new file mode 100644
index 000000000000..afcf7595a73d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121829.c
@@ -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];
+}
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 20141dbc2e54..7af70a51335f 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -1459,6 +1459,21 @@ get_live_virtual_operand_on_edge (edge e)
while (1);
}
+/* Remove the single succ/pred forwarder block BB. */
+
+static void
+vect_remove_forwarder (basic_block bb)
+{
+ edge pred = single_pred_edge (bb);
+ edge succ = single_succ_edge (bb);
+ basic_block to = single_succ (bb);
+ edge e = redirect_edge_and_branch (pred, to);
+ gcc_assert (e == pred);
+ copy_phi_arg_into_existing_phi (succ, e);
+ delete_basic_block (bb);
+ set_immediate_dominator (CDI_DOMINATORS, to, pred->src);
+}
+
/* Given LOOP this function generates a new copy of it and puts it
on E which is either the entry or exit of LOOP. If SCALAR_LOOP is
non-NULL, assume LOOP and SCALAR_LOOP are equivalent and copy the
@@ -1858,11 +1873,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit,
/* And remove the non-necessary forwarder again. Keep the other
one so we have a proper pre-header for the loop at the exit edge. */
- redirect_edge_pred (single_succ_edge (preheader),
- single_pred (preheader));
- delete_basic_block (preheader);
- set_immediate_dominator (CDI_DOMINATORS, scalar_loop->header,
- loop_preheader_edge (scalar_loop)->src);
+ vect_remove_forwarder (preheader);
/* Finally after wiring the new epilogue we need to update its main exit
to the original function exit we recorded. Other exits are already
@@ -1920,11 +1931,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit,
if (scalar_loop != loop)
{
/* Remove the non-necessary forwarder of scalar_loop again. */
- redirect_edge_pred (single_succ_edge (preheader),
- single_pred (preheader));
- delete_basic_block (preheader);
- set_immediate_dominator (CDI_DOMINATORS, scalar_loop->header,
- loop_preheader_edge (scalar_loop)->src);
+ vect_remove_forwarder (preheader);
preheader = split_edge (loop_preheader_edge (loop));
entry_e = single_pred_edge (preheader);
}
@@ -1939,11 +1946,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit,
/* And remove the non-necessary forwarder again. Keep the other
one so we have a proper pre-header for the loop at the exit edge. */
- redirect_edge_pred (single_succ_edge (new_preheader),
- single_pred (new_preheader));
- delete_basic_block (new_preheader);
- set_immediate_dominator (CDI_DOMINATORS, new_loop->header,
- loop_preheader_edge (new_loop)->src);
+ vect_remove_forwarder (new_preheader);
/* Update dominators for multiple exits. */
if (multiple_exits_p)
More information about the Gcc-cvs
mailing list