static unsigned
process_bb (rpo_elim &avail, basic_block bb,
bool bb_visited, bool iterate_phis, bool iterate, bool eliminate,
- bool do_region, bitmap exit_bbs)
+ bool do_region, bitmap exit_bbs, bool skip_phis)
{
unsigned todo = 0;
edge_iterator ei;
/* If we are in loop-closed SSA preserve this state. This is
relevant when called on regions from outside of FRE/PRE. */
bool lc_phi_nodes = false;
- if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
+ if (!skip_phis
+ && loops_state_satisfies_p (LOOP_CLOSED_SSA))
FOR_EACH_EDGE (e, ei, bb->preds)
if (e->src->loop_father != e->dest->loop_father
&& flow_loop_nested_p (e->dest->loop_father,
}
/* Value-number all defs in the basic-block. */
- for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
- gsi_next (&gsi))
- {
- gphi *phi = gsi.phi ();
- tree res = PHI_RESULT (phi);
- vn_ssa_aux_t res_info = VN_INFO (res);
- if (!bb_visited)
- {
- gcc_assert (!res_info->visited);
- res_info->valnum = VN_TOP;
- res_info->visited = true;
- }
+ if (!skip_phis)
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ tree res = PHI_RESULT (phi);
+ vn_ssa_aux_t res_info = VN_INFO (res);
+ if (!bb_visited)
+ {
+ gcc_assert (!res_info->visited);
+ res_info->valnum = VN_TOP;
+ res_info->visited = true;
+ }
- /* When not iterating force backedge values to varying. */
- visit_stmt (phi, !iterate_phis);
- if (virtual_operand_p (res))
- continue;
+ /* When not iterating force backedge values to varying. */
+ visit_stmt (phi, !iterate_phis);
+ if (virtual_operand_p (res))
+ continue;
- /* Eliminate */
- /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
- how we handle backedges and availability.
- And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
- tree val = res_info->valnum;
- if (res != val && !iterate && eliminate)
- {
- if (tree leader = avail.eliminate_avail (bb, res))
- {
- if (leader != res
- /* Preserve loop-closed SSA form. */
- && (! lc_phi_nodes
- || is_gimple_min_invariant (leader)))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Replaced redundant PHI node "
- "defining ");
- print_generic_expr (dump_file, res);
- fprintf (dump_file, " with ");
- print_generic_expr (dump_file, leader);
- fprintf (dump_file, "\n");
- }
- avail.eliminations++;
+ /* Eliminate */
+ /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
+ how we handle backedges and availability.
+ And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
+ tree val = res_info->valnum;
+ if (res != val && !iterate && eliminate)
+ {
+ if (tree leader = avail.eliminate_avail (bb, res))
+ {
+ if (leader != res
+ /* Preserve loop-closed SSA form. */
+ && (! lc_phi_nodes
+ || is_gimple_min_invariant (leader)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replaced redundant PHI node "
+ "defining ");
+ print_generic_expr (dump_file, res);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, leader);
+ fprintf (dump_file, "\n");
+ }
+ avail.eliminations++;
- if (may_propagate_copy (res, leader))
- {
- /* Schedule for removal. */
- avail.to_remove.safe_push (phi);
- continue;
- }
- /* ??? Else generate a copy stmt. */
- }
- }
- }
- /* Only make defs available that not already are. But make
- sure loop-closed SSA PHI node defs are picked up for
- downstream uses. */
- if (lc_phi_nodes
- || res == val
- || ! avail.eliminate_avail (bb, res))
- avail.eliminate_push_avail (bb, res);
- }
+ if (may_propagate_copy (res, leader))
+ {
+ /* Schedule for removal. */
+ avail.to_remove.safe_push (phi);
+ continue;
+ }
+ /* ??? Else generate a copy stmt. */
+ }
+ }
+ }
+ /* Only make defs available that not already are. But make
+ sure loop-closed SSA PHI node defs are picked up for
+ downstream uses. */
+ if (lc_phi_nodes
+ || res == val
+ || ! avail.eliminate_avail (bb, res))
+ avail.eliminate_push_avail (bb, res);
+ }
/* For empty BBs mark outgoing edges executable. For non-empty BBs
we do this when processing the last stmt as we have to do this
bitmap_set_bit (exit_bbs, EXIT_BLOCK);
}
+ /* Clear EDGE_DFS_BACK on "all" entry edges, RPO order compute will
+ re-mark those that are contained in the region. */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, entry->dest->preds)
+ e->flags &= ~EDGE_DFS_BACK;
+
int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
int n = rev_post_order_and_mark_dfs_back_seme
(fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
if (!do_region)
BITMAP_FREE (exit_bbs);
+ /* If there are any non-DFS_BACK edges into entry->dest skip
+ processing PHI nodes for that block. This supports
+ value-numbering loop bodies w/o the actual loop. */
+ FOR_EACH_EDGE (e, ei, entry->dest->preds)
+ if (e != entry
+ && !(e->flags & EDGE_DFS_BACK))
+ break;
+ bool skip_entry_phis = e != NULL;
+ if (skip_entry_phis && dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Region does not contain all edges into "
+ "the entry block, skipping its PHIs.\n");
+
int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
for (int i = 0; i < n; ++i)
bb_to_rpo[rpo[i]] = i;
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
- gcc_assert (e == entry || (e->src->flags & bb_in_region));
+ gcc_assert (e == entry
+ || (skip_entry_phis && bb == entry->dest)
+ || (e->src->flags & bb_in_region));
}
for (int i = 0; i < n; ++i)
{
if (e->flags & EDGE_DFS_BACK)
has_backedges = true;
e->flags &= ~EDGE_EXECUTABLE;
- if (iterate || e == entry)
+ if (iterate || e == entry || (skip_entry_phis && bb == entry->dest))
continue;
if (bb_to_rpo[e->src->index] > i)
{
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
{
- if (e == entry)
+ if (e == entry || (skip_entry_phis && bb == entry->dest))
continue;
int max_rpo = MAX (rpo_state[i].max_rpo,
rpo_state[bb_to_rpo[e->src->index]].max_rpo);
todo |= process_bb (avail, bb,
rpo_state[idx].visited != 0,
rpo_state[idx].iterate,
- iterate, eliminate, do_region, exit_bbs);
+ iterate, eliminate, do_region, exit_bbs, false);
rpo_state[idx].visited++;
/* Verify if changed values flow over executable outgoing backedges
edge e;
FOR_EACH_EDGE (e, ei, bb->preds)
if (!(e->flags & EDGE_EXECUTABLE)
- && !rpo_state[bb_to_rpo[e->src->index]].visited
- && rpo_state[bb_to_rpo[e->src->index]].max_rpo >= (int)idx)
+ && (bb == entry->dest
+ || (!rpo_state[bb_to_rpo[e->src->index]].visited
+ && (rpo_state[bb_to_rpo[e->src->index]].max_rpo
+ >= (int)idx))))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Cannot trust state of predecessor "
nblk++;
todo |= process_bb (avail, bb, false, false, false, eliminate,
- do_region, exit_bbs);
+ do_region, exit_bbs,
+ skip_entry_phis && bb == entry->dest);
rpo_state[idx].visited++;
FOR_EACH_EDGE (e, ei, bb->succs)
}
/* Region-based entry for RPO VN. Performs value-numbering and elimination
- on the SEME region specified by ENTRY and EXIT_BBS. */
+ on the SEME region specified by ENTRY and EXIT_BBS. If ENTRY is not
+ the only edge into the region at ENTRY->dest PHI nodes in ENTRY->dest
+ are not considered. */
unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)