}
}
- /* If the value we want to use is the backedge and that wasn't visited
- yet or if we should take it as VARYING but it has a non-VARYING
- value drop to VARYING. This only happens when not iterating.
- If we value-number a virtual operand never value-number to the
+ /* If we value-number a virtual operand never value-number to the
value from the backedge as that confuses the alias-walking code.
See gcc.dg/torture/pr87176.c. If the value is the same on a
non-backedge everything is OK though. */
&& !seen_non_backedge
&& TREE_CODE (backedge_val) == SSA_NAME
&& sameval == backedge_val
- && (SSA_NAME_IS_VIRTUAL_OPERAND (backedge_val)
- || !SSA_VISITED (backedge_val)
- || SSA_VAL (backedge_val) != backedge_val))
+ && SSA_NAME_IS_VIRTUAL_OPERAND (backedge_val))
/* Note this just drops to VARYING without inserting the PHI into
the hashes. */
result = PHI_RESULT (phi);
/* Whether to handle this as iteration point or whether to treat
incoming backedge PHI values as varying. */
bool iterate;
+ /* Maximum RPO index this block is reachable from. */
+ int max_rpo;
+ /* Unwind state. */
void *ob_top;
vn_reference_t ref_top;
vn_phi_t phi_top;
}
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,
- iterate, rpo);
+ int n = rev_post_order_and_mark_dfs_back_seme
+ (fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
/* rev_post_order_and_mark_dfs_back_seme fills RPO in reverse order. */
for (int i = 0; i < n / 2; ++i)
std::swap (rpo[i], rpo[n-i-1]);
{
basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
rpo_state[i].visited = 0;
+ rpo_state[i].max_rpo = i;
bb->flags &= ~BB_EXECUTABLE;
bool has_backedges = false;
edge e;
if (e->flags & EDGE_DFS_BACK)
has_backedges = true;
if (! iterate && (e->flags & EDGE_DFS_BACK))
- {
- e->flags |= EDGE_EXECUTABLE;
- /* ??? Strictly speaking we only need to unconditionally
- process a block when it is in an irreducible region,
- thus when it may be reachable via the backedge only. */
- bb->flags |= BB_EXECUTABLE;
- }
+ e->flags |= EDGE_EXECUTABLE;
else
e->flags &= ~EDGE_EXECUTABLE;
+ if (e == entry)
+ continue;
+ if (bb_to_rpo[e->src->index] > i)
+ rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo,
+ bb_to_rpo[e->src->index]);
+ else
+ rpo_state[i].max_rpo
+ = MAX (rpo_state[i].max_rpo,
+ rpo_state[bb_to_rpo[e->src->index]].max_rpo);
}
rpo_state[i].iterate = iterate && has_backedges;
}
}
}
- /* Go and process all blocks, iterating as necessary. */
- int idx = 0;
uint64_t nblk = 0;
- do
+ int idx = 0;
+ if (iterate)
+ /* Go and process all blocks, iterating as necessary. */
+ do
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[idx]);
+
+ /* If the block has incoming backedges remember unwind state. This
+ is required even for non-executable blocks since in irreducible
+ regions we might reach them via the backedge and re-start iterating
+ from there.
+ Note we can individually mark blocks with incoming backedges to
+ not iterate where we then handle PHIs conservatively. We do that
+ heuristically to reduce compile-time for degenerate cases. */
+ if (rpo_state[idx].iterate)
+ {
+ rpo_state[idx].ob_top = obstack_alloc (&vn_tables_obstack, 0);
+ rpo_state[idx].ref_top = last_inserted_ref;
+ rpo_state[idx].phi_top = last_inserted_phi;
+ rpo_state[idx].nary_top = last_inserted_nary;
+ }
+
+ if (!(bb->flags & BB_EXECUTABLE))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Block %d: BB%d found not executable\n",
+ idx, bb->index);
+ idx++;
+ continue;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Processing block %d: BB%d\n", idx, bb->index);
+ nblk++;
+ todo |= process_bb (avail, bb,
+ rpo_state[idx].visited != 0,
+ rpo_state[idx].iterate,
+ iterate, eliminate, do_region, exit_bbs);
+ rpo_state[idx].visited++;
+
+ /* Verify if changed values flow over executable outgoing backedges
+ and those change destination PHI values (that's the thing we
+ can easily verify). Reduce over all such edges to the farthest
+ away PHI. */
+ int iterate_to = -1;
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if ((e->flags & (EDGE_DFS_BACK|EDGE_EXECUTABLE))
+ == (EDGE_DFS_BACK|EDGE_EXECUTABLE)
+ && rpo_state[bb_to_rpo[e->dest->index]].iterate)
+ {
+ int destidx = bb_to_rpo[e->dest->index];
+ if (!rpo_state[destidx].visited)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Unvisited destination %d\n",
+ e->dest->index);
+ if (iterate_to == -1 || destidx < iterate_to)
+ iterate_to = destidx;
+ continue;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Looking for changed values of backedge"
+ " %d->%d destination PHIs\n",
+ e->src->index, e->dest->index);
+ vn_context_bb = e->dest;
+ gphi_iterator gsi;
+ for (gsi = gsi_start_phis (e->dest);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ bool inserted = false;
+ /* While we'd ideally just iterate on value changes
+ we CSE PHIs and do that even across basic-block
+ boundaries. So even hashtable state changes can
+ be important (which is roughly equivalent to
+ PHI argument value changes). To not excessively
+ iterate because of that we track whether a PHI
+ was CSEd to with GF_PLF_1. */
+ bool phival_changed;
+ if ((phival_changed = visit_phi (gsi.phi (),
+ &inserted, false))
+ || (inserted && gimple_plf (gsi.phi (), GF_PLF_1)))
+ {
+ if (!phival_changed
+ && dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "PHI was CSEd and hashtable "
+ "state (changed)\n");
+ if (iterate_to == -1 || destidx < iterate_to)
+ iterate_to = destidx;
+ break;
+ }
+ }
+ vn_context_bb = NULL;
+ }
+ if (iterate_to != -1)
+ {
+ do_unwind (&rpo_state[iterate_to], iterate_to, avail, bb_to_rpo);
+ idx = iterate_to;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Iterating to %d BB%d\n",
+ iterate_to, rpo[iterate_to]);
+ continue;
+ }
+
+ idx++;
+ }
+ while (idx < n);
+
+ else /* !iterate */
{
- basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[idx]);
-
- /* If the block has incoming backedges remember unwind state. This
- is required even for non-executable blocks since in irreducible
- regions we might reach them via the backedge and re-start iterating
- from there.
- Note we can individually mark blocks with incoming backedges to
- not iterate where we then handle PHIs conservatively. We do that
- heuristically to reduce compile-time for degenerate cases. */
- if (rpo_state[idx].iterate)
+ /* Process all blocks greedily with a worklist that enforces RPO
+ processing of reachable blocks. */
+ auto_bitmap worklist;
+ bitmap_set_bit (worklist, 0);
+ while (!bitmap_empty_p (worklist))
{
- rpo_state[idx].ob_top = obstack_alloc (&vn_tables_obstack, 0);
- rpo_state[idx].ref_top = last_inserted_ref;
- rpo_state[idx].phi_top = last_inserted_phi;
- rpo_state[idx].nary_top = last_inserted_nary;
- }
+ int idx = bitmap_first_set_bit (worklist);
+ bitmap_clear_bit (worklist, idx);
+ basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[idx]);
+ gcc_assert ((bb->flags & BB_EXECUTABLE)
+ && !rpo_state[idx].visited);
- if (!(bb->flags & BB_EXECUTABLE))
- {
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Block %d: BB%d found not executable\n",
- idx, bb->index);
- idx++;
- continue;
- }
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Processing block %d: BB%d\n", idx, bb->index);
- nblk++;
- todo |= process_bb (avail, bb,
- rpo_state[idx].visited != 0,
- rpo_state[idx].iterate,
- iterate, eliminate, do_region, exit_bbs);
- rpo_state[idx].visited++;
+ fprintf (dump_file, "Processing block %d: BB%d\n", idx, bb->index);
- if (iterate)
- {
- /* Verify if changed values flow over executable outgoing backedges
- and those change destination PHI values (that's the thing we
- can easily verify). Reduce over all such edges to the farthest
- away PHI. */
- int iterate_to = -1;
+ /* When we run into predecessor edges where we cannot trust its
+ executable state mark them executable so PHI processing will
+ be conservative.
+ ??? Do we need to force arguments flowing over that edge
+ to be varying or will they even always be? */
edge_iterator ei;
edge e;
- FOR_EACH_EDGE (e, ei, bb->succs)
- if ((e->flags & (EDGE_DFS_BACK|EDGE_EXECUTABLE))
- == (EDGE_DFS_BACK|EDGE_EXECUTABLE)
- && rpo_state[bb_to_rpo[e->dest->index]].iterate)
+ 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)
{
- int destidx = bb_to_rpo[e->dest->index];
- if (!rpo_state[destidx].visited)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Unvisited destination %d\n",
- e->dest->index);
- if (iterate_to == -1
- || destidx < iterate_to)
- iterate_to = destidx;
- continue;
- }
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Looking for changed values of backedge "
- "%d->%d destination PHIs\n",
+ fprintf (dump_file, "Cannot trust state of predecessor "
+ "edge %d -> %d, marking executable\n",
e->src->index, e->dest->index);
- vn_context_bb = e->dest;
- gphi_iterator gsi;
- for (gsi = gsi_start_phis (e->dest);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- bool inserted = false;
- /* While we'd ideally just iterate on value changes
- we CSE PHIs and do that even across basic-block
- boundaries. So even hashtable state changes can
- be important (which is roughly equivalent to
- PHI argument value changes). To not excessively
- iterate because of that we track whether a PHI
- was CSEd to with GF_PLF_1. */
- bool phival_changed;
- if ((phival_changed = visit_phi (gsi.phi (),
- &inserted, false))
- || (inserted && gimple_plf (gsi.phi (), GF_PLF_1)))
- {
- if (!phival_changed
- && dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "PHI was CSEd and hashtable "
- "state (changed)\n");
- if (iterate_to == -1
- || destidx < iterate_to)
- iterate_to = destidx;
- break;
- }
- }
- vn_context_bb = NULL;
+ e->flags |= EDGE_EXECUTABLE;
}
- if (iterate_to != -1)
- {
- do_unwind (&rpo_state[iterate_to], iterate_to,
- avail, bb_to_rpo);
- idx = iterate_to;
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Iterating to %d BB%d\n",
- iterate_to, rpo[iterate_to]);
- continue;
- }
- }
- idx++;
+ nblk++;
+ todo |= process_bb (avail, bb, false, false, false, eliminate,
+ do_region, exit_bbs);
+ rpo_state[idx].visited++;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if ((e->flags & EDGE_EXECUTABLE)
+ && e->dest->index != EXIT_BLOCK
+ && (!do_region || !bitmap_bit_p (exit_bbs, e->dest->index))
+ && !rpo_state[bb_to_rpo[e->dest->index]].visited)
+ bitmap_set_bit (worklist, bb_to_rpo[e->dest->index]);
+ }
}
- while (idx < n);
/* If statistics or dump file active. */
int nex = 0;