diff options
author | Richard Biener <rguenther@suse.de> | 2022-05-18 11:57:10 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2022-05-18 11:57:10 +0200 |
commit | 399a970a9e2302fa0ffefc03fad7d8d56801c2e6 (patch) | |
tree | cfa90a942bfa7127f0b3599e67c63582d423c79b | |
parent | 74ccb99070906ed9bbed2079e6ffba732ef1678d (diff) | |
download | gcc-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.cc | 27 |
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) |