aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-loop-manip.cc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-02-26 15:17:43 +0100
committerRichard Biener <rguenther@suse.de>2024-02-27 09:11:36 +0100
commit8a5d9409584aeb777b06f9c19c7d1a3552d496ad (patch)
treec0c7877c18241f01574962b27ec10ca08513558b /gcc/tree-vect-loop-manip.cc
parent8e8eac3dea017eae739eb79d540887bb2cf1dc9f (diff)
downloadgcc-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.cc78
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);