#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
-/* Splits basic block BB after INSN, returns created edge. Updates loops
- and dominators. */
-edge
-split_loop_bb (basic_block bb, void *insn)
-{
- edge e;
-
- /* Split the block. */
- e = split_block (bb, insn);
-
- /* Add dest to loop. */
- add_bb_to_loop (e->dest, e->src->loop_father);
-
- return e;
-}
-
/* Checks whether basic block BB is dominated by DATA. */
static bool
rpe_enum_p (basic_block bb, void *data)
gcc_assert (EDGE_COUNT (e->dest->preds) <= 1);
/* Find bbs in the path. */
- *bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ *bbs = XCNEWVEC (basic_block, n_basic_blocks);
return dfs_enumerate_from (e->dest, 0, rpe_enum_p, *bbs,
n_basic_blocks, e->dest);
}
/* Prevent us from going out of the base_loop. */
SET_BIT (in_queue, base_loop->header->index);
- queue = xmalloc ((base_loop->num_nodes + 1) * sizeof (basic_block));
+ queue = XNEWVEC (basic_block, base_loop->num_nodes + 1);
qtop = queue + base_loop->num_nodes + 1;
qbeg = queue;
qend = queue + 1;
on_stack = sbitmap_alloc (last_basic_block);
sbitmap_zero (on_stack);
SET_BIT (on_stack, from->index);
- stack = xmalloc (from->loop_father->num_nodes * sizeof (basic_block));
+ stack = XNEWVEC (basic_block, from->loop_father->num_nodes);
stack[0] = from;
stack_top = 1;
else
{
num_edges = EDGE_COUNT (bb->succs);
- edges = xmalloc (num_edges * sizeof (edge));
+ edges = XNEWVEC (edge, num_edges);
FOR_EACH_EDGE (e, ei, bb->succs)
edges[ei.index] = e;
}
nrem = find_path (e, &rem_bbs);
n_bord_bbs = 0;
- bord_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ bord_bbs = XCNEWVEC (basic_block, n_basic_blocks);
seen = sbitmap_alloc (last_basic_block);
sbitmap_zero (seen);
from = e->src;
deleted = loop_delete_branch_edge (e, 1);
gcc_assert (deleted);
- dom_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
/* Cancel loops contained in the path. */
for (i = 0; i < nrem; i++)
loop->level = 1;
/* Find its nodes. */
- bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ bbs = XCNEWVEC (basic_block, n_basic_blocks);
n = dfs_enumerate_from (loop->latch, 1, alp_enum_p,
bbs, n_basic_blocks, loop->header);
basic_block *dom_bbs, *body;
unsigned n_dom_bbs, i;
sbitmap seen;
- struct loop *loop = xcalloc (1, sizeof (struct loop));
+ struct loop *loop = XCNEW (struct loop);
struct loop *outer = succ_bb->loop_father->outer;
int freq, prob, tot_prob;
gcov_type cnt;
scale_loop_frequencies (succ_bb->loop_father, tot_prob - prob, tot_prob);
/* Update dominators of blocks outside of LOOP. */
- dom_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
+ dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
n_dom_bbs = 0;
seen = sbitmap_alloc (last_basic_block);
sbitmap_zero (seen);
duplicate_loop (struct loops *loops, struct loop *loop, struct loop *target)
{
struct loop *cloop;
- cloop = xcalloc (1, sizeof (struct loop));
+ cloop = XCNEW (struct loop);
place_new_loop (loops, cloop);
/* Initialize copied loop. */
int p, freq_in, freq_le, freq_out_orig;
int prob_pass_thru, prob_pass_wont_exit, prob_pass_main;
int add_irreducible_flag;
+ basic_block place_after;
gcc_assert (e->dest == loop->header);
gcc_assert (ndupl > 0);
gcc_assert (!flow_bb_inside_loop_p (loop, orig->dest));
}
- bbs = get_loop_body (loop);
+ n = loop->num_nodes;
+ bbs = get_loop_body_in_dom_order (loop);
+ gcc_assert (bbs[0] == loop->header);
+ gcc_assert (bbs[n - 1] == loop->latch);
/* Check whether duplication is possible. */
if (!can_copy_bbs_p (bbs, loop->num_nodes))
free (bbs);
return false;
}
- new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes);
+ new_bbs = XNEWVEC (basic_block, loop->num_nodes);
/* In case we are doing loop peeling and the loop is in the middle of
irreducible region, the peeled copies will be inside it too. */
prob_pass_wont_exit =
RDIV (REG_BR_PROB_BASE * (freq_le + freq_out_orig), freq_in);
- scale_step = xmalloc (ndupl * sizeof (int));
+ scale_step = XNEWVEC (int, ndupl);
for (i = 1; i <= ndupl; i++)
scale_step[i - 1] = TEST_BIT (wont_exit, i)
? prob_pass_wont_exit
: prob_pass_thru;
- /* Complette peeling is special as the probability of exit in last
+ /* Complete peeling is special as the probability of exit in last
copy becomes 1. */
if (flags & DLTHE_FLAG_COMPLETTE_PEEL)
{
wanted_freq = freq_in;
gcc_assert (!is_latch);
- /* First copy has frequency of incomming edge. Each subseqeuent
+ /* First copy has frequency of incoming edge. Each subsequent
frequency should be reduced by prob_pass_wont_exit. Caller
should've managed the flags so all except for original loop
has won't exist set. */
n_orig_loops = 0;
for (aloop = loop->inner; aloop; aloop = aloop->next)
n_orig_loops++;
- orig_loops = xcalloc (n_orig_loops, sizeof (struct loop *));
+ orig_loops = XCNEWVEC (struct loop *, n_orig_loops);
for (aloop = loop->inner, i = 0; aloop; aloop = aloop->next, i++)
orig_loops[i] = aloop;
loop->copy = target;
- n = loop->num_nodes;
-
- first_active = xmalloc (n * sizeof (basic_block));
+ first_active = XNEWVEC (basic_block, n);
if (is_latch)
{
memcpy (first_active, bbs, n * sizeof (basic_block));
spec_edges[SE_ORIG] = orig;
spec_edges[SE_LATCH] = latch_edge;
+ place_after = e->src;
for (j = 0; j < ndupl; j++)
{
/* Copy loops. */
copy_loops_to (loops, orig_loops, n_orig_loops, target);
/* Copy bbs. */
- copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop);
+ copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop,
+ place_after);
+ place_after = new_spec_edges[SE_LATCH]->src;
if (flags & DLTHE_RECORD_COPY_NUMBER)
for (i = 0; i < n; i++)
redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
loop->header);
set_immediate_dominator (CDI_DOMINATORS, new_bbs[0], latch);
- latch = loop->latch = new_bbs[1];
+ latch = loop->latch = new_bbs[n - 1];
e = latch_edge = new_spec_edges[SE_LATCH];
}
else
if (!first_active_latch)
{
memcpy (first_active, new_bbs, n * sizeof (basic_block));
- first_active_latch = new_bbs[1];
+ first_active_latch = new_bbs[n - 1];
}
/* Set counts and frequencies. */
free_dominance_info (CDI_DOMINATORS);
if (loops.num > 1)
{
- last = xcalloc (loops.num, sizeof (basic_block));
+ last = XCNEWVEC (basic_block, loops.num);
FOR_EACH_BB (bb)
{
last[loop->num] = bb;
}
- first = xcalloc (loops.num, sizeof (basic_block));
- stack = xcalloc (loops.num, sizeof (struct loop *));
+ first = XCNEWVEC (basic_block, loops.num);
+ stack = XCNEWVEC (struct loop *, loops.num);
top = stack;
FOR_EACH_BB (bb)
lv_adjust_loop_entry_edge (basic_block first_head,
basic_block second_head,
edge e,
- tree cond_expr)
+ void *cond_expr)
{
basic_block new_head = NULL;
edge e1;
lv_add_condition_to_bb (first_head, second_head, new_head,
cond_expr);
- e1 = make_edge (new_head, first_head, EDGE_TRUE_VALUE);
+ /* Don't set EDGE_TRUE_VALUE in RTL mode, as it's invalid there. */
+ e1 = make_edge (new_head, first_head, ir_type () ? EDGE_TRUE_VALUE : 0);
set_immediate_dominator (CDI_DOMINATORS, first_head, new_head);
set_immediate_dominator (CDI_DOMINATORS, second_head, new_head);
/* Main entry point for Loop Versioning transformation.
-This transformation given a condition and a loop, creates
--if (condition) { loop_copy1 } else { loop_copy2 },
-where loop_copy1 is the loop transformed in one way, and loop_copy2
-is the loop transformed in another way (or unchanged). 'condition'
-may be a run time test for things that were not resolved by static
-analysis (overlapping ranges (anti-aliasing), alignment, etc.). */
+ This transformation given a condition and a loop, creates
+ -if (condition) { loop_copy1 } else { loop_copy2 },
+ where loop_copy1 is the loop transformed in one way, and loop_copy2
+ is the loop transformed in another way (or unchanged). 'condition'
+ may be a run time test for things that were not resolved by static
+ analysis (overlapping ranges (anti-aliasing), alignment, etc.).
+
+ If PLACE_AFTER is true, we place the new loop after LOOP in the
+ instruction stream, otherwise it is placed before LOOP. */
struct loop *
loop_version (struct loops *loops, struct loop * loop,
- void *cond_expr, basic_block *condition_bb)
+ void *cond_expr, basic_block *condition_bb,
+ bool place_after)
{
basic_block first_head, second_head;
edge entry, latch_edge, exit, true_edge, false_edge;
int irred_flag;
struct loop *nloop;
+ basic_block cond_bb;
/* CHECKME: Loop versioning does not handle nested loop at this point. */
if (loop->inner)
second_head = entry->dest;
/* Split loop entry edge and insert new block with cond expr. */
- *condition_bb = lv_adjust_loop_entry_edge (first_head, second_head,
- entry, cond_expr);
- if (!*condition_bb)
+ cond_bb = lv_adjust_loop_entry_edge (first_head, second_head,
+ entry, cond_expr);
+ if (condition_bb)
+ *condition_bb = cond_bb;
+
+ if (!cond_bb)
{
entry->flags |= irred_flag;
return NULL;
latch_edge = single_succ_edge (get_bb_copy (loop->latch));
- extract_cond_bb_edges (*condition_bb, &true_edge, &false_edge);
+ extract_cond_bb_edges (cond_bb, &true_edge, &false_edge);
nloop = loopify (loops,
latch_edge,
single_pred_edge (get_bb_copy (loop->header)),
- *condition_bb, true_edge, false_edge,
+ cond_bb, true_edge, false_edge,
false /* Do not redirect all edges. */);
exit = loop->single_exit;
lv_flush_pending_stmts (latch_edge);
/* loopify redirected condition_bb's succ edge. Update its PENDING_STMTS. */
- extract_cond_bb_edges (*condition_bb, &true_edge, &false_edge);
+ extract_cond_bb_edges (cond_bb, &true_edge, &false_edge);
lv_flush_pending_stmts (false_edge);
/* Adjust irreducible flag. */
if (irred_flag)
{
- (*condition_bb)->flags |= BB_IRREDUCIBLE_LOOP;
+ cond_bb->flags |= BB_IRREDUCIBLE_LOOP;
loop_preheader_edge (loop)->flags |= EDGE_IRREDUCIBLE_LOOP;
loop_preheader_edge (nloop)->flags |= EDGE_IRREDUCIBLE_LOOP;
- single_pred_edge ((*condition_bb))->flags |= EDGE_IRREDUCIBLE_LOOP;
+ single_pred_edge (cond_bb)->flags |= EDGE_IRREDUCIBLE_LOOP;
+ }
+
+ if (place_after)
+ {
+ basic_block *bbs = get_loop_body_in_dom_order (nloop), after;
+ unsigned i;
+
+ after = loop->latch;
+
+ for (i = 0; i < nloop->num_nodes; i++)
+ {
+ move_block_after (bbs[i], after);
+ after = bbs[i];
+ }
+ free (bbs);
}
/* At this point condition_bb is loop predheader with two successors,
}
/* Remove the dead loops from structures. */
- loops->tree_root->num_nodes = n_basic_blocks + 2;
+ loops->tree_root->num_nodes = n_basic_blocks;
for (i = 1; i < loops->num; i++)
{
loop = loops->parray[i];
bb->aux = NULL;
}
- mark_single_exit_loops (loops);
- mark_irreducible_loops (loops);
+ if (loops->state & LOOPS_HAVE_MARKED_SINGLE_EXITS)
+ mark_single_exit_loops (loops);
+ if (loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+ mark_irreducible_loops (loops);
}