diff options
author | Richard Biener <rguenther@suse.de> | 2024-02-26 15:17:43 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2024-02-27 09:11:36 +0100 |
commit | 8a5d9409584aeb777b06f9c19c7d1a3552d496ad (patch) | |
tree | c0c7877c18241f01574962b27ec10ca08513558b /gcc/tree-vect-loop-manip.cc | |
parent | 8e8eac3dea017eae739eb79d540887bb2cf1dc9f (diff) | |
download | gcc-8a5d9409584aeb777b06f9c19c7d1a3552d496ad.zip gcc-8a5d9409584aeb777b06f9c19c7d1a3552d496ad.tar.gz gcc-8a5d9409584aeb777b06f9c19c7d1a3552d496ad.tar.bz2 |
tree-optimization/114081 - dominator update for prologue peeling
The following implements manual update for multi-exit loop prologue
peeling during vectorization.
PR tree-optimization/114081
* tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg):
Perform manual dominator update for prologue peeling.
(vect_do_peeling): Properly update dominators after adding the
prologue-around guard.
* gcc.dg/vect/vect-early-break_121-pr114081.c: New testcase.
Diffstat (limited to 'gcc/tree-vect-loop-manip.cc')
-rw-r--r-- | gcc/tree-vect-loop-manip.cc | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 137b053..f72da91 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -1594,7 +1594,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, auto loop_exits = get_loop_exit_edges (loop); bool multiple_exits_p = loop_exits.length () > 1; auto_vec<basic_block> doms; - class loop *update_loop = NULL; if (at_exit) /* Add the loop copy at exit. */ { @@ -1856,11 +1855,33 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, correct. */ if (multiple_exits_p) { - update_loop = new_loop; + class loop *update_loop = new_loop; doms = get_all_dominated_blocks (CDI_DOMINATORS, loop->header); for (unsigned i = 0; i < doms.length (); ++i) if (flow_bb_inside_loop_p (loop, doms[i])) doms.unordered_remove (i); + + for (edge e : get_loop_exit_edges (update_loop)) + { + edge ex; + edge_iterator ei; + FOR_EACH_EDGE (ex, ei, e->dest->succs) + { + /* Find the first non-fallthrough block as fall-throughs can't + dominate other blocks. */ + if (single_succ_p (ex->dest)) + { + doms.safe_push (ex->dest); + ex = single_succ_edge (ex->dest); + } + doms.safe_push (ex->dest); + } + doms.safe_push (e->dest); + } + + iterate_fix_dominators (CDI_DOMINATORS, doms, false); + if (updated_doms) + updated_doms->safe_splice (doms); } } else /* Add the copy at entry. */ @@ -1910,33 +1931,28 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, edge loop_exit, set_immediate_dominator (CDI_DOMINATORS, new_loop->header, loop_preheader_edge (new_loop)->src); + /* Update dominators for multiple exits. */ if (multiple_exits_p) - update_loop = loop; - } - - if (multiple_exits_p) - { - for (edge e : get_loop_exit_edges (update_loop)) { - edge ex; - edge_iterator ei; - FOR_EACH_EDGE (ex, ei, e->dest->succs) + for (edge alt_e : loop_exits) { - /* Find the first non-fallthrough block as fall-throughs can't - dominate other blocks. */ - if (single_succ_p (ex->dest)) + if (alt_e == loop_exit) + continue; + basic_block old_dom + = get_immediate_dominator (CDI_DOMINATORS, alt_e->dest); + if (flow_bb_inside_loop_p (loop, old_dom)) { - doms.safe_push (ex->dest); - ex = single_succ_edge (ex->dest); + auto_vec<basic_block, 8> queue; + for (auto son = first_dom_son (CDI_DOMINATORS, old_dom); + son; son = next_dom_son (CDI_DOMINATORS, son)) + if (!flow_bb_inside_loop_p (loop, son)) + queue.safe_push (son); + for (auto son : queue) + set_immediate_dominator (CDI_DOMINATORS, + son, get_bb_copy (old_dom)); } - doms.safe_push (ex->dest); } - doms.safe_push (e->dest); } - - iterate_fix_dominators (CDI_DOMINATORS, doms, false); - if (updated_doms) - updated_doms->safe_splice (doms); } free (new_bbs); @@ -3368,6 +3384,24 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, guard_to, guard_bb, prob_prolog.invert (), irred_flag); + for (edge alt_e : get_loop_exit_edges (prolog)) + { + if (alt_e == prolog_e) + continue; + basic_block old_dom + = get_immediate_dominator (CDI_DOMINATORS, alt_e->dest); + if (flow_bb_inside_loop_p (prolog, old_dom)) + { + auto_vec<basic_block, 8> queue; + for (auto son = first_dom_son (CDI_DOMINATORS, old_dom); + son; son = next_dom_son (CDI_DOMINATORS, son)) + if (!flow_bb_inside_loop_p (prolog, son)) + queue.safe_push (son); + for (auto son : queue) + set_immediate_dominator (CDI_DOMINATORS, son, guard_bb); + } + } + e = EDGE_PRED (guard_to, 0); e = (e != guard_e ? e : EDGE_PRED (guard_to, 1)); slpeel_update_phi_nodes_for_guard1 (prolog, loop, guard_e, e); |