[gcc r16-1499] expand: Fix up edge splitting for ENTRY block during expansion if there are any PHIs [PR120629]
Jakub Jelinek
jakub@gcc.gnu.org
Fri Jun 13 12:02:37 GMT 2025
https://gcc.gnu.org/g:2661d87d54ab7185e7115cbcfa47cb42565eb925
commit r16-1499-g2661d87d54ab7185e7115cbcfa47cb42565eb925
Author: Jakub Jelinek <jakub@redhat.com>
Date: Fri Jun 13 14:01:18 2025 +0200
expand: Fix up edge splitting for ENTRY block during expansion if there are any PHIs [PR120629]
Andrew ran some extra ranger checking during bootstrap and found one more
case (though much rarer than the GIMPLE_COND case).
Seems on fold-const.cc (native_encode_expr) we end up with bb 2, ENTRY
bb successor, having PHI nodes (usually there is some bb in between, even if
empty, in the native_encode_expr it is tail recursion but haven't managed
to construct a test with such case by hand).
So, we have in optimized dump
<bb 2> [local count: 1089340384]:
# expr_12 = PHI <expr_199(D)(0), part_93(51)>
# ptr_13 = PHI <ptr_86(D)(0), ptr_13(51)>
# len_14 = PHI <len_103(D)(0), _198(51)>
# off_10 = PHI <off_102(D)(0), _207(51)>
# add_acc_99 = PHI <0(0), add_acc_101(51)>
where there are mostly default defs from the 0->2 edge (and one zero)
and some other values from the other edge.
construct_init_block inserts a BB_RTL basic block with the function start
instructions and similarly to the GIMPLE_COND case it wants to insert that
bb on the edge from ENTRY to its single successor.
Now, without this patch redirect_edge_succ redirects the 0->2 edge to 0->52,
so the 51->2 edge gets moved first by unordered_remove, and
make_single_succ_edge adds a new 52->2 edge. So we end up with
# expr_12 = PHI <expr_199(D)(51), part_93(52)>
# ptr_13 = PHI <ptr_86(D)(51), ptr_13(52)>
# len_14 = PHI <len_103(D)(51), _198(52)>
# off_10 = PHI <off_102(D)(51), _207(52)>
# add_acc_99 = PHI <0(51), add_acc_101(52)>
which is not correct, the default definitions and zero are now from the edge
from end of function and the other values from the edge from the new BB_RTL
successor of ENTRY. With this patch we get
# expr_12 = PHI <expr_199(D)(52), part_93(51)>
# ptr_13 = PHI <ptr_86(D)(52), ptr_13(51)>
# len_14 = PHI <len_103(D)(52), _198(51)>
# off_10 = PHI <off_102(D)(52), _207(51)>
# add_acc_99 = PHI <0(52), add_acc_101(51)>
instead.
2025-06-13 Jakub Jelinek <jakub@redhat.com>
PR middle-end/120629
* cfgexpand.cc (construct_init_block): If first_block isn't BB_RTL,
has any PHI nodes and false_edge->dest_idx before redirection is
different from make_single_succ_edge result's dest_idx, swap the
latter with the former last pred edge and their dest_idx members.
Diff:
---
gcc/cfgexpand.cc | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index f288a5407346..2e6241d1e39a 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -6570,9 +6570,22 @@ construct_init_block (void)
add_bb_to_loop (init_block, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father);
if (e)
{
+ unsigned int dest_idx = e->dest_idx;
first_block = e->dest;
redirect_edge_succ (e, init_block);
- make_single_succ_edge (init_block, first_block, flags);
+ e = make_single_succ_edge (init_block, first_block, flags);
+ if ((first_block->flags & BB_RTL) == 0
+ && phi_nodes (first_block)
+ && e->dest_idx != dest_idx)
+ {
+ /* If there are any PHI nodes on dest, swap the new succ edge
+ with the one moved into false_edge's former position, so that
+ PHI arguments don't need adjustment. */
+ edge e2 = EDGE_PRED (first_block, dest_idx);
+ std::swap (e->dest_idx, e2->dest_idx);
+ std::swap (EDGE_PRED (first_block, e->dest_idx),
+ EDGE_PRED (first_block, e2->dest_idx));
+ }
}
else
make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
More information about the Gcc-cvs
mailing list