This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Cleanup bb copying
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 1 Jul 2003 02:42:32 +0200
- Subject: [PATCH] Cleanup bb copying
Hello,
this patch adds a more clear way to copy set of basic blocks, and
uses it to decrease level of dark magic in loop duplication
significantly.
Zdenek
* 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.
Index: cfglayout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfglayout.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 cfglayout.c
*** cfglayout.c 27 Jun 2003 09:49:30 -0000 1.38
--- cfglayout.c 1 Jul 2003 00:34:13 -0000
*************** duplicate_insn_chain (rtx from, rtx to)
*** 1029,1035 ****
delete_insn (last);
return insn;
}
! /* Create a duplicate of the basic block BB and redirect edge E into it. */
basic_block
cfg_layout_duplicate_bb (basic_block bb, edge e)
--- 1029,1037 ----
delete_insn (last);
return insn;
}
! /* 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
cfg_layout_duplicate_bb (basic_block bb, edge e)
*************** cfg_layout_duplicate_bb (basic_block bb,
*** 1091,1119 ****
is no need to actually check for duplicated edges. */
n = unchecked_make_edge (new_bb, s->dest, s->flags);
n->probability = s->probability;
! if (new_count)
! /* Take care for overflows! */
! n->count = s->count * (new_count * 10000 / bb->count) / 10000;
else
! n->count = 0;
! s->count -= n->count;
}
- new_bb->count = new_count;
- bb->count -= new_count;
-
if (e)
{
new_bb->frequency = EDGE_FREQUENCY (e);
bb->frequency -= EDGE_FREQUENCY (e);
redirect_edge_and_branch_force (e, new_bb);
- }
! if (bb->count < 0)
! bb->count = 0;
! if (bb->frequency < 0)
! bb->frequency = 0;
RBI (new_bb)->original = bb;
RBI (bb)->copy = new_bb;
--- 1093,1129 ----
is no need to actually check for duplicated edges. */
n = unchecked_make_edge (new_bb, s->dest, s->flags);
n->probability = s->probability;
! if (e && bb->count)
! {
! /* Take care for overflows! */
! n->count = s->count * (new_count * 10000 / bb->count) / 10000;
! s->count -= n->count;
! }
else
! n->count = s->count;
! n->aux = s->aux;
}
if (e)
{
+ new_bb->count = new_count;
+ bb->count -= new_count;
+
new_bb->frequency = EDGE_FREQUENCY (e);
bb->frequency -= EDGE_FREQUENCY (e);
redirect_edge_and_branch_force (e, new_bb);
! if (bb->count < 0)
! bb->count = 0;
! if (bb->frequency < 0)
! bb->frequency = 0;
! }
! else
! {
! new_bb->count = bb->count;
! new_bb->frequency = bb->frequency;
! }
RBI (new_bb)->original = bb;
RBI (bb)->copy = new_bb;
*************** cfg_layout_finalize (void)
*** 1189,1194 ****
--- 1199,1321 ----
#ifdef ENABLE_CHECKING
verify_flow_info ();
#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++)
+ RBI (bbs[i])->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)
+ && RBI (e->dest)->duplicated)
+ {
+ ret = false;
+ goto end;
+ }
+
+ if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
+ {
+ ret = false;
+ break;
+ }
+ }
+
+ end:
+ for (i = 0; i < n; i++)
+ RBI (bbs[i])->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);
+ RBI (bb)->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 (RBI (dom_bb)->duplicated)
+ {
+ dom_bb = RBI (dom_bb)->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 (!RBI (e->dest)->duplicated)
+ continue;
+ redirect_edge_and_branch_force (e, RBI (e->dest)->copy);
+ }
+ }
+
+ /* Clear information about duplicates. */
+ for (i = 0; i < n; i++)
+ RBI (bbs[i])->duplicated = 0;
}
#include "gt-cfglayout.h"
Index: cfglayout.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfglayout.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 cfglayout.h
*** cfglayout.h 22 Jun 2003 15:03:26 -0000 1.7
--- cfglayout.h 1 Jul 2003 00:34:13 -0000
*************** extern bool cfg_layout_can_duplicate_bb_
*** 43,45 ****
--- 43,48 ----
extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
extern void insn_locators_initialize (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 *);
Index: cfgloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.c,v
retrieving revision 1.22
diff -c -3 -p -r1.22 cfgloop.c
*** cfgloop.c 22 Jun 2003 15:03:26 -0000 1.22
--- cfgloop.c 1 Jul 2003 00:34:14 -0000
*************** glb_enum_p (basic_block bb, void *glb_he
*** 960,966 ****
return bb != (basic_block) glb_header;
}
! /* Gets basic blocks of a loop. */
basic_block *
get_loop_body (const struct loop *loop)
{
--- 960,968 ----
return bb != (basic_block) glb_header;
}
! /* 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 *
get_loop_body (const struct loop *loop)
{
Index: cfgloopmanip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloopmanip.c,v
retrieving revision 1.9
diff -c -3 -p -r1.9 cfgloopmanip.c
*** cfgloopmanip.c 22 Jun 2003 15:03:26 -0000 1.9
--- cfgloopmanip.c 1 Jul 2003 00:34:15 -0000
*************** static void copy_loops_to (struct loops
*** 36,43 ****
struct loop *);
static void loop_redirect_edge (edge, basic_block);
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 bool rpe_enum_p (basic_block, void *);
static int find_path (edge, dominance_info, basic_block **);
--- 36,41 ----
*************** static void fix_bb_placements (struct lo
*** 49,56 ****
static void place_new_loop (struct loops *, struct loop *);
static void scale_loop_frequencies (struct loop *, 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 void fix_irreducible_loops (basic_block);
--- 47,52 ----
*************** add_loop (struct loops *loops, struct lo
*** 471,477 ****
free (bbs);
}
! /* Multiply all frequencies of basic blocks in array BBS of lenght NBBS
by NUM/DEN. */
static void
scale_bbs_frequencies (basic_block *bbs, int nbbs, int num, int den)
--- 467,473 ----
free (bbs);
}
! /* Multiply all frequencies of basic blocks in array BBS of length NBBS
by NUM/DEN. */
static void
scale_bbs_frequencies (basic_block *bbs, int nbbs, int num, int den)
*************** loop_delete_branch_edge (edge e, int rea
*** 820,1038 ****
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 neccessarily 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);
- RBI (new_bb)->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 = RBI (dom_bb)->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 (!RBI (src)->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
- || RBI (src)->original->loop_father == header->loop_father))
- e->flags |= EDGE_IRREDUCIBLE_LOOP;
- }
- }
-
- /* Redirect header edge. */
- bb = RBI (latch_edge->src)->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, RBI (header)->copy);
- *copy_header_edge = entry;
-
- /* Clear information about duplicates. */
- for (i = 0; i < n; i++)
- RBI ((*new_bbs)[i])->duplicated = 0;
- }
-
/* Check whether LOOP's body can be duplicated. */
bool
can_duplicate_loop_p (struct loop *loop)
{
! basic_block *bbs;
! unsigned i;
!
! bbs = get_loop_body (loop);
!
! 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);
!
! return true;
}
- /* 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 = RBI (orig->src)->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))
! /* Duplicates body of LOOP to given edge E NDUPL times. Takes care of
! updating LOOPS structure and dominators. E's destination must be LOOP
! header for this to work, i.e. it must be entry or latch edge of this loop;
! these are unique, as the loops must have preheaders for this function to
! work correctly (in case E is latch, the function unrolls the loop, if E is
! entry edge, it peels the loop). Store edges created by copying ORIG edge
! (if NULL, then all edges leaving loop) from copies corresponding to set
! bits in WONT_EXIT bitmap (bit 0 corresponds to original LOOP body, the
! other copies are numbered in order given by control flow through them)
! into TO_REMOVE array. Returns false if duplication is impossible. */
int
duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
unsigned int ndupl, sbitmap wont_exit,
--- 816,846 ----
return false; /* To avoid warning, cannot get here. */
}
/* Check whether LOOP's body can be duplicated. */
bool
can_duplicate_loop_p (struct loop *loop)
{
! int ret;
! basic_block *bbs = get_loop_body (loop);
! ret = can_copy_bbs_p (bbs, loop->num_nodes);
free (bbs);
!
! return ret;
}
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
! /* Duplicates body of LOOP to given edge E NDUPL times. Takes care of updating
! LOOPS structure and dominators. E's destination must be LOOP header for
! this to work, i.e. it must be entry or latch edge of this loop; these are
! unique, as the loops must have preheaders for this function to work
! correctly (in case E is latch, the function unrolls the loop, if E is entry
! edge, it peels the loop). Store edges created by copying ORIG edge from
! copies corresponding to set bits in WONT_EXIT bitmap (bit 0 corresponds to
! original LOOP body, the other copies are numbered in order given by control
! flow through them) into TO_REMOVE array. Returns false if duplication is
! impossible. */
int
duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
unsigned int ndupl, sbitmap wont_exit,
*************** duplicate_loop_to_header_edge (struct lo
*** 1045,1051 ****
basic_block header = loop->header, latch = loop->latch;
basic_block *new_bbs, *bbs, *first_active;
basic_block new_bb, bb, first_active_latch = NULL;
! edge ae, latch_edge, he;
unsigned i, j, n;
int is_latch = (latch == e->src);
int scale_act = 0, *scale_step = NULL, scale_main = 0;
--- 853,862 ----
basic_block header = loop->header, latch = loop->latch;
basic_block *new_bbs, *bbs, *first_active;
basic_block new_bb, bb, first_active_latch = NULL;
! edge ae, latch_edge;
! edge spec_edges[2], new_spec_edges[2];
! #define SE_LATCH 0
! #define SE_ORIG 1
unsigned i, j, n;
int is_latch = (latch == e->src);
int scale_act = 0, *scale_step = NULL, scale_main = 0;
*************** duplicate_loop_to_header_edge (struct lo
*** 1070,1086 ****
bbs = get_loop_body (loop);
/* Check whether duplication is possible. */
!
! for (i = 0; i < loop->num_nodes; i++)
{
! if (!cfg_layout_can_duplicate_bb_p (bbs[i]))
! {
! free (bbs);
! return false;
! }
}
! add_irreducible_flag = !is_latch && (e->flags & EDGE_IRREDUCIBLE_LOOP);
/* Find edge from latch. */
latch_edge = loop_latch_edge (loop);
--- 881,898 ----
bbs = get_loop_body (loop);
/* 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);
! /* 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. */
latch_edge = loop_latch_edge (loop);
*************** duplicate_loop_to_header_edge (struct lo
*** 1140,1146 ****
}
/* Loop the new bbs will belong to. */
! target = find_common_loop (e->src->loop_father, e->dest->loop_father);
/* Original loops. */
n_orig_loops = 0;
--- 952,958 ----
}
/* Loop the new bbs will belong to. */
! target = e->src->loop_father;
/* Original loops. */
n_orig_loops = 0;
*************** duplicate_loop_to_header_edge (struct lo
*** 1152,1170 ****
loop->copy = target;
- /* Original basic blocks. */
n = loop->num_nodes;
! first_active = xcalloc(n, sizeof (basic_block));
if (is_latch)
{
memcpy (first_active, bbs, n * sizeof (basic_block));
first_active_latch = latch;
}
! /* Record exit edges in original loop body. */
! if (TEST_BIT (wont_exit, 0))
! record_exit_edges (orig, bbs, n, to_remove, n_to_remove, true);
for (j = 0; j < ndupl; j++)
{
--- 964,984 ----
loop->copy = target;
n = loop->num_nodes;
! first_active = xmalloc (n * sizeof (basic_block));
if (is_latch)
{
memcpy (first_active, bbs, n * sizeof (basic_block));
first_active_latch = latch;
}
! /* Record exit edge in original loop body. */
! if (orig && TEST_BIT (wont_exit, 0))
! to_remove[(*n_to_remove)++] = orig;
!
! spec_edges[SE_ORIG] = orig;
! spec_edges[SE_LATCH] = latch_edge;
for (j = 0; j < ndupl; j++)
{
*************** duplicate_loop_to_header_edge (struct lo
*** 1172,1249 ****
copy_loops_to (loops, orig_loops, n_orig_loops, target);
/* Copy bbs. */
! copy_bbs (bbs, n, e, latch_edge, &new_bbs, loops,
! &e, &he, add_irreducible_flag);
if (is_latch)
! loop->latch = RBI (latch)->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];
! bb = bbs[i];
!
! if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
! new_bb->count = RDIV (scale_act * bb->count, REG_BR_PROB_BASE);
! new_bb->frequency = RDIV (scale_act * bb->frequency,
! REG_BR_PROB_BASE);
}
- else
- {
- new_bb->count = bb->count;
- new_bb->frequency = bb->frequency;
- }
-
- 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);
if (!first_active_latch)
{
memcpy (first_active, new_bbs, n * sizeof (basic_block));
! first_active_latch = RBI (latch)->copy;
}
! free (new_bbs);
!
! /* 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, RBI (latch)->copy);
! if (is_latch && j == 0)
{
! /* Update edge from latch. */
! for (latch_edge = RBI (header)->copy->pred;
! latch_edge->src != latch;
! latch_edge = latch_edge->pred_next);
}
}
! /* Now handle original loop. */
!
! /* Update edge counts. */
if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
! for (i = 0; i < n; i++)
! {
! 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 (orig_loops);
! /* Update dominators of other blocks if affected. */
for (i = 0; i < n; i++)
{
basic_block dominated, dom_bb, *dom_bbs;
--- 986,1060 ----
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, loops);
!
! /* Redirect the special edges. */
if (is_latch)
! {
! redirect_edge_and_branch_force (latch_edge, new_bbs[0]);
! redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
! loop->header);
! set_immediate_dominator (loops->cfg.dom, new_bbs[0], latch);
! latch = loop->latch = new_bbs[1];
! e = latch_edge = new_spec_edges[SE_LATCH];
! }
! else
! {
! redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
! loop->header);
! redirect_edge_and_branch_force (e, new_bbs[0]);
! set_immediate_dominator (loops->cfg.dom, new_bbs[0], e->src);
! e = new_spec_edges[SE_LATCH];
! }
! /* 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)
{
memcpy (first_active, new_bbs, n * sizeof (basic_block));
! first_active_latch = latch;
}
! /* Set counts and frequencies. */
! if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
! scale_bbs_frequencies (new_bbs, n, scale_act, REG_BR_PROB_BASE);
! scale_act = RDIV (scale_act * scale_step[j], REG_BR_PROB_BASE);
}
}
! free (new_bbs);
! free (orig_loops);
!
! /* Update the original loop. */
! if (!is_latch)
! set_immediate_dominator (loops->cfg.dom, e->dest, e->src);
if (flags & DLTHE_FLAG_UPDATE_FREQ)
{
! scale_bbs_frequencies (bbs, n, scale_main, REG_BR_PROB_BASE);
free (scale_step);
}
! /* Update dominators of outer blocks if affected. */
for (i = 0; i < n; i++)
{
basic_block dominated, dom_bb, *dom_bbs;