Commit 35b07080 by Zdenek Dvorak Committed by Zdenek Dvorak

basic-block.h (EDGE_IRREDUCIBLE_LOOP, [...]): New.

	* basic-block.h (EDGE_IRREDUCIBLE_LOOP, EDGE_ALL_FLAGS): New.
	* cfg.c (dump_edge_info): Add EDGE_IRREDUCIBLE_LOOP flag dump.
	* cfgloop.c (flow_loop_free): Made global.
	(establish_preds): New static function.
	(flow_loop_tree_node_add): Handle subloops of added loop correctly.
	(get_loop_exit_edges): New.
	(verify_loop_structure): Verify EDGE_IRREDUCIBLE_LOOP flags.
	* cfgloop.h (flow_loop_free, get_loop_exit_edges, unloop): Declare.
	* cfgloopanal.c (mark_irreducible_loops): Mark edges in irreducible
	loops.
	* cfgloopmanip.c (loop_delete_branch_edge): Allow to test for
	removability of an edge.
	(fix_irreducible_loops): New static function.
	(find_path, remove_path): Add ability to remove enclosing loops.
	(unloop): New.
	(copy_bbs, duplicate_loop_to_header_edge): Use EDGE_IRREDUCIBLE_LOOP
	flags.
	* cfgrtl.c (verify_flow_info): Handle EDGE_IRREDUCIBLE_LOOP flag.
	* loop-unroll.c (peel_loops_completely): Do not duplicate loop if
	not neccessary.
	(decide_peel_completely, peel_loops_completely): Allow complete peeling
	of non-duplicable once rolling loops.
	* loop-unswitch.c (unswitch_loop): Update EDGE_IRREDUCIBLE_LOOP flags.

From-SVN: r63864
parent bb182d23
2003-03-05 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* basic-block.h (EDGE_IRREDUCIBLE_LOOP, EDGE_ALL_FLAGS): New.
* cfg.c (dump_edge_info): Add EDGE_IRREDUCIBLE_LOOP flag dump.
* cfgloop.c (flow_loop_free): Made global.
(establish_preds): New static function.
(flow_loop_tree_node_add): Handle subloops of added loop correctly.
(get_loop_exit_edges): New.
(verify_loop_structure): Verify EDGE_IRREDUCIBLE_LOOP flags.
* cfgloop.h (flow_loop_free, get_loop_exit_edges, unloop): Declare.
* cfgloopanal.c (mark_irreducible_loops): Mark edges in irreducible
loops.
* cfgloopmanip.c (loop_delete_branch_edge): Allow to test for
removability of an edge.
(fix_irreducible_loops): New static function.
(find_path, remove_path): Add ability to remove enclosing loops.
(unloop): New.
(copy_bbs, duplicate_loop_to_header_edge): Use EDGE_IRREDUCIBLE_LOOP
flags.
* cfgrtl.c (verify_flow_info): Handle EDGE_IRREDUCIBLE_LOOP flag.
* loop-unroll.c (peel_loops_completely): Do not duplicate loop if
not neccessary.
(decide_peel_completely, peel_loops_completely): Allow complete peeling
of non-duplicable once rolling loops.
* loop-unswitch.c (unswitch_loop): Update EDGE_IRREDUCIBLE_LOOP flags.
Wed Mar 5 21:40:57 2003 J"orn Rennecke <joern.rennecke@superh.com> Wed Mar 5 21:40:57 2003 J"orn Rennecke <joern.rennecke@superh.com>
* sh.h (OVERRIDE_OPTIONS): For TARGET_SHMEDIA, the minimum value * sh.h (OVERRIDE_OPTIONS): For TARGET_SHMEDIA, the minimum value
......
...@@ -150,6 +150,8 @@ typedef struct edge_def { ...@@ -150,6 +150,8 @@ typedef struct edge_def {
#define EDGE_DFS_BACK 32 /* A backwards edge */ #define EDGE_DFS_BACK 32 /* A backwards edge */
#define EDGE_CAN_FALLTHRU 64 /* Candidate for straight line #define EDGE_CAN_FALLTHRU 64 /* Candidate for straight line
flow. */ flow. */
#define EDGE_IRREDUCIBLE_LOOP 128 /* Part of irreducible loop. */
#define EDGE_ALL_FLAGS 255
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH) #define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
...@@ -540,7 +542,7 @@ extern void init_flow PARAMS ((void)); ...@@ -540,7 +542,7 @@ extern void init_flow PARAMS ((void));
extern void reorder_basic_blocks PARAMS ((void)); extern void reorder_basic_blocks PARAMS ((void));
extern void dump_bb PARAMS ((basic_block, FILE *)); extern void dump_bb PARAMS ((basic_block, FILE *));
extern void debug_bb PARAMS ((basic_block)); extern void debug_bb PARAMS ((basic_block));
extern void debug_bb_n PARAMS ((int)); extern basic_block debug_bb_n PARAMS ((int));
extern void dump_regset PARAMS ((regset, FILE *)); extern void dump_regset PARAMS ((regset, FILE *));
extern void debug_regset PARAMS ((regset)); extern void debug_regset PARAMS ((regset));
extern void allocate_reg_life_data PARAMS ((void)); extern void allocate_reg_life_data PARAMS ((void));
......
...@@ -639,7 +639,7 @@ dump_edge_info (file, e, do_succ) ...@@ -639,7 +639,7 @@ dump_edge_info (file, e, do_succ)
if (e->flags) if (e->flags)
{ {
static const char * const bitnames[] static const char * const bitnames[]
= {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"}; = {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru","irreducible"};
int comma = 0; int comma = 0;
int i, flags = e->flags; int i, flags = e->flags;
......
...@@ -43,12 +43,12 @@ static basic_block flow_loop_pre_header_find PARAMS ((basic_block, ...@@ -43,12 +43,12 @@ static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
dominance_info)); dominance_info));
static int flow_loop_level_compute PARAMS ((struct loop *)); static int flow_loop_level_compute PARAMS ((struct loop *));
static int flow_loops_level_compute PARAMS ((struct loops *)); static int flow_loops_level_compute PARAMS ((struct loops *));
static void establish_preds PARAMS ((struct loop *));
static basic_block make_forwarder_block PARAMS ((basic_block, int, int, static basic_block make_forwarder_block PARAMS ((basic_block, int, int,
edge, int)); edge, int));
static void canonicalize_loop_headers PARAMS ((void)); static void canonicalize_loop_headers PARAMS ((void));
static bool glb_enum_p PARAMS ((basic_block, void *)); static bool glb_enum_p PARAMS ((basic_block, void *));
static void redirect_edge_with_latch_update PARAMS ((edge, basic_block)); static void redirect_edge_with_latch_update PARAMS ((edge, basic_block));
static void flow_loop_free PARAMS ((struct loop *));
/* Dump loop related CFG information. */ /* Dump loop related CFG information. */
...@@ -185,7 +185,7 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose) ...@@ -185,7 +185,7 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose)
} }
/* Free data allocated for LOOP. */ /* Free data allocated for LOOP. */
static void void
flow_loop_free (loop) flow_loop_free (loop)
struct loop *loop; struct loop *loop;
{ {
...@@ -447,8 +447,26 @@ flow_loop_pre_header_find (header, dom) ...@@ -447,8 +447,26 @@ flow_loop_pre_header_find (header, dom)
return pre_header; return pre_header;
} }
static void
establish_preds (loop)
struct loop *loop;
{
struct loop *ploop, *father = loop->outer;
loop->depth = father->depth + 1;
if (loop->pred)
free (loop->pred);
loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
loop->pred[father->depth] = father;
for (ploop = loop->inner; ploop; ploop = ploop->next)
establish_preds (ploop);
}
/* Add LOOP to the loop hierarchy tree where FATHER is father of the /* Add LOOP to the loop hierarchy tree where FATHER is father of the
added loop. */ added loop. If LOOP has some children, take care of that their
pred field will be initialized correctly. */
void void
flow_loop_tree_node_add (father, loop) flow_loop_tree_node_add (father, loop)
...@@ -459,10 +477,7 @@ flow_loop_tree_node_add (father, loop) ...@@ -459,10 +477,7 @@ flow_loop_tree_node_add (father, loop)
father->inner = loop; father->inner = loop;
loop->outer = father; loop->outer = father;
loop->depth = father->depth + 1; establish_preds (loop);
loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
loop->pred[father->depth] = father;
} }
/* Remove LOOP from the loop hierarchy tree. */ /* Remove LOOP from the loop hierarchy tree. */
...@@ -1029,6 +1044,37 @@ get_loop_body (loop) ...@@ -1029,6 +1044,37 @@ get_loop_body (loop)
return tovisit; return tovisit;
} }
/* Gets exit edges of a LOOP, returning their number in N_EDGES. */
edge *
get_loop_exit_edges (loop, n_edges)
const struct loop *loop;
unsigned *n_edges;
{
edge *edges, e;
unsigned i, n;
basic_block * body;
if (loop->latch == EXIT_BLOCK_PTR)
abort ();
body = get_loop_body (loop);
n = 0;
for (i = 0; i < loop->num_nodes; i++)
for (e = body[i]->succ; e; e = e->succ_next)
if (!flow_bb_inside_loop_p (loop, e->dest))
n++;
edges = xmalloc (n * sizeof (edge));
*n_edges = n;
n = 0;
for (i = 0; i < loop->num_nodes; i++)
for (e = body[i]->succ; e; e = e->succ_next)
if (!flow_bb_inside_loop_p (loop, e->dest))
edges[n++] = e;
free (body);
return edges;
}
/* Adds basic block BB to LOOP. */ /* Adds basic block BB to LOOP. */
void void
add_bb_to_loop (bb, loop) add_bb_to_loop (bb, loop)
...@@ -1135,6 +1181,7 @@ verify_loop_structure (loops) ...@@ -1135,6 +1181,7 @@ verify_loop_structure (loops)
basic_block *bbs, bb; basic_block *bbs, bb;
struct loop *loop; struct loop *loop;
int err = 0; int err = 0;
edge e;
/* Check sizes. */ /* Check sizes. */
sizes = xcalloc (loops->num, sizeof (int)); sizes = xcalloc (loops->num, sizeof (int));
...@@ -1215,6 +1262,12 @@ verify_loop_structure (loops) ...@@ -1215,6 +1262,12 @@ verify_loop_structure (loops)
error ("Loop %d's header does not belong directly to it.", i); error ("Loop %d's header does not belong directly to it.", i);
err = 1; err = 1;
} }
if ((loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
&& (loop_latch_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP))
{
error ("Loop %d's latch is marked as part of irreducible region.", i);
err = 1;
}
} }
/* Check irreducible loops. */ /* Check irreducible loops. */
...@@ -1223,10 +1276,15 @@ verify_loop_structure (loops) ...@@ -1223,10 +1276,15 @@ verify_loop_structure (loops)
/* Record old info. */ /* Record old info. */
irreds = sbitmap_alloc (last_basic_block); irreds = sbitmap_alloc (last_basic_block);
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
if (bb->flags & BB_IRREDUCIBLE_LOOP) {
SET_BIT (irreds, bb->index); if (bb->flags & BB_IRREDUCIBLE_LOOP)
else SET_BIT (irreds, bb->index);
RESET_BIT (irreds, bb->index); else
RESET_BIT (irreds, bb->index);
for (e = bb->succ; e; e = e->succ_next)
if (e->flags & EDGE_IRREDUCIBLE_LOOP)
e->flags |= EDGE_ALL_FLAGS + 1;
}
/* Recount it. */ /* Recount it. */
mark_irreducible_loops (loops); mark_irreducible_loops (loops);
...@@ -1246,6 +1304,24 @@ verify_loop_structure (loops) ...@@ -1246,6 +1304,24 @@ verify_loop_structure (loops)
error ("Basic block %d should not be marked irreducible.", bb->index); error ("Basic block %d should not be marked irreducible.", bb->index);
err = 1; err = 1;
} }
for (e = bb->succ; e; e = e->succ_next)
{
if ((e->flags & EDGE_IRREDUCIBLE_LOOP)
&& !(e->flags & (EDGE_ALL_FLAGS + 1)))
{
error ("Edge from %d to %d should be marked irreducible.",
e->src->index, e->dest->index);
err = 1;
}
else if (!(e->flags & EDGE_IRREDUCIBLE_LOOP)
&& (e->flags & (EDGE_ALL_FLAGS + 1)))
{
error ("Edge from %d to %d should not be marked irreducible.",
e->src->index, e->dest->index);
err = 1;
}
e->flags &= ~(EDGE_ALL_FLAGS + 1);
}
} }
free (irreds); free (irreds);
} }
......
...@@ -266,6 +266,7 @@ extern void flow_loop_dump PARAMS ((const struct loop *, FILE *, ...@@ -266,6 +266,7 @@ extern void flow_loop_dump PARAMS ((const struct loop *, FILE *,
FILE *, int), int)); FILE *, int), int));
extern int flow_loop_scan PARAMS ((struct loops *, extern int flow_loop_scan PARAMS ((struct loops *,
struct loop *, int)); struct loop *, int));
extern void flow_loop_free PARAMS ((struct loop *));
void mark_irreducible_loops PARAMS ((struct loops *)); void mark_irreducible_loops PARAMS ((struct loops *));
/* Loop datastructure manipulation/querying. */ /* Loop datastructure manipulation/querying. */
...@@ -282,6 +283,7 @@ extern int average_num_loop_insns PARAMS ((struct loop *)); ...@@ -282,6 +283,7 @@ extern int average_num_loop_insns PARAMS ((struct loop *));
/* Loops & cfg manipulation. */ /* Loops & cfg manipulation. */
extern basic_block *get_loop_body PARAMS ((const struct loop *)); extern basic_block *get_loop_body PARAMS ((const struct loop *));
extern edge *get_loop_exit_edges PARAMS ((const struct loop *, unsigned *));
extern edge loop_preheader_edge PARAMS ((const struct loop *)); extern edge loop_preheader_edge PARAMS ((const struct loop *));
extern edge loop_latch_edge PARAMS ((const struct loop *)); extern edge loop_latch_edge PARAMS ((const struct loop *));
...@@ -326,6 +328,7 @@ extern int duplicate_loop_to_header_edge PARAMS ((struct loop *, edge, ...@@ -326,6 +328,7 @@ extern int duplicate_loop_to_header_edge PARAMS ((struct loop *, edge,
unsigned *, int)); unsigned *, int));
extern struct loop *loopify PARAMS ((struct loops *, edge, extern struct loop *loopify PARAMS ((struct loops *, edge,
edge, basic_block)); edge, basic_block));
extern void unloop PARAMS ((struct loops *, struct loop *));
extern bool remove_path PARAMS ((struct loops *, edge)); extern bool remove_path PARAMS ((struct loops *, edge));
extern edge split_loop_bb PARAMS ((struct loops *, basic_block, extern edge split_loop_bb PARAMS ((struct loops *, basic_block,
rtx)); rtx));
......
...@@ -819,12 +819,12 @@ simple_loop_p (loops, loop, desc) ...@@ -819,12 +819,12 @@ simple_loop_p (loops, loop, desc)
return any; return any;
} }
/* Marks blocks that are part of non-recognized loops; i.e. we throw away /* Marks blocks and edges that are part of non-recognized loops; i.e. we
all latch edges and mark blocks inside any remaining cycle. Everything throw away all latch edges and mark blocks inside any remaining cycle.
is a bit complicated due to fact we do not want to do this for parts of Everything is a bit complicated due to fact we do not want to do this
cycles that only "pass" through some loop -- i.e. for each cycle, we want for parts of cycles that only "pass" through some loop -- i.e. for
to mark blocks that belong directly to innermost loop containing the whole each cycle, we want to mark blocks that belong directly to innermost
cycle. */ loop containing the whole cycle. */
void void
mark_irreducible_loops (loops) mark_irreducible_loops (loops)
struct loops *loops; struct loops *loops;
...@@ -832,10 +832,19 @@ mark_irreducible_loops (loops) ...@@ -832,10 +832,19 @@ mark_irreducible_loops (loops)
int *dfs_in, *closed, *mr, *mri, *n_edges, *stack; int *dfs_in, *closed, *mr, *mri, *n_edges, *stack;
unsigned i; unsigned i;
edge **edges, e; edge **edges, e;
edge *estack;
basic_block act; basic_block act;
int stack_top, tick, depth; int stack_top, tick, depth;
struct loop *cloop; struct loop *cloop;
/* Reset the flags. */
FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
act->flags &= ~BB_IRREDUCIBLE_LOOP;
for (e = act->succ; e; e = e->succ_next)
e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
}
/* The first last_basic_block + 1 entries are for real blocks (including /* The first last_basic_block + 1 entries are for real blocks (including
entry); then we have loops->num - 1 fake blocks for loops to that we entry); then we have loops->num - 1 fake blocks for loops to that we
assign edges leading from loops (fake loop 0 is not interesting). */ assign edges leading from loops (fake loop 0 is not interesting). */
...@@ -846,6 +855,7 @@ mark_irreducible_loops (loops) ...@@ -846,6 +855,7 @@ mark_irreducible_loops (loops)
n_edges = xmalloc ((last_basic_block + loops->num) * sizeof (int)); n_edges = xmalloc ((last_basic_block + loops->num) * sizeof (int));
edges = xmalloc ((last_basic_block + loops->num) * sizeof (edge *)); edges = xmalloc ((last_basic_block + loops->num) * sizeof (edge *));
stack = xmalloc ((n_basic_blocks + loops->num) * sizeof (int)); stack = xmalloc ((n_basic_blocks + loops->num) * sizeof (int));
estack = xmalloc ((n_basic_blocks + loops->num) * sizeof (edge));
/* Create the edge lists. */ /* Create the edge lists. */
for (i = 0; i < last_basic_block + loops->num; i++) for (i = 0; i < last_basic_block + loops->num; i++)
...@@ -923,7 +933,11 @@ mark_irreducible_loops (loops) ...@@ -923,7 +933,11 @@ mark_irreducible_loops (loops)
stack_top = 0; stack_top = 0;
for (i = 0; i < loops->num; i++) for (i = 0; i < loops->num; i++)
if (loops->parray[i]) if (loops->parray[i])
stack[stack_top++] = loops->parray[i]->header->index + 1; {
stack[stack_top] = loops->parray[i]->header->index + 1;
estack[stack_top] = NULL;
stack_top++;
}
while (stack_top) while (stack_top)
{ {
...@@ -941,16 +955,24 @@ mark_irreducible_loops (loops) ...@@ -941,16 +955,24 @@ mark_irreducible_loops (loops)
: e->dest->index + 1; : e->dest->index + 1;
if (closed[sidx]) if (closed[sidx])
{ {
if (mr[sidx] < mr[idx] && !closed[mri[sidx]]) if (!closed[mri[sidx]])
{ {
mr[idx] = mr[sidx]; if (mr[sidx] < mr[idx])
mri[idx] = mri[sidx]; {
mr[idx] = mr[sidx];
mri[idx] = mri[sidx];
}
if (mr[sidx] <= dfs_in[idx])
e->flags |= EDGE_IRREDUCIBLE_LOOP;
} }
continue; continue;
} }
if (dfs_in[sidx] < 0) if (dfs_in[sidx] < 0)
{ {
stack[stack_top++] = sidx; stack[stack_top] = sidx;
estack[stack_top] = e;
stack_top++;
goto next; goto next;
} }
if (dfs_in[sidx] < mr[idx]) if (dfs_in[sidx] < mr[idx])
...@@ -958,12 +980,14 @@ mark_irreducible_loops (loops) ...@@ -958,12 +980,14 @@ mark_irreducible_loops (loops)
mr[idx] = dfs_in[sidx]; mr[idx] = dfs_in[sidx];
mri[idx] = sidx; mri[idx] = sidx;
} }
e->flags |= EDGE_IRREDUCIBLE_LOOP;
} }
/* Return back. */ /* Return back. */
closed[idx] = 1; closed[idx] = 1;
e = estack[stack_top - 1];
stack_top--; stack_top--;
if (stack_top && dfs_in[stack[stack_top - 1]] >= 0) if (e)
{ {
/* Propagate information back. */ /* Propagate information back. */
sidx = stack[stack_top - 1]; sidx = stack[stack_top - 1];
...@@ -972,6 +996,8 @@ mark_irreducible_loops (loops) ...@@ -972,6 +996,8 @@ mark_irreducible_loops (loops)
mr[sidx] = mr[idx]; mr[sidx] = mr[idx];
mri[sidx] = mri[idx]; mri[sidx] = mri[idx];
} }
if (mr[idx] <= dfs_in[sidx])
e->flags |= EDGE_IRREDUCIBLE_LOOP;
} }
/* Mark the block if relevant. */ /* Mark the block if relevant. */
if (idx && idx <= last_basic_block && mr[idx] <= dfs_in[idx]) if (idx && idx <= last_basic_block && mr[idx] <= dfs_in[idx])
...@@ -980,6 +1006,7 @@ next:; ...@@ -980,6 +1006,7 @@ next:;
} }
free (stack); free (stack);
free (estack);
free (dfs_in); free (dfs_in);
free (closed); free (closed);
free (mr); free (mr);
......
...@@ -1594,11 +1594,13 @@ debug_bb (bb) ...@@ -1594,11 +1594,13 @@ debug_bb (bb)
dump_bb (bb, stderr); dump_bb (bb, stderr);
} }
void basic_block
debug_bb_n (n) debug_bb_n (n)
int n; int n;
{ {
dump_bb (BASIC_BLOCK (n), stderr); basic_block bb = BASIC_BLOCK (n);
dump_bb (bb, stderr);
return bb;
} }
/* Like print_rtl, but also print out live information for the start of each /* Like print_rtl, but also print out live information for the start of each
...@@ -1866,7 +1868,7 @@ verify_flow_info () ...@@ -1866,7 +1868,7 @@ verify_flow_info ()
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
n_fallthru++; n_fallthru++;
if ((e->flags & ~(EDGE_DFS_BACK | EDGE_CAN_FALLTHRU)) == 0) if ((e->flags & ~(EDGE_DFS_BACK | EDGE_CAN_FALLTHRU | EDGE_IRREDUCIBLE_LOOP)) == 0)
n_branch++; n_branch++;
if (e->flags & EDGE_ABNORMAL_CALL) if (e->flags & EDGE_ABNORMAL_CALL)
......
...@@ -180,25 +180,6 @@ peel_loops_completely (loops, flags) ...@@ -180,25 +180,6 @@ peel_loops_completely (loops, flags)
fprintf (rtl_dump_file, ";; Considering loop %d for complete peeling\n", fprintf (rtl_dump_file, ";; Considering loop %d for complete peeling\n",
loop->num); loop->num);
/* Do not peel cold areas. */
if (!maybe_hot_bb_p (loop->header))
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not considering loop, cold area\n");
loop = next;
continue;
}
/* Can the loop be manipulated? */
if (!can_duplicate_loop_p (loop))
{
if (rtl_dump_file)
fprintf (rtl_dump_file,
";; Not considering loop, cannot duplicate\n");
loop = next;
continue;
}
loop->ninsns = num_loop_insns (loop); loop->ninsns = num_loop_insns (loop);
decide_peel_once_rolling (loops, loop, flags); decide_peel_once_rolling (loops, loop, flags);
...@@ -348,6 +329,23 @@ decide_peel_completely (loops, loop, flags) ...@@ -348,6 +329,23 @@ decide_peel_completely (loops, loop, flags)
return; return;
} }
/* Do not peel cold areas. */
if (!maybe_hot_bb_p (loop->header))
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not considering loop, cold area\n");
return;
}
/* Can the loop be manipulated? */
if (!can_duplicate_loop_p (loop))
{
if (rtl_dump_file)
fprintf (rtl_dump_file,
";; Not considering loop, cannot duplicate\n");
return;
}
/* npeel = number of iterations to peel. */ /* npeel = number of iterations to peel. */
npeel = PARAM_VALUE (PARAM_MAX_COMPLETELY_PEELED_INSNS) / loop->ninsns; npeel = PARAM_VALUE (PARAM_MAX_COMPLETELY_PEELED_INSNS) / loop->ninsns;
if (npeel > (unsigned) PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES)) if (npeel > (unsigned) PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES))
...@@ -411,45 +409,40 @@ peel_loop_completely (loops, loop) ...@@ -411,45 +409,40 @@ peel_loop_completely (loops, loop)
{ {
sbitmap wont_exit; sbitmap wont_exit;
unsigned HOST_WIDE_INT npeel; unsigned HOST_WIDE_INT npeel;
edge e;
unsigned n_remove_edges, i; unsigned n_remove_edges, i;
edge *remove_edges; edge *remove_edges;
struct loop_desc *desc = &loop->desc; struct loop_desc *desc = &loop->desc;
npeel = desc->niter; npeel = desc->niter;
wont_exit = sbitmap_alloc (npeel + 2); if (npeel)
sbitmap_ones (wont_exit); {
RESET_BIT (wont_exit, 0); wont_exit = sbitmap_alloc (npeel + 1);
RESET_BIT (wont_exit, npeel + 1); sbitmap_ones (wont_exit);
if (desc->may_be_zero) RESET_BIT (wont_exit, 0);
RESET_BIT (wont_exit, 1); if (desc->may_be_zero)
RESET_BIT (wont_exit, 1);
remove_edges = xcalloc (npeel, sizeof (edge));
n_remove_edges = 0;
if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
loops, npeel + 1,
wont_exit, desc->out_edge, remove_edges, &n_remove_edges,
DLTHE_FLAG_UPDATE_FREQ))
abort ();
free (wont_exit); remove_edges = xcalloc (npeel, sizeof (edge));
n_remove_edges = 0;
/* Remove the exit edges. */ if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
for (i = 0; i < n_remove_edges; i++) loops, npeel,
remove_path (loops, remove_edges[i]); wont_exit, desc->out_edge, remove_edges, &n_remove_edges,
free (remove_edges); DLTHE_FLAG_UPDATE_FREQ))
abort ();
/* Now remove the loop. */ free (wont_exit);
for (e = RBI (desc->in_edge->src)->copy->succ;
e && e->dest != RBI (desc->in_edge->dest)->copy;
e = e->succ_next);
if (!e) /* Remove the exit edges. */
abort (); for (i = 0; i < n_remove_edges; i++)
remove_path (loops, remove_edges[i]);
free (remove_edges);
}
remove_path (loops, e); /* Now remove the unreachable part of the last iteration and cancel
the loop. */
remove_path (loops, desc->in_edge);
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Peeled loop completely, %d times\n", (int) npeel); fprintf (rtl_dump_file, ";; Peeled loop completely, %d times\n", (int) npeel);
......
...@@ -335,7 +335,7 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -335,7 +335,7 @@ unswitch_loop (loops, loop, unswitch_on)
struct loop *loop; struct loop *loop;
basic_block unswitch_on; basic_block unswitch_on;
{ {
edge entry, e, latch_edge; edge entry, latch_edge;
basic_block switch_bb, unswitch_on_alt, src; basic_block switch_bb, unswitch_on_alt, src;
struct loop *nloop; struct loop *nloop;
sbitmap zero_bitmap; sbitmap zero_bitmap;
...@@ -366,15 +366,15 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -366,15 +366,15 @@ unswitch_loop (loops, loop, unswitch_on)
/* Make a copy. */ /* Make a copy. */
src = entry->src; src = entry->src;
irred_flag = src->flags & BB_IRREDUCIBLE_LOOP; irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
src->flags &= ~BB_IRREDUCIBLE_LOOP; entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
zero_bitmap = sbitmap_alloc (2); zero_bitmap = sbitmap_alloc (2);
sbitmap_zero (zero_bitmap); sbitmap_zero (zero_bitmap);
if (!duplicate_loop_to_header_edge (loop, entry, loops, 1, if (!duplicate_loop_to_header_edge (loop, entry, loops, 1,
zero_bitmap, NULL, NULL, NULL, 0)) zero_bitmap, NULL, NULL, NULL, 0))
return NULL; return NULL;
free (zero_bitmap); free (zero_bitmap);
src->flags |= irred_flag; entry->flags |= irred_flag;
/* Record the block with condition we unswitch on. */ /* Record the block with condition we unswitch on. */
unswitch_on_alt = RBI (unswitch_on)->copy; unswitch_on_alt = RBI (unswitch_on)->copy;
...@@ -382,8 +382,18 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -382,8 +382,18 @@ unswitch_loop (loops, loop, unswitch_on)
/* Make a copy of the block containing the condition; we will use /* Make a copy of the block containing the condition; we will use
it as switch to decide which loop we want to use. */ it as switch to decide which loop we want to use. */
switch_bb = cfg_layout_duplicate_bb (unswitch_on, NULL); switch_bb = cfg_layout_duplicate_bb (unswitch_on, NULL);
switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP; if (irred_flag)
switch_bb->flags |= irred_flag; {
switch_bb->flags |= BB_IRREDUCIBLE_LOOP;
switch_bb->succ->flags |= EDGE_IRREDUCIBLE_LOOP;
switch_bb->succ->succ_next->flags |= EDGE_IRREDUCIBLE_LOOP;
}
else
{
switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP;
switch_bb->succ->flags &= ~EDGE_IRREDUCIBLE_LOOP;
switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP;
}
add_to_dominance_info (loops->cfg.dom, switch_bb); add_to_dominance_info (loops->cfg.dom, switch_bb);
RBI (unswitch_on)->copy = unswitch_on_alt; RBI (unswitch_on)->copy = unswitch_on_alt;
...@@ -396,10 +406,6 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -396,10 +406,6 @@ unswitch_loop (loops, loop, unswitch_on)
/* Remove branches that are now unreachable in new loops. We rely on the /* Remove branches that are now unreachable in new loops. We rely on the
fact that cfg_layout_duplicate_bb reverses list of edges. */ fact that cfg_layout_duplicate_bb reverses list of edges. */
for (e = unswitch_on->succ->succ_next->dest->pred; e; e = e->pred_next)
if (e->src != unswitch_on &&
!dominated_by_p (loops->cfg.dom, e->src, e->dest))
break;
remove_path (loops, unswitch_on->succ); remove_path (loops, unswitch_on->succ);
remove_path (loops, unswitch_on_alt->succ); remove_path (loops, unswitch_on_alt->succ);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment