mirror of git://gcc.gnu.org/git/gcc.git
cfglayout.c (cfg_layout_duplicate_bb): Do not update frequencies at all if edge is not specified.
* cfglayout.c (cfg_layout_duplicate_bb): Do not update frequencies at all if edge is not specified. (can_copy_bbs_p, copy_bbs): New. * cfglayout.h (can_copy_bbs_p, copy_bbs): Declare. * cfgloop.c (get_loop_body): Comment more precisely. * cfgloopmanip.c (copy_bbs, record_exit_edges): Removed. (scale_bbs_frequencies): Fix comment typo. (can_duplicate_loop_p): Use can_copy_bbs_p. (duplicate_loop_to_header_edge): Simplify by using copy_bbs. From-SVN: r68906
This commit is contained in:
parent
694abeb6a7
commit
8d28e87da7
|
|
@ -1,3 +1,15 @@
|
||||||
|
2003-07-03 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
|
||||||
|
|
||||||
|
* cfglayout.c (cfg_layout_duplicate_bb): Do not update frequencies
|
||||||
|
at all if edge is not specified.
|
||||||
|
(can_copy_bbs_p, copy_bbs): New.
|
||||||
|
* cfglayout.h (can_copy_bbs_p, copy_bbs): Declare.
|
||||||
|
* cfgloop.c (get_loop_body): Comment more precisely.
|
||||||
|
* cfgloopmanip.c (copy_bbs, record_exit_edges): Removed.
|
||||||
|
(scale_bbs_frequencies): Fix comment typo.
|
||||||
|
(can_duplicate_loop_p): Use can_copy_bbs_p.
|
||||||
|
(duplicate_loop_to_header_edge): Simplify by using copy_bbs.
|
||||||
|
|
||||||
2003-07-03 Devang Patel <dpatel@apple.com>
|
2003-07-03 Devang Patel <dpatel@apple.com>
|
||||||
|
|
||||||
* c-opts.c (c_common_parse_file): Remove extra
|
* c-opts.c (c_common_parse_file): Remove extra
|
||||||
|
|
|
||||||
156
gcc/cfglayout.c
156
gcc/cfglayout.c
|
|
@ -985,7 +985,9 @@ duplicate_insn_chain (rtx from, rtx to)
|
||||||
delete_insn (last);
|
delete_insn (last);
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
/* Create a duplicate of the basic block BB and redirect edge E into it. */
|
/* Create a duplicate of the basic block BB and redirect edge E into it.
|
||||||
|
If E is not specified, BB is just copied, but updating the frequencies
|
||||||
|
etc. is left to the caller. */
|
||||||
|
|
||||||
basic_block
|
basic_block
|
||||||
cfg_layout_duplicate_bb (basic_block bb, edge e)
|
cfg_layout_duplicate_bb (basic_block bb, edge e)
|
||||||
|
|
@ -1046,32 +1048,41 @@ cfg_layout_duplicate_bb (basic_block bb, edge e)
|
||||||
is no need to actually check for duplicated edges. */
|
is no need to actually check for duplicated edges. */
|
||||||
n = unchecked_make_edge (new_bb, s->dest, s->flags);
|
n = unchecked_make_edge (new_bb, s->dest, s->flags);
|
||||||
n->probability = s->probability;
|
n->probability = s->probability;
|
||||||
if (new_count)
|
if (e && bb->count)
|
||||||
/* Take care for overflows! */
|
{
|
||||||
n->count = s->count * (new_count * 10000 / bb->count) / 10000;
|
/* Take care for overflows! */
|
||||||
|
n->count = s->count * (new_count * 10000 / bb->count) / 10000;
|
||||||
|
s->count -= n->count;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
n->count = 0;
|
n->count = s->count;
|
||||||
s->count -= n->count;
|
n->aux = s->aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_bb->count = new_count;
|
|
||||||
bb->count -= new_count;
|
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
new_bb->count = new_count;
|
||||||
|
bb->count -= new_count;
|
||||||
|
|
||||||
new_bb->frequency = EDGE_FREQUENCY (e);
|
new_bb->frequency = EDGE_FREQUENCY (e);
|
||||||
bb->frequency -= EDGE_FREQUENCY (e);
|
bb->frequency -= EDGE_FREQUENCY (e);
|
||||||
|
|
||||||
redirect_edge_and_branch_force (e, new_bb);
|
redirect_edge_and_branch_force (e, new_bb);
|
||||||
}
|
|
||||||
|
|
||||||
if (bb->count < 0)
|
if (bb->count < 0)
|
||||||
bb->count = 0;
|
bb->count = 0;
|
||||||
if (bb->frequency < 0)
|
if (bb->frequency < 0)
|
||||||
bb->frequency = 0;
|
bb->frequency = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_bb->count = bb->count;
|
||||||
|
new_bb->frequency = bb->frequency;
|
||||||
|
}
|
||||||
|
|
||||||
new_bb->rbi->original = bb;
|
new_bb->rbi->original = bb;
|
||||||
bb->rbi->copy = new_bb;
|
bb->rbi->copy = new_bb;
|
||||||
|
|
||||||
return new_bb;
|
return new_bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1167,4 +1178,121 @@ cfg_layout_finalize (void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Checks whether all N blocks in BBS array can be copied. */
|
||||||
|
bool
|
||||||
|
can_copy_bbs_p (basic_block *bbs, unsigned n)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
edge e;
|
||||||
|
int ret = true;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
bbs[i]->rbi->duplicated = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
/* In case we should redirect abnormal edge during duplication, fail. */
|
||||||
|
for (e = bbs[i]->succ; e; e = e->succ_next)
|
||||||
|
if ((e->flags & EDGE_ABNORMAL)
|
||||||
|
&& e->dest->rbi->duplicated)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
bbs[i]->rbi->duplicated = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Duplicates N basic blocks stored in array BBS. Newly created basic blocks
|
||||||
|
are placed into array NEW_BBS in the same order. Edges from basic blocks
|
||||||
|
in BBS are also duplicated and copies of those of them
|
||||||
|
that lead into BBS are redirected to appropriate newly created block. The
|
||||||
|
function assigns bbs into loops (copy of basic block bb is assigned to
|
||||||
|
bb->loop_father->copy loop, so this must be set up correctly in advance)
|
||||||
|
and updates dominators locally (LOOPS structure that contains the information
|
||||||
|
about dominators is passed to enable this).
|
||||||
|
|
||||||
|
BASE is the superloop to that basic block belongs; if its header or latch
|
||||||
|
is copied, we do not set the new blocks as header or latch.
|
||||||
|
|
||||||
|
Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
|
||||||
|
also in the same order. */
|
||||||
|
|
||||||
|
void
|
||||||
|
copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
|
||||||
|
edge *edges, unsigned n_edges, edge *new_edges,
|
||||||
|
struct loop *base, struct loops *loops)
|
||||||
|
{
|
||||||
|
unsigned i, j;
|
||||||
|
basic_block bb, new_bb, dom_bb;
|
||||||
|
edge e;
|
||||||
|
|
||||||
|
/* Duplicate bbs, update dominators, assign bbs to loops. */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
/* Duplicate. */
|
||||||
|
bb = bbs[i];
|
||||||
|
new_bb = new_bbs[i] = cfg_layout_duplicate_bb (bb, NULL);
|
||||||
|
bb->rbi->duplicated = 1;
|
||||||
|
/* Add to loop. */
|
||||||
|
add_bb_to_loop (new_bb, bb->loop_father->copy);
|
||||||
|
add_to_dominance_info (loops->cfg.dom, new_bb);
|
||||||
|
/* Possibly set header. */
|
||||||
|
if (bb->loop_father->header == bb && bb->loop_father != base)
|
||||||
|
new_bb->loop_father->header = new_bb;
|
||||||
|
/* Or latch. */
|
||||||
|
if (bb->loop_father->latch == bb && bb->loop_father != base)
|
||||||
|
new_bb->loop_father->latch = new_bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set dominators. */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
bb = bbs[i];
|
||||||
|
new_bb = new_bbs[i];
|
||||||
|
|
||||||
|
dom_bb = get_immediate_dominator (loops->cfg.dom, bb);
|
||||||
|
if (dom_bb->rbi->duplicated)
|
||||||
|
{
|
||||||
|
dom_bb = dom_bb->rbi->copy;
|
||||||
|
set_immediate_dominator (loops->cfg.dom, new_bb, dom_bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redirect edges. */
|
||||||
|
for (j = 0; j < n_edges; j++)
|
||||||
|
new_edges[j] = NULL;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
new_bb = new_bbs[i];
|
||||||
|
bb = bbs[i];
|
||||||
|
|
||||||
|
for (e = new_bb->succ; e; e = e->succ_next)
|
||||||
|
{
|
||||||
|
for (j = 0; j < n_edges; j++)
|
||||||
|
if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
|
||||||
|
new_edges[j] = e;
|
||||||
|
|
||||||
|
if (!e->dest->rbi->duplicated)
|
||||||
|
continue;
|
||||||
|
redirect_edge_and_branch_force (e, e->dest->rbi->copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear information about duplicates. */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
bbs[i]->rbi->duplicated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#include "gt-cfglayout.h"
|
#include "gt-cfglayout.h"
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,7 @@ extern bool cfg_layout_can_duplicate_bb_p (basic_block);
|
||||||
extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
|
extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
|
||||||
extern void insn_locators_initialize (void);
|
extern void insn_locators_initialize (void);
|
||||||
extern void reemit_insn_block_notes (void);
|
extern void reemit_insn_block_notes (void);
|
||||||
|
extern bool can_copy_bbs_p (basic_block *, unsigned);
|
||||||
|
extern void copy_bbs (basic_block *, unsigned, basic_block *,
|
||||||
|
edge *, unsigned, edge *, struct loop *, struct loops *);
|
||||||
extern void cfg_layout_initialize_rbi (basic_block);
|
extern void cfg_layout_initialize_rbi (basic_block);
|
||||||
|
|
|
||||||
|
|
@ -960,7 +960,9 @@ glb_enum_p (basic_block bb, void *glb_header)
|
||||||
return bb != (basic_block) glb_header;
|
return bb != (basic_block) glb_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets basic blocks of a loop. */
|
/* Gets basic blocks of a LOOP. Header is the 0-th block, rest is in dfs
|
||||||
|
order against direction of edges from latch. Specially, if
|
||||||
|
header != latch, latch is the 1-st block. */
|
||||||
basic_block *
|
basic_block *
|
||||||
get_loop_body (const struct loop *loop)
|
get_loop_body (const struct loop *loop)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@ static void copy_loops_to (struct loops *, struct loop **, int,
|
||||||
struct loop *);
|
struct loop *);
|
||||||
static void loop_redirect_edge (edge, basic_block);
|
static void loop_redirect_edge (edge, basic_block);
|
||||||
static bool loop_delete_branch_edge (edge, int);
|
static bool loop_delete_branch_edge (edge, int);
|
||||||
static void copy_bbs (basic_block *, int, edge, edge, basic_block **,
|
|
||||||
struct loops *, edge *, edge *, int);
|
|
||||||
static void remove_bbs (dominance_info, basic_block *, int);
|
static void remove_bbs (dominance_info, basic_block *, int);
|
||||||
static bool rpe_enum_p (basic_block, void *);
|
static bool rpe_enum_p (basic_block, void *);
|
||||||
static int find_path (edge, dominance_info, basic_block **);
|
static int find_path (edge, dominance_info, basic_block **);
|
||||||
|
|
@ -49,8 +47,6 @@ static void fix_bb_placements (struct loops *, basic_block);
|
||||||
static void place_new_loop (struct loops *, struct loop *);
|
static void place_new_loop (struct loops *, struct loop *);
|
||||||
static void scale_loop_frequencies (struct loop *, int, int);
|
static void scale_loop_frequencies (struct loop *, int, int);
|
||||||
static void scale_bbs_frequencies (basic_block *, int, int, int);
|
static void scale_bbs_frequencies (basic_block *, int, int, int);
|
||||||
static void record_exit_edges (edge, basic_block *, int, edge *, unsigned *,
|
|
||||||
int);
|
|
||||||
static basic_block create_preheader (struct loop *, dominance_info, int);
|
static basic_block create_preheader (struct loop *, dominance_info, int);
|
||||||
static void fix_irreducible_loops (basic_block);
|
static void fix_irreducible_loops (basic_block);
|
||||||
|
|
||||||
|
|
@ -820,219 +816,31 @@ loop_delete_branch_edge (edge e, int really_delete)
|
||||||
return false; /* To avoid warning, cannot get here. */
|
return false; /* To avoid warning, cannot get here. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Duplicates N basic blocks stored in array BBS (they form a body of
|
|
||||||
duplicated loop). Newly created basic blocks are placed into array NEW_BBS
|
|
||||||
that we allocate. Edges from basic blocks in BBS are also duplicated and
|
|
||||||
copies of those of them that lead into BBS are redirected to appropriate
|
|
||||||
newly created block. The function also assigns bbs into loops and updates
|
|
||||||
dominators. If ADD_IRREDUCIBLE_FLAG is set, newly created basic blocks that
|
|
||||||
are not members of any inner loop are marked irreducible.
|
|
||||||
|
|
||||||
Additionally, we perform following manipulation with edges:
|
|
||||||
We have two special edges given. LATCH_EDGE is the latch edge of the
|
|
||||||
duplicated loop and leads into its header (one of blocks in BBS);
|
|
||||||
it does not have necessarily lead from one of the blocks, because
|
|
||||||
we may be copying the loop body several times in unrolling.
|
|
||||||
Edge ENTRY leads also leads to header, and it is either latch or entry
|
|
||||||
edge. Copy of LATCH_EDGE is redirected to header and is stored in
|
|
||||||
HEADER_EDGE, the ENTRY edge is redirected into copy of header and
|
|
||||||
returned as COPY_HEADER_EDGE. The effect is following:
|
|
||||||
if LATCH_EDGE == ENTRY, then the loop is unrolled by one copy,
|
|
||||||
HEADER_EDGE is latch of a new loop, COPY_HEADER_EDGE leads from original
|
|
||||||
latch source to first block in copy.
|
|
||||||
if LATCH_EDGE != ENTRY, then the loop is peeled by one copy,
|
|
||||||
HEADER_EDGE is entry edge of the loop, COPY_HEADER_EDGE leads from
|
|
||||||
original entry block to first block in peeled copy.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
|
|
||||||
basic_block **new_bbs, struct loops *loops, edge *header_edge,
|
|
||||||
edge *copy_header_edge, int add_irreducible_flag)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
basic_block bb, new_bb, header = entry->dest, dom_bb;
|
|
||||||
edge e;
|
|
||||||
|
|
||||||
/* Duplicate bbs, update dominators, assign bbs to loops. */
|
|
||||||
(*new_bbs) = xcalloc (n, sizeof (basic_block));
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
/* Duplicate. */
|
|
||||||
bb = bbs[i];
|
|
||||||
new_bb = (*new_bbs)[i] = cfg_layout_duplicate_bb (bb, NULL);
|
|
||||||
new_bb->rbi->duplicated = 1;
|
|
||||||
/* Add to loop. */
|
|
||||||
add_bb_to_loop (new_bb, bb->loop_father->copy);
|
|
||||||
add_to_dominance_info (loops->cfg.dom, new_bb);
|
|
||||||
/* Possibly set header. */
|
|
||||||
if (bb->loop_father->header == bb && bb != header)
|
|
||||||
new_bb->loop_father->header = new_bb;
|
|
||||||
/* Or latch. */
|
|
||||||
if (bb->loop_father->latch == bb &&
|
|
||||||
bb->loop_father != header->loop_father)
|
|
||||||
new_bb->loop_father->latch = new_bb;
|
|
||||||
/* Take care of irreducible loops. */
|
|
||||||
if (add_irreducible_flag
|
|
||||||
&& bb->loop_father == header->loop_father)
|
|
||||||
new_bb->flags |= BB_IRREDUCIBLE_LOOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set dominators. */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
bb = bbs[i];
|
|
||||||
new_bb = (*new_bbs)[i];
|
|
||||||
if (bb != header)
|
|
||||||
{
|
|
||||||
/* For anything else than loop header, just copy it. */
|
|
||||||
dom_bb = get_immediate_dominator (loops->cfg.dom, bb);
|
|
||||||
dom_bb = dom_bb->rbi->copy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Copy of header is dominated by entry source. */
|
|
||||||
dom_bb = entry->src;
|
|
||||||
}
|
|
||||||
if (!dom_bb)
|
|
||||||
abort ();
|
|
||||||
set_immediate_dominator (loops->cfg.dom, new_bb, dom_bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect edges. */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
edge e_pred;
|
|
||||||
new_bb = (*new_bbs)[i];
|
|
||||||
bb = bbs[i];
|
|
||||||
for (e = bb->pred; e; e = e_pred)
|
|
||||||
{
|
|
||||||
basic_block src = e->src;
|
|
||||||
|
|
||||||
e_pred = e->pred_next;
|
|
||||||
|
|
||||||
if (!src->rbi->duplicated)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Leads to copied loop and it is not latch edge, redirect it. */
|
|
||||||
if (bb != header)
|
|
||||||
loop_redirect_edge (e, new_bb);
|
|
||||||
|
|
||||||
if (add_irreducible_flag
|
|
||||||
&& (bb->loop_father == header->loop_father
|
|
||||||
|| src->rbi->original->loop_father == header->loop_father))
|
|
||||||
e->flags |= EDGE_IRREDUCIBLE_LOOP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect header edge. */
|
|
||||||
bb = latch_edge->src->rbi->copy;
|
|
||||||
for (e = bb->succ; e->dest != latch_edge->dest; e = e->succ_next);
|
|
||||||
*header_edge = e;
|
|
||||||
loop_redirect_edge (*header_edge, header);
|
|
||||||
|
|
||||||
/* Redirect entry to copy of header. */
|
|
||||||
loop_redirect_edge (entry, header->rbi->copy);
|
|
||||||
*copy_header_edge = entry;
|
|
||||||
|
|
||||||
/* Clear information about duplicates. */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
(*new_bbs)[i]->rbi->duplicated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether LOOP's body can be duplicated. */
|
/* Check whether LOOP's body can be duplicated. */
|
||||||
bool
|
bool
|
||||||
can_duplicate_loop_p (struct loop *loop)
|
can_duplicate_loop_p (struct loop *loop)
|
||||||
{
|
{
|
||||||
basic_block *bbs;
|
int ret;
|
||||||
unsigned i;
|
basic_block *bbs = get_loop_body (loop);
|
||||||
|
|
||||||
bbs = get_loop_body (loop);
|
ret = can_copy_bbs_p (bbs, loop->num_nodes);
|
||||||
|
|
||||||
for (i = 0; i < loop->num_nodes; i++)
|
|
||||||
{
|
|
||||||
edge e;
|
|
||||||
|
|
||||||
/* In case loop contains abnormal edge we can not redirect,
|
|
||||||
we can't perform duplication. */
|
|
||||||
|
|
||||||
for (e = bbs[i]->succ; e; e = e->succ_next)
|
|
||||||
if ((e->flags & EDGE_ABNORMAL)
|
|
||||||
&& flow_bb_inside_loop_p (loop, e->dest))
|
|
||||||
{
|
|
||||||
free (bbs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
|
|
||||||
{
|
|
||||||
free (bbs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free (bbs);
|
free (bbs);
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record edges, leading from NBBS basic blocks stored in BBS, that were created
|
|
||||||
by copying ORIG edge (or just ORIG edge if IS_ORIG is set).
|
|
||||||
If ORIG is NULL, then record all edges coming outside of BBS. Store them
|
|
||||||
into TO_REMOVE array that must be large enough to hold them all; their
|
|
||||||
number is returned in N_TO_REMOVE. */
|
|
||||||
static void
|
|
||||||
record_exit_edges (edge orig, basic_block *bbs, int nbbs, edge *to_remove,
|
|
||||||
unsigned int *n_to_remove, int is_orig)
|
|
||||||
{
|
|
||||||
sbitmap my_blocks;
|
|
||||||
int i;
|
|
||||||
edge e;
|
|
||||||
|
|
||||||
if (orig)
|
|
||||||
{
|
|
||||||
if (is_orig)
|
|
||||||
{
|
|
||||||
to_remove[(*n_to_remove)++] = orig;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (e = orig->src->rbi->copy->succ; e; e = e->succ_next)
|
|
||||||
if (e->dest == orig->dest)
|
|
||||||
break;
|
|
||||||
if (!e)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
to_remove[(*n_to_remove)++] = e;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my_blocks = sbitmap_alloc (last_basic_block);
|
|
||||||
sbitmap_zero (my_blocks);
|
|
||||||
for (i = 0; i < nbbs; i++)
|
|
||||||
SET_BIT (my_blocks, bbs[i]->index);
|
|
||||||
|
|
||||||
for (i = 0; i < nbbs; i++)
|
|
||||||
for (e = bbs[i]->succ; e; e = e->succ_next)
|
|
||||||
if (e->dest == EXIT_BLOCK_PTR ||
|
|
||||||
!TEST_BIT (my_blocks, e->dest->index))
|
|
||||||
to_remove[(*n_to_remove)++] = e;
|
|
||||||
|
|
||||||
free (my_blocks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
|
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
|
||||||
|
|
||||||
/* Duplicates body of LOOP to given edge E NDUPL times. Takes care of
|
/* Duplicates body of LOOP to given edge E NDUPL times. Takes care of updating
|
||||||
updating LOOPS structure and dominators. E's destination must be LOOP
|
LOOPS structure and dominators. E's destination must be LOOP header for
|
||||||
header for this to work, i.e. it must be entry or latch edge of this loop;
|
this to work, i.e. it must be entry or latch edge of this loop; these are
|
||||||
these are unique, as the loops must have preheaders for this function to
|
unique, as the loops must have preheaders for this function to work
|
||||||
work correctly (in case E is latch, the function unrolls the loop, if E is
|
correctly (in case E is latch, the function unrolls the loop, if E is entry
|
||||||
entry edge, it peels the loop). Store edges created by copying ORIG edge
|
edge, it peels the loop). Store edges created by copying ORIG edge from
|
||||||
(if NULL, then all edges leaving loop) from copies corresponding to set
|
copies corresponding to set bits in WONT_EXIT bitmap (bit 0 corresponds to
|
||||||
bits in WONT_EXIT bitmap (bit 0 corresponds to original LOOP body, the
|
original LOOP body, the other copies are numbered in order given by control
|
||||||
other copies are numbered in order given by control flow through them)
|
flow through them) into TO_REMOVE array. Returns false if duplication is
|
||||||
into TO_REMOVE array. Returns false if duplication is impossible. */
|
impossible. */
|
||||||
int
|
int
|
||||||
duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
unsigned int ndupl, sbitmap wont_exit,
|
unsigned int ndupl, sbitmap wont_exit,
|
||||||
|
|
@ -1045,7 +853,10 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
basic_block header = loop->header, latch = loop->latch;
|
basic_block header = loop->header, latch = loop->latch;
|
||||||
basic_block *new_bbs, *bbs, *first_active;
|
basic_block *new_bbs, *bbs, *first_active;
|
||||||
basic_block new_bb, bb, first_active_latch = NULL;
|
basic_block new_bb, bb, first_active_latch = NULL;
|
||||||
edge ae, latch_edge, he;
|
edge ae, latch_edge;
|
||||||
|
edge spec_edges[2], new_spec_edges[2];
|
||||||
|
#define SE_LATCH 0
|
||||||
|
#define SE_ORIG 1
|
||||||
unsigned i, j, n;
|
unsigned i, j, n;
|
||||||
int is_latch = (latch == e->src);
|
int is_latch = (latch == e->src);
|
||||||
int scale_act = 0, *scale_step = NULL, scale_main = 0;
|
int scale_act = 0, *scale_step = NULL, scale_main = 0;
|
||||||
|
|
@ -1070,17 +881,18 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
bbs = get_loop_body (loop);
|
bbs = get_loop_body (loop);
|
||||||
|
|
||||||
/* Check whether duplication is possible. */
|
/* Check whether duplication is possible. */
|
||||||
|
if (!can_copy_bbs_p (bbs, loop->num_nodes))
|
||||||
for (i = 0; i < loop->num_nodes; i++)
|
|
||||||
{
|
{
|
||||||
if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
|
free (bbs);
|
||||||
{
|
return false;
|
||||||
free (bbs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes);
|
||||||
|
|
||||||
add_irreducible_flag = !is_latch && (e->flags & EDGE_IRREDUCIBLE_LOOP);
|
/* 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. */
|
||||||
|
add_irreducible_flag = e->flags & EDGE_IRREDUCIBLE_LOOP;
|
||||||
|
if (is_latch && add_irreducible_flag)
|
||||||
|
abort ();
|
||||||
|
|
||||||
/* Find edge from latch. */
|
/* Find edge from latch. */
|
||||||
latch_edge = loop_latch_edge (loop);
|
latch_edge = loop_latch_edge (loop);
|
||||||
|
|
@ -1140,7 +952,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop the new bbs will belong to. */
|
/* Loop the new bbs will belong to. */
|
||||||
target = find_common_loop (e->src->loop_father, e->dest->loop_father);
|
target = e->src->loop_father;
|
||||||
|
|
||||||
/* Original loops. */
|
/* Original loops. */
|
||||||
n_orig_loops = 0;
|
n_orig_loops = 0;
|
||||||
|
|
@ -1152,19 +964,21 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
|
|
||||||
loop->copy = target;
|
loop->copy = target;
|
||||||
|
|
||||||
/* Original basic blocks. */
|
|
||||||
n = loop->num_nodes;
|
n = loop->num_nodes;
|
||||||
|
|
||||||
first_active = xcalloc(n, sizeof (basic_block));
|
first_active = xmalloc (n * sizeof (basic_block));
|
||||||
if (is_latch)
|
if (is_latch)
|
||||||
{
|
{
|
||||||
memcpy (first_active, bbs, n * sizeof (basic_block));
|
memcpy (first_active, bbs, n * sizeof (basic_block));
|
||||||
first_active_latch = latch;
|
first_active_latch = latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record exit edges in original loop body. */
|
/* Record exit edge in original loop body. */
|
||||||
if (TEST_BIT (wont_exit, 0))
|
if (orig && TEST_BIT (wont_exit, 0))
|
||||||
record_exit_edges (orig, bbs, n, to_remove, n_to_remove, true);
|
to_remove[(*n_to_remove)++] = orig;
|
||||||
|
|
||||||
|
spec_edges[SE_ORIG] = orig;
|
||||||
|
spec_edges[SE_LATCH] = latch_edge;
|
||||||
|
|
||||||
for (j = 0; j < ndupl; j++)
|
for (j = 0; j < ndupl; j++)
|
||||||
{
|
{
|
||||||
|
|
@ -1172,78 +986,75 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
|
||||||
copy_loops_to (loops, orig_loops, n_orig_loops, target);
|
copy_loops_to (loops, orig_loops, n_orig_loops, target);
|
||||||
|
|
||||||
/* Copy bbs. */
|
/* Copy bbs. */
|
||||||
copy_bbs (bbs, n, e, latch_edge, &new_bbs, loops,
|
copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop, loops);
|
||||||
&e, &he, add_irreducible_flag);
|
|
||||||
|
/* Redirect the special edges. */
|
||||||
if (is_latch)
|
if (is_latch)
|
||||||
loop->latch = latch->rbi->copy;
|
|
||||||
|
|
||||||
/* Record exit edges in this copy. */
|
|
||||||
if (TEST_BIT (wont_exit, j + 1))
|
|
||||||
record_exit_edges (orig, new_bbs, n, to_remove, n_to_remove, false);
|
|
||||||
|
|
||||||
/* Set counts and frequencies. */
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
{
|
||||||
new_bb = new_bbs[i];
|
redirect_edge_and_branch_force (latch_edge, new_bbs[0]);
|
||||||
bb = bbs[i];
|
redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
|
||||||
|
loop->header);
|
||||||
if (flags & DLTHE_FLAG_UPDATE_FREQ)
|
set_immediate_dominator (loops->cfg.dom, new_bbs[0], latch);
|
||||||
{
|
latch = loop->latch = new_bbs[1];
|
||||||
new_bb->count = RDIV (scale_act * bb->count, REG_BR_PROB_BASE);
|
e = latch_edge = new_spec_edges[SE_LATCH];
|
||||||
new_bb->frequency = RDIV (scale_act * bb->frequency,
|
}
|
||||||
REG_BR_PROB_BASE);
|
else
|
||||||
}
|
{
|
||||||
else
|
redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
|
||||||
{
|
loop->header);
|
||||||
new_bb->count = bb->count;
|
redirect_edge_and_branch_force (e, new_bbs[0]);
|
||||||
new_bb->frequency = bb->frequency;
|
set_immediate_dominator (loops->cfg.dom, new_bbs[0], e->src);
|
||||||
}
|
e = new_spec_edges[SE_LATCH];
|
||||||
|
|
||||||
for (ae = new_bb->succ; ae; ae = ae->succ_next)
|
|
||||||
ae->count = RDIV (new_bb->count * ae->probability,
|
|
||||||
REG_BR_PROB_BASE);
|
|
||||||
}
|
}
|
||||||
if (flags & DLTHE_FLAG_UPDATE_FREQ)
|
|
||||||
scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
|
|
||||||
|
|
||||||
|
/* Record exit edge in this copy. */
|
||||||
|
if (orig && TEST_BIT (wont_exit, j + 1))
|
||||||
|
to_remove[(*n_to_remove)++] = new_spec_edges[SE_ORIG];
|
||||||
|
|
||||||
|
/* Note whether the blocks and edges belong to an irreducible loop. */
|
||||||
|
if (add_irreducible_flag)
|
||||||
|
{
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
new_bb = new_bbs[i];
|
||||||
|
if (new_bb->loop_father == target)
|
||||||
|
new_bb->flags |= BB_IRREDUCIBLE_LOOP;
|
||||||
|
|
||||||
|
for (ae = new_bb->succ; ae; ae = ae->succ_next)
|
||||||
|
if (ae->src->loop_father == target
|
||||||
|
|| ae->dest->loop_father == target)
|
||||||
|
ae->flags |= EDGE_IRREDUCIBLE_LOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record the first copy in the control flow order if it is not
|
||||||
|
the original loop (i.e. in case of peeling). */
|
||||||
if (!first_active_latch)
|
if (!first_active_latch)
|
||||||
{
|
{
|
||||||
memcpy (first_active, new_bbs, n * sizeof (basic_block));
|
memcpy (first_active, new_bbs, n * sizeof (basic_block));
|
||||||
first_active_latch = latch->rbi->copy;
|
first_active_latch = new_bbs[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
free (new_bbs);
|
/* Set counts and frequencies. */
|
||||||
|
if (flags & DLTHE_FLAG_UPDATE_FREQ)
|
||||||
/* Original loop header is dominated by latch copy
|
|
||||||
if we duplicated on its only entry edge. */
|
|
||||||
if (!is_latch && !header->pred->pred_next->pred_next)
|
|
||||||
set_immediate_dominator (loops->cfg.dom, header, latch->rbi->copy);
|
|
||||||
if (is_latch && j == 0)
|
|
||||||
{
|
{
|
||||||
/* Update edge from latch. */
|
scale_bbs_frequencies (new_bbs, n, scale_act, REG_BR_PROB_BASE);
|
||||||
for (latch_edge = header->rbi->copy->pred;
|
scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
|
||||||
latch_edge->src != latch;
|
|
||||||
latch_edge = latch_edge->pred_next);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Now handle original loop. */
|
free (new_bbs);
|
||||||
|
free (orig_loops);
|
||||||
/* Update edge counts. */
|
|
||||||
|
/* Update the original loop. */
|
||||||
|
if (!is_latch)
|
||||||
|
set_immediate_dominator (loops->cfg.dom, e->dest, e->src);
|
||||||
if (flags & DLTHE_FLAG_UPDATE_FREQ)
|
if (flags & DLTHE_FLAG_UPDATE_FREQ)
|
||||||
{
|
{
|
||||||
for (i = 0; i < n; i++)
|
scale_bbs_frequencies (bbs, n, scale_main, REG_BR_PROB_BASE);
|
||||||
{
|
|
||||||
bb = bbs[i];
|
|
||||||
bb->count = RDIV (scale_main * bb->count, REG_BR_PROB_BASE);
|
|
||||||
bb->frequency = RDIV (scale_main * bb->frequency, REG_BR_PROB_BASE);
|
|
||||||
for (ae = bb->succ; ae; ae = ae->succ_next)
|
|
||||||
ae->count = RDIV (bb->count * ae->probability, REG_BR_PROB_BASE);
|
|
||||||
}
|
|
||||||
free (scale_step);
|
free (scale_step);
|
||||||
}
|
}
|
||||||
free (orig_loops);
|
|
||||||
|
|
||||||
/* Update dominators of other blocks if affected. */
|
/* Update dominators of outer blocks if affected. */
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
basic_block dominated, dom_bb, *dom_bbs;
|
basic_block dominated, dom_bb, *dom_bbs;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue