Commit 40289199 by Richard Biener Committed by Richard Biener

re PR tree-optimization/90402 (ICE in slpeel_duplicate_current_defs_from_edges)

2019-05-13  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90402
	* tree-if-conv.c (tree_if_conversion): Value number only
	the loop body by making the latch an exit of the region
	as well.
	* tree-ssa-sccvn.c (process_bb): Add flag whether to skip
	processing PHIs.
	(do_rpo_vn): Deal with multiple edges into the entry block
	that are not backedges inside the region by skipping PHIs
	of the entry block.

	* gcc.dg/torture/pr90402-1.c: New testcase.

From-SVN: r271125
parent aae6da83
2019-05-13 Richard Biener <rguenther@suse.de> 2019-05-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/90402
* tree-if-conv.c (tree_if_conversion): Value number only
the loop body by making the latch an exit of the region
as well.
* tree-ssa-sccvn.c (process_bb): Add flag whether to skip
processing PHIs.
(do_rpo_vn): Deal with multiple edges into the entry block
that are not backedges inside the region by skipping PHIs
of the entry block.
2019-05-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/90316 PR tree-optimization/90316
* tree-ssa-pre.c (insert_aux): Fold into ... * tree-ssa-pre.c (insert_aux): Fold into ...
(insert): ... this function. Use a RPO walk to reduce the (insert): ... this function. Use a RPO walk to reduce the
......
2019-05-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/90402
* gcc.dg/torture/pr90402-1.c: New testcase.
2019-05-12 Iain Sandoe <iain@sandoe.co.uk> 2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
Dominique d'Humieres <dominiq@gcc.gnu.org> Dominique d'Humieres <dominiq@gcc.gnu.org>
......
/* { dg-do compile } */
/* { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } } */
int kn, ha;
int
c7 (void)
{
}
void
ul (int w3)
{
kn = c7 ();
while (w3 < 1)
{
ha += !!kn ? 1 : w3;
for (kn = 0; kn < 2; ++kn)
{
}
++w3;
}
}
...@@ -3066,10 +3066,12 @@ tree_if_conversion (struct loop *loop, vec<gimple *> *preds) ...@@ -3066,10 +3066,12 @@ tree_if_conversion (struct loop *loop, vec<gimple *> *preds)
ifcvt_local_dce (loop->header); ifcvt_local_dce (loop->header);
/* Perform local CSE, this esp. helps the vectorizer analysis if loads /* Perform local CSE, this esp. helps the vectorizer analysis if loads
and stores are involved. and stores are involved. CSE only the loop body, not the entry
PHIs, those are to be kept in sync with the non-if-converted copy.
??? We'll still keep dead stores though. */ ??? We'll still keep dead stores though. */
exit_bbs = BITMAP_ALLOC (NULL); exit_bbs = BITMAP_ALLOC (NULL);
bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index); bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
bitmap_set_bit (exit_bbs, loop->latch->index);
todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs); todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs);
BITMAP_FREE (exit_bbs); BITMAP_FREE (exit_bbs);
......
...@@ -5979,7 +5979,7 @@ insert_related_predicates_on_edge (enum tree_code code, tree *ops, edge pred_e) ...@@ -5979,7 +5979,7 @@ insert_related_predicates_on_edge (enum tree_code code, tree *ops, edge pred_e)
static unsigned static unsigned
process_bb (rpo_elim &avail, basic_block bb, process_bb (rpo_elim &avail, basic_block bb,
bool bb_visited, bool iterate_phis, bool iterate, bool eliminate, 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; unsigned todo = 0;
edge_iterator ei; edge_iterator ei;
...@@ -5990,7 +5990,8 @@ process_bb (rpo_elim &avail, basic_block bb, ...@@ -5990,7 +5990,8 @@ process_bb (rpo_elim &avail, basic_block bb,
/* If we are in loop-closed SSA preserve this state. This is /* If we are in loop-closed SSA preserve this state. This is
relevant when called on regions from outside of FRE/PRE. */ relevant when called on regions from outside of FRE/PRE. */
bool lc_phi_nodes = false; 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) FOR_EACH_EDGE (e, ei, bb->preds)
if (e->src->loop_father != e->dest->loop_father if (e->src->loop_father != e->dest->loop_father
&& flow_loop_nested_p (e->dest->loop_father, && flow_loop_nested_p (e->dest->loop_father,
...@@ -6011,67 +6012,68 @@ process_bb (rpo_elim &avail, basic_block bb, ...@@ -6011,67 +6012,68 @@ process_bb (rpo_elim &avail, basic_block bb,
} }
/* Value-number all defs in the basic-block. */ /* Value-number all defs in the basic-block. */
for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); if (!skip_phis)
gsi_next (&gsi)) for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
{ gsi_next (&gsi))
gphi *phi = gsi.phi (); {
tree res = PHI_RESULT (phi); gphi *phi = gsi.phi ();
vn_ssa_aux_t res_info = VN_INFO (res); tree res = PHI_RESULT (phi);
if (!bb_visited) vn_ssa_aux_t res_info = VN_INFO (res);
{ if (!bb_visited)
gcc_assert (!res_info->visited); {
res_info->valnum = VN_TOP; gcc_assert (!res_info->visited);
res_info->visited = true; res_info->valnum = VN_TOP;
} res_info->visited = true;
}
/* When not iterating force backedge values to varying. */ /* When not iterating force backedge values to varying. */
visit_stmt (phi, !iterate_phis); visit_stmt (phi, !iterate_phis);
if (virtual_operand_p (res)) if (virtual_operand_p (res))
continue; continue;
/* Eliminate */ /* Eliminate */
/* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
how we handle backedges and availability. how we handle backedges and availability.
And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */ And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
tree val = res_info->valnum; tree val = res_info->valnum;
if (res != val && !iterate && eliminate) if (res != val && !iterate && eliminate)
{ {
if (tree leader = avail.eliminate_avail (bb, res)) if (tree leader = avail.eliminate_avail (bb, res))
{ {
if (leader != res if (leader != res
/* Preserve loop-closed SSA form. */ /* Preserve loop-closed SSA form. */
&& (! lc_phi_nodes && (! lc_phi_nodes
|| is_gimple_min_invariant (leader))) || is_gimple_min_invariant (leader)))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Replaced redundant PHI node " fprintf (dump_file, "Replaced redundant PHI node "
"defining "); "defining ");
print_generic_expr (dump_file, res); print_generic_expr (dump_file, res);
fprintf (dump_file, " with "); fprintf (dump_file, " with ");
print_generic_expr (dump_file, leader); print_generic_expr (dump_file, leader);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
avail.eliminations++; avail.eliminations++;
if (may_propagate_copy (res, leader)) if (may_propagate_copy (res, leader))
{ {
/* Schedule for removal. */ /* Schedule for removal. */
avail.to_remove.safe_push (phi); avail.to_remove.safe_push (phi);
continue; continue;
} }
/* ??? Else generate a copy stmt. */ /* ??? Else generate a copy stmt. */
} }
} }
} }
/* Only make defs available that not already are. But make /* Only make defs available that not already are. But make
sure loop-closed SSA PHI node defs are picked up for sure loop-closed SSA PHI node defs are picked up for
downstream uses. */ downstream uses. */
if (lc_phi_nodes if (lc_phi_nodes
|| res == val || res == val
|| ! avail.eliminate_avail (bb, res)) || ! avail.eliminate_avail (bb, res))
avail.eliminate_push_avail (bb, res); avail.eliminate_push_avail (bb, res);
} }
/* For empty BBs mark outgoing edges executable. For non-empty BBs /* 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 we do this when processing the last stmt as we have to do this
...@@ -6415,6 +6417,13 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6415,6 +6417,13 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
bitmap_set_bit (exit_bbs, EXIT_BLOCK); 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 *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
int n = rev_post_order_and_mark_dfs_back_seme int n = rev_post_order_and_mark_dfs_back_seme
(fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo); (fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
...@@ -6425,6 +6434,18 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6425,6 +6434,18 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
if (!do_region) if (!do_region)
BITMAP_FREE (exit_bbs); 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)); int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
bb_to_rpo[rpo[i]] = i; bb_to_rpo[rpo[i]] = i;
...@@ -6454,7 +6475,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6454,7 +6475,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge e; edge e;
edge_iterator ei; edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds) 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) for (int i = 0; i < n; ++i)
{ {
...@@ -6499,7 +6522,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6499,7 +6522,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
if (e->flags & EDGE_DFS_BACK) if (e->flags & EDGE_DFS_BACK)
has_backedges = true; has_backedges = true;
e->flags &= ~EDGE_EXECUTABLE; e->flags &= ~EDGE_EXECUTABLE;
if (iterate || e == entry) if (iterate || e == entry || (skip_entry_phis && bb == entry->dest))
continue; continue;
if (bb_to_rpo[e->src->index] > i) if (bb_to_rpo[e->src->index] > i)
{ {
...@@ -6532,7 +6555,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6532,7 +6555,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge_iterator ei; edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
{ {
if (e == entry) if (e == entry || (skip_entry_phis && bb == entry->dest))
continue; continue;
int max_rpo = MAX (rpo_state[i].max_rpo, int max_rpo = MAX (rpo_state[i].max_rpo,
rpo_state[bb_to_rpo[e->src->index]].max_rpo); rpo_state[bb_to_rpo[e->src->index]].max_rpo);
...@@ -6621,7 +6644,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6621,7 +6644,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
todo |= process_bb (avail, bb, todo |= process_bb (avail, bb,
rpo_state[idx].visited != 0, rpo_state[idx].visited != 0,
rpo_state[idx].iterate, rpo_state[idx].iterate,
iterate, eliminate, do_region, exit_bbs); iterate, eliminate, do_region, exit_bbs, false);
rpo_state[idx].visited++; rpo_state[idx].visited++;
/* Verify if changed values flow over executable outgoing backedges /* Verify if changed values flow over executable outgoing backedges
...@@ -6719,8 +6742,10 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6719,8 +6742,10 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge e; edge e;
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
if (!(e->flags & EDGE_EXECUTABLE) if (!(e->flags & EDGE_EXECUTABLE)
&& !rpo_state[bb_to_rpo[e->src->index]].visited && (bb == entry->dest
&& rpo_state[bb_to_rpo[e->src->index]].max_rpo >= (int)idx) || (!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)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Cannot trust state of predecessor " fprintf (dump_file, "Cannot trust state of predecessor "
...@@ -6731,7 +6756,8 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6731,7 +6756,8 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
nblk++; nblk++;
todo |= process_bb (avail, bb, false, false, false, eliminate, 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++; rpo_state[idx].visited++;
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
...@@ -6813,7 +6839,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, ...@@ -6813,7 +6839,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
} }
/* Region-based entry for RPO VN. Performs value-numbering and elimination /* 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 unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs) do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment