aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2022-05-18 11:57:10 +0200
committerRichard Biener <rguenther@suse.de>2022-05-18 11:57:10 +0200
commit399a970a9e2302fa0ffefc03fad7d8d56801c2e6 (patch)
treecfa90a942bfa7127f0b3599e67c63582d423c79b
parent74ccb99070906ed9bbed2079e6ffba732ef1678d (diff)
downloadgcc-399a970a9e2302fa0ffefc03fad7d8d56801c2e6.zip
gcc-399a970a9e2302fa0ffefc03fad7d8d56801c2e6.tar.gz
gcc-399a970a9e2302fa0ffefc03fad7d8d56801c2e6.tar.bz2
Make sure to cost bb[0], work around unreachable predicates
This applies a workaround to avoid unswitching on predicates from BBs that are considered unreachable and to that effect makes sure to always cost bb[0] which we always put on the worklist as reachable.
-rw-r--r--gcc/tree-ssa-loop-unswitch.cc27
1 files changed, 17 insertions, 10 deletions
diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index c5d3762..d5ec23e 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -793,9 +793,11 @@ evaluate_insns (class loop *loop, basic_block *bbs,
int reachable_flag, int ignored_edge_flag)
{
auto_vec<basic_block> worklist (loop->num_nodes);
- worklist.quick_push (bbs[0]);
hash_set<edge> ignored_edges;
+ bbs[0]->flags |= reachable_flag;
+ worklist.quick_push (bbs[0]);
+
while (!worklist.is_empty ())
{
edge e;
@@ -804,10 +806,7 @@ evaluate_insns (class loop *loop, basic_block *bbs,
basic_block bb = worklist.pop ();
gimple *last = last_stmt (bb);
- gcond *cond = last != NULL ? dyn_cast<gcond *> (last) : NULL;
- gswitch *swtch = last != NULL ? dyn_cast<gswitch *> (last) : NULL;
-
- if (cond != NULL)
+ if (gcond *cond = safe_dyn_cast <gcond *> (last))
{
if (gimple_cond_true_p (cond))
flags = EDGE_FALSE_VALUE;
@@ -824,11 +823,11 @@ evaluate_insns (class loop *loop, basic_block *bbs,
? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
}
}
- else if (swtch != NULL
- && !get_predicates_for_bb (bb).is_empty ())
- evaluate_control_stmt_using_entry_checks (swtch, predicate_path,
- ignored_edge_flag,
- &ignored_edges);
+ else if (gswitch *swtch = safe_dyn_cast<gswitch *> (last))
+ if (!get_predicates_for_bb (bb).is_empty ())
+ evaluate_control_stmt_using_entry_checks (swtch, predicate_path,
+ ignored_edge_flag,
+ &ignored_edges);
/* ??? We fail to account for removed condition or switch stmts. */
@@ -909,6 +908,9 @@ tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
for (unsigned i = 0; i < loop->num_nodes; i++)
{
+ /* ??? The caller computed reachability of blocks when
+ evaluating costs but we are still processing predicates
+ on unreachable ones. */
for (auto pred : get_predicates_for_bb (bbs[i]))
{
if (bitmap_bit_p (handled, pred->num))
@@ -917,8 +919,13 @@ tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
evaluate_loop_insns_for_predicate (loop, bbs, predicate_path,
pred, ignored_edge_flag,
&true_size, &false_size);
+
gcc_assert (true_size + false_size >= loop_size);
+ /* When the block was unreachable the predicate has no effect. */
+ if (true_size == loop_size && false_size == loop_size)
+ continue;
+
/* FIXME: right now we select first candidate, but we can choose
the cheapest or hottest one. */
if (true_size + false_size < budget + loop_size)