https://gcc.gnu.org/g:def63f7c26207e4dfefcf5e92c07ea2582474dc5
commit r17-5658-gdef63f7c26207e4dfefcf5e92c07ea2582474dc5 Author: Richard Biener <[email protected]> Date: Tue Oct 27 17:02:58 2026 +0100 tree-optimization/128209 - fix uninitialized read of bb_to_rpo The following fixes the uninitialized read of bb_to_rpo introduced by the PR123298 fix. The issue is that nothing prevents walk_non_aliased_vuses to walk outside of the region and thus the backedge queries go where we do not have the information. To fix this we're marking the region with a local BB flag and conservatively treat out-of-region edges as backedges (apart from the entry edge which is known forward). PR tree-optimization/128209 * tree-ssa-sccvn.cc (vn_bb_in_region_flag, vn_entry_edge): New globals. (vn_is_backedge): Treat out-of-region edges conservatively. (do_rpo_vn_1): Split out region marking from verification-only to be always done. Diff: --- gcc/tree-ssa-sccvn.cc | 84 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 77ab131b5f4c..7d97bce77fa7 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -380,6 +380,8 @@ static class eliminate_dom_walker *rpo_avail; basic_block vn_context_bb; int *vn_bb_to_rpo; static int *vn_exec_idom; +static int vn_bb_in_region_flag; +static edge vn_entry_edge; /* Valueization hook for simplify_replace_tree. Valueize NAME if it is @@ -4105,9 +4107,22 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, static bool vn_is_backedge (edge e, void *) { - /* During PRE elimination we no longer have access to this info. */ - return (!vn_bb_to_rpo - || vn_bb_to_rpo[e->dest->index] <= vn_bb_to_rpo[e->src->index]); + /* During PRE elimination and ANTIC compute we no longer have + vn_bb_to_rpo and the region is no longer marked. */ + if (!vn_bb_to_rpo) + return true; + + gcc_assert (vn_bb_in_region_flag != 0); + + /* The entry edge is a forward edge. */ + if (e == vn_entry_edge) + return false; + /* For out-of region edges conservatively return true. */ + if (!(e->src->flags & vn_bb_in_region_flag)) + return true; + /* We should never ask for region exit edges. */ + gcc_checking_assert (e->dest->flags & vn_bb_in_region_flag); + return vn_bb_to_rpo[e->dest->index] <= vn_bb_to_rpo[e->src->index]; } /* Return a reference op vector from OP that can be used for @@ -8935,37 +8950,6 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, rpo_avail = &avail; - /* Verify we have no extra entries into the region. */ - if (flag_checking && do_region) - { - auto_bb_flag bb_in_region (fn); - for (int i = 0; i < n; ++i) - { - basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); - bb->flags |= bb_in_region; - } - /* We can't merge the first two loops because we cannot rely - on EDGE_DFS_BACK for edges not within the region. But if - we decide to always have the bb_in_region flag we can - do the checking during the RPO walk itself (but then it's - also easy to handle MEME conservatively). */ - for (int i = 0; i < n; ++i) - { - basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); - edge e; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->preds) - gcc_assert (e == entry - || (skip_entry_phis && bb == entry->dest) - || (e->src->flags & bb_in_region)); - } - for (int i = 0; i < n; ++i) - { - basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); - bb->flags &= ~bb_in_region; - } - } - /* Create the VN state. For the initial size of the various hashtables use a heuristic based on region size and number of SSA names. */ unsigned region_size = (((unsigned HOST_WIDE_INT)n * num_ssa_names) @@ -8988,11 +8972,17 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, vn_valueize = rpo_vn_valueize; + /* The blocks in the value-numbered region are marked with bb_in_region. */ + auto_bb_flag bb_in_region (fn); + vn_bb_in_region_flag = bb_in_region; + vn_entry_edge = entry; + /* Initialize the unwind state and edge/BB executable state. */ unsigned curr_scc = 0; for (int i = 0; i < n; ++i) { basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); + bb->flags |= bb_in_region; rpo_state[i].visited = 0; rpo_state[i].max_rpo = i; if (!iterate && curr_scc < toplevel_scc_extents.length ()) @@ -9020,6 +9010,23 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, entry->flags |= EDGE_EXECUTABLE; entry->dest->flags |= BB_EXECUTABLE; + /* Verify we have no extra entries into the region. */ + if (flag_checking && do_region) + { + /* We can't merge the first two loops because we cannot rely + on EDGE_DFS_BACK for edges not within the region. */ + for (int i = 0; i < n; ++i) + { + basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, bb->preds) + gcc_assert (e == entry + || (skip_entry_phis && bb == entry->dest) + || (e->src->flags & bb_in_region)); + } + } + /* As heuristic to improve compile-time we handle only the N innermost loops and the outermost one optimistically. */ if (iterate) @@ -9276,9 +9283,18 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, } } + /* Clear the bb_in_region flag. */ + for (int i = 0; i < n; ++i) + { + basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]); + bb->flags &= ~bb_in_region; + } + vn_valueize = NULL; rpo_avail = NULL; vn_bb_to_rpo = NULL; + vn_bb_in_region_flag = 0; + vn_entry_edge = NULL; vn_exec_idom = NULL;
