Commit 70388d94 by Zdenek Dvorak Committed by Zdenek Dvorak

cfgloop.c (flow_loop_entry_edges_find, [...]): Removed.

	* cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
	flow_loop_pre_header_scan, flow_loop_pre_header_find,
	flow_loop_scan): Removed.
	(flow_loop_dump): Do not dump removed fields.
	(flow_loop_free): Do not free removed fields.
	(flow_loops_find): Flags argument removed.  Do not call flow_loop_scan.
	(loop_exit_edge_p): New function.
	* cfgloop.h (struct loop): Removed fields pre_header, pre_header_edges,
	num_pre_header_edges, entry_edges, num_entries, exit_edges,
	num_exits, exits_doms.
	(LOOP_TREE, LOOP_PRE_HEADER, LOOP_ENTRY_EDGES, LOOP_EXIT_EDGES,
	LOOP_EDGES, LOOP_ALL): Removed.
	(flow_loop_scan): Declaration removed.
	(loop_exit_edge_p, mark_loop_exit_edges): Declare.
	* cfgloopmanip.c (create_loop_notes): Do not pass flags to
	flow_loops_find.
	* ifcvt.c (mark_loop_exit_edges): Moved to cfgloopanal.c.
	(if_convert): Call flow_loops_find and flow_loops_free
	when calling mark_loop_exit_edges.
	* cfgloopanal.c (mark_loop_exit_edges): Moved from
	ifcvt.c.  Removed the flow_loops_find, flow_loops_free and
	free_dominance_info calls.
	* loop-init.c (flow_loops_find): Ditto.
	* passes.c (rest_of_handle_branch_prob): Ditto.
	* lambda-code.c (perfect_nestify): Do not call flow_loops_find.
	* loop-unroll.c (analyze_insns_in_loop): Do not use
	EDGE_LOOP_EXIT.
	* predict.c (predict_loops): Do not call flow_loop_scan.
	Use get_loop_exit_edges.
	(tree_estimate_probability): Do not pass flags to flow_loops_find.
	* tree-if-conv.c (bb_with_exit_edge_p): Take loop as argument.
	Do not use EDGE_LOOP_EXIT.
	(tree_if_convert_cond_expr, if_convertible_modify_expr_p): Pass loop
	to bb_with_exit_edge_p.
	(if_convertible_loop_p): Do not call flow_loop_scan.  Use
	loop->single_exit.  Do not use EDGE_LOOP_EXIT.  Pass loop
	to bb_with_exit_edge_p.
	(combine_blocks): Pass loop to bb_with_exit_edge_p.  Do not use
	EDGE_LOOP_EXIT.
	* tree-loop-linear.c (linear_transform_loops): Do not call
	flow_loop_scan.  Use loop->single_exit.
	* tree-vect-analyze.c (vect_analyze_operations): Use loop->single_exit.
	(vect_analyze_loop_form): Do not call flow_loop_scan.
	* tree-vect-transform.c (vect_update_ivs_after_vectorizer): Use
	loop->single_exit.
	(vect_do_peeling_for_loop_bound): Use loop_preheader_edge and
	loop->single_exit.
	* tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
	slpeel_make_loop_iterate_ntimes, slpeel_can_duplicate_loop_p,
	slpeel_tree_duplicate_loop_to_edge_cfg,
	slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
	Use loop_preheader_edge and loop->single_exit.  Do not call
	flow_loop_scan.

From-SVN: r95738
parent b279b20a
2005-03-01 Zdenek Dvorak <dvorakz@suse.cz>
* cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
flow_loop_pre_header_scan, flow_loop_pre_header_find,
flow_loop_scan): Removed.
(flow_loop_dump): Do not dump removed fields.
(flow_loop_free): Do not free removed fields.
(flow_loops_find): Flags argument removed. Do not call flow_loop_scan.
(loop_exit_edge_p): New function.
* cfgloop.h (struct loop): Removed fields pre_header, pre_header_edges,
num_pre_header_edges, entry_edges, num_entries, exit_edges,
num_exits, exits_doms.
(LOOP_TREE, LOOP_PRE_HEADER, LOOP_ENTRY_EDGES, LOOP_EXIT_EDGES,
LOOP_EDGES, LOOP_ALL): Removed.
(flow_loop_scan): Declaration removed.
(loop_exit_edge_p, mark_loop_exit_edges): Declare.
* cfgloopmanip.c (create_loop_notes): Do not pass flags to
flow_loops_find.
* ifcvt.c (mark_loop_exit_edges): Moved to cfgloopanal.c.
(if_convert): Call flow_loops_find and flow_loops_free
when calling mark_loop_exit_edges.
* cfgloopanal.c (mark_loop_exit_edges): Moved from
ifcvt.c. Removed the flow_loops_find, flow_loops_free and
free_dominance_info calls.
* loop-init.c (flow_loops_find): Ditto.
* passes.c (rest_of_handle_branch_prob): Ditto.
* lambda-code.c (perfect_nestify): Do not call flow_loops_find.
* loop-unroll.c (analyze_insns_in_loop): Do not use
EDGE_LOOP_EXIT.
* predict.c (predict_loops): Do not call flow_loop_scan.
Use get_loop_exit_edges.
(tree_estimate_probability): Do not pass flags to flow_loops_find.
* tree-if-conv.c (bb_with_exit_edge_p): Take loop as argument.
Do not use EDGE_LOOP_EXIT.
(tree_if_convert_cond_expr, if_convertible_modify_expr_p): Pass loop
to bb_with_exit_edge_p.
(if_convertible_loop_p): Do not call flow_loop_scan. Use
loop->single_exit. Do not use EDGE_LOOP_EXIT. Pass loop
to bb_with_exit_edge_p.
(combine_blocks): Pass loop to bb_with_exit_edge_p. Do not use
EDGE_LOOP_EXIT.
* tree-loop-linear.c (linear_transform_loops): Do not call
flow_loop_scan. Use loop->single_exit.
* tree-vect-analyze.c (vect_analyze_operations): Use loop->single_exit.
(vect_analyze_loop_form): Do not call flow_loop_scan.
* tree-vect-transform.c (vect_update_ivs_after_vectorizer): Use
loop->single_exit.
(vect_do_peeling_for_loop_bound): Use loop_preheader_edge and
loop->single_exit.
* tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
slpeel_make_loop_iterate_ntimes, slpeel_can_duplicate_loop_p,
slpeel_tree_duplicate_loop_to_edge_cfg,
slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
Use loop_preheader_edge and loop->single_exit. Do not call
flow_loop_scan.
2005-03-01 Nick Clifton <nickc@redhat.com> 2005-03-01 Nick Clifton <nickc@redhat.com>
* config/arm/arm.c (thumb_find_work_register): Check all of the * config/arm/arm.c (thumb_find_work_register): Check all of the
......
...@@ -41,11 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -41,11 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define LATCH_EDGE(E) (*(int *) (E)->aux) #define LATCH_EDGE(E) (*(int *) (E)->aux)
static void flow_loops_cfg_dump (const struct loops *, FILE *); static void flow_loops_cfg_dump (const struct loops *, FILE *);
static void flow_loop_entry_edges_find (struct loop *);
static void flow_loop_exit_edges_find (struct loop *);
static int flow_loop_nodes_find (basic_block, struct loop *); static int flow_loop_nodes_find (basic_block, struct loop *);
static void flow_loop_pre_header_scan (struct loop *);
static basic_block flow_loop_pre_header_find (basic_block);
static int flow_loop_level_compute (struct loop *); static int flow_loop_level_compute (struct loop *);
static void flow_loops_level_compute (struct loops *); static void flow_loops_level_compute (struct loops *);
static void establish_preds (struct loop *); static void establish_preds (struct loop *);
...@@ -135,27 +131,18 @@ flow_loop_dump (const struct loop *loop, FILE *file, ...@@ -135,27 +131,18 @@ flow_loop_dump (const struct loop *loop, FILE *file,
fprintf (file, ";;\n;; Loop %d:%s\n", loop->num, fprintf (file, ";;\n;; Loop %d:%s\n", loop->num,
loop->invalid ? " invalid" : ""); loop->invalid ? " invalid" : "");
fprintf (file, ";; header %d, latch %d, pre-header %d\n", fprintf (file, ";; header %d, latch %d\n",
loop->header->index, loop->latch->index, loop->header->index, loop->latch->index);
loop->pre_header ? loop->pre_header->index : -1);
fprintf (file, ";; depth %d, level %d, outer %ld\n", fprintf (file, ";; depth %d, level %d, outer %ld\n",
loop->depth, loop->level, loop->depth, loop->level,
(long) (loop->outer ? loop->outer->num : -1)); (long) (loop->outer ? loop->outer->num : -1));
if (loop->pre_header_edges)
flow_edge_list_print (";; pre-header edges", loop->pre_header_edges,
loop->num_pre_header_edges, file);
flow_edge_list_print (";; entry edges", loop->entry_edges,
loop->num_entries, file);
fprintf (file, ";; nodes:"); fprintf (file, ";; nodes:");
bbs = get_loop_body (loop); bbs = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
fprintf (file, " %d", bbs[i]->index); fprintf (file, " %d", bbs[i]->index);
free (bbs); free (bbs);
fprintf (file, "\n"); fprintf (file, "\n");
flow_edge_list_print (";; exit edges", loop->exit_edges,
loop->num_exits, file);
if (loop_dump_aux) if (loop_dump_aux)
loop_dump_aux (loop, file, verbose); loop_dump_aux (loop, file, verbose);
...@@ -194,12 +181,6 @@ flow_loops_dump (const struct loops *loops, FILE *file, void (*loop_dump_aux) (c ...@@ -194,12 +181,6 @@ flow_loops_dump (const struct loops *loops, FILE *file, void (*loop_dump_aux) (c
void void
flow_loop_free (struct loop *loop) flow_loop_free (struct loop *loop)
{ {
if (loop->pre_header_edges)
free (loop->pre_header_edges);
if (loop->entry_edges)
free (loop->entry_edges);
if (loop->exit_edges)
free (loop->exit_edges);
if (loop->pred) if (loop->pred)
free (loop->pred); free (loop->pred);
free (loop); free (loop);
...@@ -238,95 +219,6 @@ flow_loops_free (struct loops *loops) ...@@ -238,95 +219,6 @@ flow_loops_free (struct loops *loops)
} }
} }
/* Find the entry edges into the LOOP. */
static void
flow_loop_entry_edges_find (struct loop *loop)
{
edge e;
edge_iterator ei;
int num_entries;
num_entries = 0;
FOR_EACH_EDGE (e, ei, loop->header->preds)
{
if (flow_loop_outside_edge_p (loop, e))
num_entries++;
}
gcc_assert (num_entries);
loop->entry_edges = xmalloc (num_entries * sizeof (edge *));
num_entries = 0;
FOR_EACH_EDGE (e, ei, loop->header->preds)
{
if (flow_loop_outside_edge_p (loop, e))
loop->entry_edges[num_entries++] = e;
}
loop->num_entries = num_entries;
}
/* Find the exit edges from the LOOP. */
static void
flow_loop_exit_edges_find (struct loop *loop)
{
edge e;
basic_block node, *bbs;
unsigned num_exits, i;
loop->exit_edges = NULL;
loop->num_exits = 0;
/* Check all nodes within the loop to see if there are any
successors not in the loop. Note that a node may have multiple
exiting edges. */
num_exits = 0;
bbs = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++)
{
edge_iterator ei;
node = bbs[i];
FOR_EACH_EDGE (e, ei, node->succs)
{
basic_block dest = e->dest;
if (!flow_bb_inside_loop_p (loop, dest))
num_exits++;
}
}
if (! num_exits)
{
free (bbs);
return;
}
loop->exit_edges = xmalloc (num_exits * sizeof (edge *));
/* Store all exiting edges into an array. */
num_exits = 0;
for (i = 0; i < loop->num_nodes; i++)
{
edge_iterator ei;
node = bbs[i];
FOR_EACH_EDGE (e, ei, node->succs)
{
basic_block dest = e->dest;
if (!flow_bb_inside_loop_p (loop, dest))
{
e->flags |= EDGE_LOOP_EXIT;
loop->exit_edges[num_exits++] = e;
}
}
}
free (bbs);
loop->num_exits = num_exits;
}
/* Find the nodes contained within the LOOP with header HEADER. /* Find the nodes contained within the LOOP with header HEADER.
Return the number of nodes within the loop. */ Return the number of nodes within the loop. */
...@@ -434,77 +326,6 @@ mark_single_exit_loops (struct loops *loops) ...@@ -434,77 +326,6 @@ mark_single_exit_loops (struct loops *loops)
loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS; loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS;
} }
/* Find the root node of the loop pre-header extended basic block and
the edges along the trace from the root node to the loop header. */
static void
flow_loop_pre_header_scan (struct loop *loop)
{
int num;
basic_block ebb;
edge e;
loop->num_pre_header_edges = 0;
if (loop->num_entries != 1)
return;
ebb = loop->entry_edges[0]->src;
if (ebb == ENTRY_BLOCK_PTR)
return;
/* Count number of edges along trace from loop header to
root of pre-header extended basic block. Usually this is
only one or two edges. */
for (num = 1;
EDGE_PRED (ebb, 0)->src != ENTRY_BLOCK_PTR && EDGE_COUNT (ebb->preds) == 1;
num++)
ebb = EDGE_PRED (ebb, 0)->src;
loop->pre_header_edges = xmalloc (num * sizeof (edge));
loop->num_pre_header_edges = num;
/* Store edges in order that they are followed. The source of the first edge
is the root node of the pre-header extended basic block and the
destination of the last last edge is the loop header. */
for (e = loop->entry_edges[0]; num; e = EDGE_PRED (e->src, 0))
loop->pre_header_edges[--num] = e;
}
/* Return the block for the pre-header of the loop with header
HEADER. Return NULL if there is no pre-header. */
static basic_block
flow_loop_pre_header_find (basic_block header)
{
basic_block pre_header;
edge e;
edge_iterator ei;
/* If block p is a predecessor of the header and is the only block
that the header does not dominate, then it is the pre-header. */
pre_header = NULL;
FOR_EACH_EDGE (e, ei, header->preds)
{
basic_block node = e->src;
if (node != ENTRY_BLOCK_PTR
&& ! dominated_by_p (CDI_DOMINATORS, node, header))
{
if (pre_header == NULL)
pre_header = node;
else
{
/* There are multiple edges into the header from outside
the loop so there is no pre-header block. */
pre_header = NULL;
break;
}
}
}
return pre_header;
}
static void static void
establish_preds (struct loop *loop) establish_preds (struct loop *loop)
{ {
...@@ -602,39 +423,6 @@ flow_loops_level_compute (struct loops *loops) ...@@ -602,39 +423,6 @@ flow_loops_level_compute (struct loops *loops)
flow_loop_level_compute (loops->tree_root); flow_loop_level_compute (loops->tree_root);
} }
/* Scan a single natural loop specified by LOOP collecting information
about it specified by FLAGS. */
int
flow_loop_scan (struct loop *loop, int flags)
{
if (flags & LOOP_ENTRY_EDGES)
{
/* Find edges which enter the loop header.
Note that the entry edges should only
enter the header of a natural loop. */
flow_loop_entry_edges_find (loop);
}
if (flags & LOOP_EXIT_EDGES)
{
/* Find edges which exit the loop. */
flow_loop_exit_edges_find (loop);
}
if (flags & LOOP_PRE_HEADER)
{
/* Look to see if the loop has a pre-header node. */
loop->pre_header = flow_loop_pre_header_find (loop->header);
/* Find the blocks within the extended basic block of
the loop pre-header. */
flow_loop_pre_header_scan (loop);
}
return 1;
}
/* A callback to update latch and header info for basic block JUMP created /* A callback to update latch and header info for basic block JUMP created
by redirecting an edge. */ by redirecting an edge. */
...@@ -800,14 +588,12 @@ initialize_loops_parallel_p (struct loops *loops) ...@@ -800,14 +588,12 @@ initialize_loops_parallel_p (struct loops *loops)
} }
/* Find all the natural loops in the function and save in LOOPS structure and /* Find all the natural loops in the function and save in LOOPS structure and
recalculate loop_depth information in basic block structures. FLAGS recalculate loop_depth information in basic block structures.
controls which loop information is collected. Return the number of natural Return the number of natural loops found. */
loops found. */
int int
flow_loops_find (struct loops *loops, int flags) flow_loops_find (struct loops *loops)
{ {
int i;
int b; int b;
int num_loops; int num_loops;
edge e; edge e;
...@@ -817,11 +603,6 @@ flow_loops_find (struct loops *loops, int flags) ...@@ -817,11 +603,6 @@ flow_loops_find (struct loops *loops, int flags)
basic_block header; basic_block header;
basic_block bb; basic_block bb;
/* This function cannot be repeatedly called with different
flags to build up the loop information. The loop tree
must always be built if this function is called. */
gcc_assert (flags & LOOP_TREE);
memset (loops, 0, sizeof *loops); memset (loops, 0, sizeof *loops);
/* We are going to recount the maximum loop depth, /* We are going to recount the maximum loop depth,
...@@ -963,10 +744,6 @@ flow_loops_find (struct loops *loops, int flags) ...@@ -963,10 +744,6 @@ flow_loops_find (struct loops *loops, int flags)
loop. */ loop. */
flow_loops_level_compute (loops); flow_loops_level_compute (loops);
/* Scan the loops. */
for (i = 1; i < num_loops; i++)
flow_loop_scan (loops->parray[i], flags);
loops->num = num_loops; loops->num = num_loops;
initialize_loops_parallel_p (loops); initialize_loops_parallel_p (loops);
} }
...@@ -1523,3 +1300,12 @@ loop_preheader_edge (const struct loop *loop) ...@@ -1523,3 +1300,12 @@ loop_preheader_edge (const struct loop *loop)
return e; return e;
} }
/* Returns true if E is an exit of LOOP. */
bool
loop_exit_edge_p (const struct loop *loop, edge e)
{
return (flow_bb_inside_loop_p (loop, e->src)
&& !flow_bb_inside_loop_p (loop, e->dest));
}
...@@ -69,9 +69,6 @@ struct loop ...@@ -69,9 +69,6 @@ struct loop
/* Basic block of loop latch. */ /* Basic block of loop latch. */
basic_block latch; basic_block latch;
/* Basic block of loop preheader or NULL if it does not exist. */
basic_block pre_header;
/* For loop unrolling/peeling decision. */ /* For loop unrolling/peeling decision. */
struct lpt_decision lpt_decision; struct lpt_decision lpt_decision;
...@@ -81,14 +78,6 @@ struct loop ...@@ -81,14 +78,6 @@ struct loop
/* Average number of executed insns per iteration. */ /* Average number of executed insns per iteration. */
unsigned av_ninsns; unsigned av_ninsns;
/* Array of edges along the preheader extended basic block trace.
The source of the first edge is the root node of preheader
extended basic block, if it exists. */
edge *pre_header_edges;
/* Number of edges along the pre_header extended basic block trace. */
int num_pre_header_edges;
/* The first block in the loop. This is not necessarily the same as /* The first block in the loop. This is not necessarily the same as
the loop header. */ the loop header. */
basic_block first; basic_block first;
...@@ -100,21 +89,6 @@ struct loop ...@@ -100,21 +89,6 @@ struct loop
/* Number of blocks contained within the loop. */ /* Number of blocks contained within the loop. */
unsigned num_nodes; unsigned num_nodes;
/* Array of edges that enter the loop. */
edge *entry_edges;
/* Number of edges that enter the loop. */
int num_entries;
/* Array of edges that exit the loop. */
edge *exit_edges;
/* Number of edges that exit the loop. */
int num_exits;
/* Bitmap of blocks that dominate all exits of the loop. */
sbitmap exits_doms;
/* The loop nesting depth. */ /* The loop nesting depth. */
int depth; int depth;
...@@ -254,23 +228,13 @@ struct loops ...@@ -254,23 +228,13 @@ struct loops
extern struct loops *current_loops; extern struct loops *current_loops;
/* Flags for loop discovery. */
#define LOOP_TREE 1 /* Build loop hierarchy tree. */
#define LOOP_PRE_HEADER 2 /* Analyze loop preheader. */
#define LOOP_ENTRY_EDGES 4 /* Find entry edges. */
#define LOOP_EXIT_EDGES 8 /* Find exit edges. */
#define LOOP_EDGES (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES)
#define LOOP_ALL 15 /* All of the above */
/* Loop recognition. */ /* Loop recognition. */
extern int flow_loops_find (struct loops *, int flags); extern int flow_loops_find (struct loops *);
extern void flow_loops_free (struct loops *); extern void flow_loops_free (struct loops *);
extern void flow_loops_dump (const struct loops *, FILE *, extern void flow_loops_dump (const struct loops *, FILE *,
void (*)(const struct loop *, FILE *, int), int); void (*)(const struct loop *, FILE *, int), int);
extern void flow_loop_dump (const struct loop *, FILE *, extern void flow_loop_dump (const struct loop *, FILE *,
void (*)(const struct loop *, FILE *, int), int); void (*)(const struct loop *, FILE *, int), int);
extern int flow_loop_scan (struct loop *, int);
extern void flow_loop_free (struct loop *); extern void flow_loop_free (struct loop *);
void mark_irreducible_loops (struct loops *); void mark_irreducible_loops (struct loops *);
void mark_single_exit_loops (struct loops *); void mark_single_exit_loops (struct loops *);
...@@ -288,6 +252,8 @@ extern unsigned tree_num_loop_insns (struct loop *); ...@@ -288,6 +252,8 @@ extern unsigned tree_num_loop_insns (struct loop *);
extern int num_loop_insns (struct loop *); extern int num_loop_insns (struct loop *);
extern int average_num_loop_insns (struct loop *); extern int average_num_loop_insns (struct loop *);
extern unsigned get_loop_level (const struct loop *); extern unsigned get_loop_level (const struct loop *);
extern bool loop_exit_edge_p (const struct loop *, edge);
extern void mark_loop_exit_edges (struct loops *);
/* Loops & cfg manipulation. */ /* Loops & cfg manipulation. */
extern basic_block *get_loop_body (const struct loop *); extern basic_block *get_loop_body (const struct loop *);
......
...@@ -565,3 +565,32 @@ global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses) ...@@ -565,3 +565,32 @@ global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses)
return cost; return cost;
} }
/* Sets EDGE_LOOP_EXIT flag for all exits of LOOPS. */
void
mark_loop_exit_edges (struct loops *loops)
{
basic_block bb;
edge e;
if (loops->num <= 1)
return;
FOR_EACH_BB (bb)
{
edge_iterator ei;
/* Do not mark exits from the fake outermost loop. */
if (!bb->loop_father->outer)
continue;
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (loop_exit_edge_p (bb->loop_father, e))
e->flags |= EDGE_LOOP_EXIT;
else
e->flags &= ~EDGE_LOOP_EXIT;
}
}
}
...@@ -1296,7 +1296,7 @@ create_loop_notes (void) ...@@ -1296,7 +1296,7 @@ create_loop_notes (void)
NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG); NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
#endif #endif
flow_loops_find (&loops, LOOP_TREE); flow_loops_find (&loops);
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
if (loops.num > 1) if (loops.num > 1)
{ {
......
...@@ -110,38 +110,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block, ...@@ -110,38 +110,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block,
basic_block, int); basic_block, int);
static void noce_emit_move_insn (rtx, rtx); static void noce_emit_move_insn (rtx, rtx);
static rtx block_has_only_trap (basic_block); static rtx block_has_only_trap (basic_block);
static void mark_loop_exit_edges (void);
/* Sets EDGE_LOOP_EXIT flag for all loop exits. */
static void
mark_loop_exit_edges (void)
{
struct loops loops;
basic_block bb;
edge e;
flow_loops_find (&loops, LOOP_TREE);
free_dominance_info (CDI_DOMINATORS);
if (loops.num > 1)
{
FOR_EACH_BB (bb)
{
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (find_common_loop (bb->loop_father, e->dest->loop_father)
!= bb->loop_father)
e->flags |= EDGE_LOOP_EXIT;
else
e->flags &= ~EDGE_LOOP_EXIT;
}
}
}
flow_loops_free (&loops);
}
/* Count the number of non-jump active insns in BB. */ /* Count the number of non-jump active insns in BB. */
static int static int
...@@ -3356,7 +3325,14 @@ if_convert (int x_life_data_ok) ...@@ -3356,7 +3325,14 @@ if_convert (int x_life_data_ok)
if ((! targetm.cannot_modify_jumps_p ()) if ((! targetm.cannot_modify_jumps_p ())
&& (!flag_reorder_blocks_and_partition || !no_new_pseudos && (!flag_reorder_blocks_and_partition || !no_new_pseudos
|| !targetm.have_named_sections)) || !targetm.have_named_sections))
mark_loop_exit_edges (); {
struct loops loops;
flow_loops_find (&loops);
mark_loop_exit_edges (&loops);
flow_loops_free (&loops);
free_dominance_info (CDI_DOMINATORS);
}
/* Compute postdominators if we think we'll use them. */ /* Compute postdominators if we think we'll use them. */
if (HAVE_conditional_execution || life_data_ok) if (HAVE_conditional_execution || life_data_ok)
......
...@@ -2430,7 +2430,6 @@ perfect_nestify (struct loops *loops, ...@@ -2430,7 +2430,6 @@ perfect_nestify (struct loops *loops,
} }
} }
free (bbs); free (bbs);
flow_loops_find (loops, LOOP_ALL);
return perfect_nest_p (loop); return perfect_nest_p (loop);
} }
......
...@@ -56,7 +56,7 @@ loop_optimizer_init (FILE *dumpfile) ...@@ -56,7 +56,7 @@ loop_optimizer_init (FILE *dumpfile)
/* Find the loops. */ /* Find the loops. */
if (flow_loops_find (loops, LOOP_TREE) <= 1) if (flow_loops_find (loops) <= 1)
{ {
/* No loops. */ /* No loops. */
flow_loops_free (loops); flow_loops_free (loops);
......
...@@ -1669,8 +1669,7 @@ analyze_insns_in_loop (struct loop *loop) ...@@ -1669,8 +1669,7 @@ analyze_insns_in_loop (struct loop *loop)
opt_info->loop_preheader = loop_preheader_edge (loop)->src; opt_info->loop_preheader = loop_preheader_edge (loop)->src;
if (n_edges == 1 if (n_edges == 1
&& !(edges[0]->flags & EDGE_COMPLEX) && !(edges[0]->flags & EDGE_COMPLEX))
&& (edges[0]->flags & EDGE_LOOP_EXIT))
{ {
opt_info->loop_exit = loop_split_edge_with (edges[0], NULL_RTX); opt_info->loop_exit = loop_split_edge_with (edges[0], NULL_RTX);
can_apply = true; can_apply = true;
......
...@@ -781,7 +781,7 @@ rest_of_handle_branch_prob (void) ...@@ -781,7 +781,7 @@ rest_of_handle_branch_prob (void)
/* Discover and record the loop depth at the head of each basic /* Discover and record the loop depth at the head of each basic
block. The loop infrastructure does the real job for us. */ block. The loop infrastructure does the real job for us. */
flow_loops_find (&loops, LOOP_TREE); flow_loops_find (&loops);
if (dump_file) if (dump_file)
flow_loops_dump (&loops, dump_file, NULL, 0); flow_loops_dump (&loops, dump_file, NULL, 0);
......
...@@ -583,13 +583,13 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) ...@@ -583,13 +583,13 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
{ {
basic_block bb, *bbs; basic_block bb, *bbs;
unsigned j; unsigned j;
int exits; unsigned n_exits;
struct loop *loop = loops_info->parray[i]; struct loop *loop = loops_info->parray[i];
struct niter_desc desc; struct niter_desc desc;
unsigned HOST_WIDE_INT niter; unsigned HOST_WIDE_INT niter;
edge *exits;
flow_loop_scan (loop, LOOP_EXIT_EDGES); exits = get_loop_exit_edges (loop, &n_exits);
exits = loop->num_exits;
if (rtlsimpleloops) if (rtlsimpleloops)
{ {
...@@ -615,11 +615,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) ...@@ -615,11 +615,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
} }
else else
{ {
edge *exits;
unsigned j, n_exits;
struct tree_niter_desc niter_desc; struct tree_niter_desc niter_desc;
exits = get_loop_exit_edges (loop, &n_exits);
for (j = 0; j < n_exits; j++) for (j = 0; j < n_exits; j++)
{ {
tree niter = NULL; tree niter = NULL;
...@@ -647,8 +644,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) ...@@ -647,8 +644,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
} }
} }
free (exits);
} }
free (exits);
bbs = get_loop_body (loop); bbs = get_loop_body (loop);
...@@ -690,7 +687,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) ...@@ -690,7 +687,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
(e, PRED_LOOP_EXIT, (e, PRED_LOOP_EXIT,
(REG_BR_PROB_BASE (REG_BR_PROB_BASE
- predictor_info [(int) PRED_LOOP_EXIT].hitrate) - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
/ exits); / n_exits);
} }
/* Free basic blocks from get_loop_body. */ /* Free basic blocks from get_loop_body. */
...@@ -1293,7 +1290,7 @@ tree_estimate_probability (void) ...@@ -1293,7 +1290,7 @@ tree_estimate_probability (void)
basic_block bb; basic_block bb;
struct loops loops_info; struct loops loops_info;
flow_loops_find (&loops_info, LOOP_TREE); flow_loops_find (&loops_info);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
flow_loops_dump (&loops_info, dump_file, NULL, 0); flow_loops_dump (&loops_info, dump_file, NULL, 0);
......
...@@ -126,7 +126,7 @@ static void combine_blocks (struct loop *); ...@@ -126,7 +126,7 @@ static void combine_blocks (struct loop *);
static tree ifc_temp_var (tree, tree); static tree ifc_temp_var (tree, tree);
static bool pred_blocks_visited_p (basic_block, bitmap *); static bool pred_blocks_visited_p (basic_block, bitmap *);
static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop); static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop);
static bool bb_with_exit_edge_p (basic_block); static bool bb_with_exit_edge_p (struct loop *, basic_block);
/* List of basic blocks in if-conversion-suitable order. */ /* List of basic blocks in if-conversion-suitable order. */
static basic_block *ifc_bbs; static basic_block *ifc_bbs;
...@@ -312,7 +312,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond, ...@@ -312,7 +312,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
/* Now this conditional statement is redundant. Remove it. /* Now this conditional statement is redundant. Remove it.
But, do not remove exit condition! Update exit condition But, do not remove exit condition! Update exit condition
using new condition. */ using new condition. */
if (!bb_with_exit_edge_p (bb_for_stmt (stmt))) if (!bb_with_exit_edge_p (loop, bb_for_stmt (stmt)))
{ {
bsi_remove (bsi); bsi_remove (bsi);
cond = NULL_TREE; cond = NULL_TREE;
...@@ -405,7 +405,7 @@ if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr) ...@@ -405,7 +405,7 @@ if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr)
if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME
&& bb != loop->header && bb != loop->header
&& !bb_with_exit_edge_p (bb)) && !bb_with_exit_edge_p (loop, bb))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -534,8 +534,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) ...@@ -534,8 +534,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
return false; return false;
} }
flow_loop_scan (loop, LOOP_ALL);
/* If only one block, no need for if-conversion. */ /* If only one block, no need for if-conversion. */
if (loop->num_nodes <= 2) if (loop->num_nodes <= 2)
{ {
...@@ -545,7 +543,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) ...@@ -545,7 +543,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
} }
/* More than one loop exit is too much to handle. */ /* More than one loop exit is too much to handle. */
if (loop->num_exits > 1) if (!loop->single_exit)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "multiple exits\n"); fprintf (dump_file, "multiple exits\n");
...@@ -557,8 +555,10 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) ...@@ -557,8 +555,10 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
/* If one of the loop header's edge is exit edge then do not apply /* If one of the loop header's edge is exit edge then do not apply
if-conversion. */ if-conversion. */
FOR_EACH_EDGE (e, ei, loop->header->succs) FOR_EACH_EDGE (e, ei, loop->header->succs)
if ( e->flags & EDGE_LOOP_EXIT) {
return false; if (loop_exit_edge_p (loop, e))
return false;
}
compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL); compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL);
...@@ -593,7 +593,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) ...@@ -593,7 +593,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
if (!if_convertible_phi_p (loop, bb, phi)) if (!if_convertible_phi_p (loop, bb, phi))
return false; return false;
if (bb_with_exit_edge_p (bb)) if (bb_with_exit_edge_p (loop, bb))
exit_bb_seen = true; exit_bb_seen = true;
} }
...@@ -874,7 +874,7 @@ combine_blocks (struct loop *loop) ...@@ -874,7 +874,7 @@ combine_blocks (struct loop *loop)
bb = ifc_bbs[i]; bb = ifc_bbs[i];
if (!exit_bb && bb_with_exit_edge_p (bb)) if (!exit_bb && bb_with_exit_edge_p (loop, bb))
exit_bb = bb; exit_bb = bb;
if (bb == exit_bb) if (bb == exit_bb)
...@@ -890,11 +890,13 @@ combine_blocks (struct loop *loop) ...@@ -890,11 +890,13 @@ combine_blocks (struct loop *loop)
{ {
/* Redirect non-exit edge to loop->latch. */ /* Redirect non-exit edge to loop->latch. */
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
if (!(e->flags & EDGE_LOOP_EXIT)) {
{ if (!loop_exit_edge_p (loop, e))
redirect_edge_and_branch (e, loop->latch); {
set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb); redirect_edge_and_branch (e, loop->latch);
} set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
}
}
} }
continue; continue;
} }
...@@ -1056,17 +1058,17 @@ get_loop_body_in_if_conv_order (const struct loop *loop) ...@@ -1056,17 +1058,17 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
return blocks; return blocks;
} }
/* Return true if one of the basic block BB edge is loop exit. */ /* Return true if one of the basic block BB edge is exit of LOOP. */
static bool static bool
bb_with_exit_edge_p (basic_block bb) bb_with_exit_edge_p (struct loop *loop, basic_block bb)
{ {
edge e; edge e;
edge_iterator ei; edge_iterator ei;
bool exit_edge_found = false; bool exit_edge_found = false;
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_LOOP_EXIT) if (loop_exit_edge_p (loop, e))
{ {
exit_edge_found = true; exit_edge_found = true;
break; break;
......
...@@ -277,9 +277,8 @@ linear_transform_loops (struct loops *loops) ...@@ -277,9 +277,8 @@ linear_transform_loops (struct loops *loops)
depth = 1; depth = 1;
for (temp = loop_nest->inner; temp; temp = temp->inner) for (temp = loop_nest->inner; temp; temp = temp->inner)
{ {
flow_loop_scan (temp, LOOP_ALL);
/* If we have a sibling loop or multiple exit edges, jump ship. */ /* If we have a sibling loop or multiple exit edges, jump ship. */
if (temp->next || temp->num_exits != 1) if (temp->next || !temp->single_exit)
{ {
problem = true; problem = true;
break; break;
......
...@@ -462,7 +462,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo) ...@@ -462,7 +462,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
"not vectorized: can't create epilog loop 1."); "not vectorized: can't create epilog loop 1.");
return false; return false;
} }
if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0])) if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
{ {
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
LOOP_LOC (loop_vinfo))) LOOP_LOC (loop_vinfo)))
...@@ -2265,7 +2265,6 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2265,7 +2265,6 @@ vect_analyze_loop_form (struct loop *loop)
loop_vec_info loop_vinfo; loop_vec_info loop_vinfo;
tree loop_cond; tree loop_cond;
tree number_of_iterations = NULL; tree number_of_iterations = NULL;
bool rescan = false;
LOC loop_loc; LOC loop_loc;
loop_loc = find_loop_location (loop); loop_loc = find_loop_location (loop);
...@@ -2282,8 +2281,7 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2282,8 +2281,7 @@ vect_analyze_loop_form (struct loop *loop)
if (!loop->single_exit if (!loop->single_exit
|| loop->num_nodes != 2 || loop->num_nodes != 2
|| EDGE_COUNT (loop->header->preds) != 2 || EDGE_COUNT (loop->header->preds) != 2)
|| loop->num_entries != 1)
{ {
if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc)) if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
{ {
...@@ -2293,8 +2291,6 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2293,8 +2291,6 @@ vect_analyze_loop_form (struct loop *loop)
fprintf (vect_dump, "not vectorized: too many BBs in loop."); fprintf (vect_dump, "not vectorized: too many BBs in loop.");
else if (EDGE_COUNT (loop->header->preds) != 2) else if (EDGE_COUNT (loop->header->preds) != 2)
fprintf (vect_dump, "not vectorized: too many incoming edges."); fprintf (vect_dump, "not vectorized: too many incoming edges.");
else if (loop->num_entries != 1)
fprintf (vect_dump, "not vectorized: too many entries.");
} }
return NULL; return NULL;
...@@ -2311,16 +2307,6 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2311,16 +2307,6 @@ vect_analyze_loop_form (struct loop *loop)
return NULL; return NULL;
} }
/* Make sure we have a preheader basic block. */
if (!loop->pre_header || EDGE_COUNT (loop->pre_header->succs) != 1)
{
edge e = loop_preheader_edge (loop);
loop_split_edge_with (e, NULL);
if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
fprintf (vect_dump, "split preheader edge.");
rescan = true;
}
/* Make sure there exists a single-predecessor exit bb: */ /* Make sure there exists a single-predecessor exit bb: */
if (EDGE_COUNT (loop->single_exit->dest->preds) != 1) if (EDGE_COUNT (loop->single_exit->dest->preds) != 1)
{ {
...@@ -2330,7 +2316,6 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2330,7 +2316,6 @@ vect_analyze_loop_form (struct loop *loop)
loop_split_edge_with (e, NULL); loop_split_edge_with (e, NULL);
if (vect_print_dump_info (REPORT_DETAILS, loop_loc)) if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
fprintf (vect_dump, "split exit edge."); fprintf (vect_dump, "split exit edge.");
rescan = true;
} }
else else
{ {
...@@ -2339,13 +2324,6 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -2339,13 +2324,6 @@ vect_analyze_loop_form (struct loop *loop)
return NULL; return NULL;
} }
} }
if (rescan)
{
flow_loop_scan (loop, LOOP_ALL);
/* Flow loop scan does not update loop->single_exit field. */
loop->single_exit = loop->exit_edges[0];
}
if (empty_block_p (loop->header)) if (empty_block_p (loop->header))
{ {
......
...@@ -1315,7 +1315,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters, ...@@ -1315,7 +1315,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
edge update_e) edge update_e)
{ {
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block exit_bb = loop->exit_edges[0]->dest; basic_block exit_bb = loop->single_exit->dest;
tree phi, phi1; tree phi, phi1;
basic_block update_bb = update_e->dest; basic_block update_bb = update_e->dest;
...@@ -1398,6 +1398,7 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, ...@@ -1398,6 +1398,7 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
struct loop *new_loop; struct loop *new_loop;
edge update_e; edge update_e;
basic_block preheader;
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
int loop_num; int loop_num;
#endif #endif
...@@ -1413,14 +1414,10 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, ...@@ -1413,14 +1414,10 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
vect_generate_tmps_on_preheader (loop_vinfo, &ni_name, vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
&ratio_mult_vf_name, ratio); &ratio_mult_vf_name, ratio);
/* Update loop info. */
loop->pre_header = loop_preheader_edge (loop)->src;
loop->pre_header_edges[0] = loop_preheader_edge (loop);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
loop_num = loop->num; loop_num = loop->num;
#endif #endif
new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->exit_edges[0], new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
ratio_mult_vf_name, ni_name, false); ratio_mult_vf_name, ni_name, false);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
gcc_assert (new_loop); gcc_assert (new_loop);
...@@ -1434,10 +1431,11 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, ...@@ -1434,10 +1431,11 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
is a bb after NEW_LOOP, where these IVs are not used. Find the edge that is a bb after NEW_LOOP, where these IVs are not used. Find the edge that
is on the path where the LOOP IVs are used and need to be updated. */ is on the path where the LOOP IVs are used and need to be updated. */
if (EDGE_PRED (new_loop->pre_header, 0)->src == loop->exit_edges[0]->dest) preheader = loop_preheader_edge (new_loop)->src;
update_e = EDGE_PRED (new_loop->pre_header, 0); if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
update_e = EDGE_PRED (preheader, 0);
else else
update_e = EDGE_PRED (new_loop->pre_header, 1); update_e = EDGE_PRED (preheader, 1);
/* Update IVs of original loop as if they were advanced /* Update IVs of original loop as if they were advanced
by ratio_mult_vf_name steps. */ by ratio_mult_vf_name steps. */
......
...@@ -373,7 +373,7 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop, ...@@ -373,7 +373,7 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop,
tree def; tree def;
edge orig_loop_latch = loop_latch_edge (orig_loop); edge orig_loop_latch = loop_latch_edge (orig_loop);
edge orig_entry_e = loop_preheader_edge (orig_loop); edge orig_entry_e = loop_preheader_edge (orig_loop);
edge new_loop_exit_e = new_loop->exit_edges[0]; edge new_loop_exit_e = new_loop->single_exit;
edge new_loop_entry_e = loop_preheader_edge (new_loop); edge new_loop_entry_e = loop_preheader_edge (new_loop);
edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e); edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e);
...@@ -518,8 +518,9 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge, ...@@ -518,8 +518,9 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge,
if (entry_phis) if (entry_phis)
{ {
loop_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, loop_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi,
EDGE_SUCC (loop->latch, 0)); loop_latch_edge (loop));
guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, loop->entry_edges[0]); guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi,
loop_preheader_edge (loop));
} }
else /* exit phis */ else /* exit phis */
{ {
...@@ -544,7 +545,7 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge, ...@@ -544,7 +545,7 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge,
loop_arg = orig_def; loop_arg = orig_def;
} }
} }
add_phi_arg (new_phi, loop_arg, loop->exit_edges[0]); add_phi_arg (new_phi, loop_arg, loop->single_exit);
add_phi_arg (new_phi, guard_arg, guard_edge); add_phi_arg (new_phi, guard_arg, guard_edge);
/* 3. Update phi in successor block. */ /* 3. Update phi in successor block. */
...@@ -567,7 +568,7 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters) ...@@ -567,7 +568,7 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
{ {
tree indx_before_incr, indx_after_incr, cond_stmt, cond; tree indx_before_incr, indx_after_incr, cond_stmt, cond;
tree orig_cond; tree orig_cond;
edge exit_edge = loop->exit_edges[0]; edge exit_edge = loop->single_exit;
block_stmt_iterator loop_cond_bsi; block_stmt_iterator loop_cond_bsi;
block_stmt_iterator incr_bsi; block_stmt_iterator incr_bsi;
bool insert_after; bool insert_after;
...@@ -636,7 +637,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, ...@@ -636,7 +637,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
basic_block exit_dest; basic_block exit_dest;
tree phi, phi_arg; tree phi, phi_arg;
at_exit = (e == loop->exit_edges[0]); at_exit = (e == loop->single_exit);
if (!at_exit && e != loop_preheader_edge (loop)) if (!at_exit && e != loop_preheader_edge (loop))
return NULL; return NULL;
...@@ -657,20 +658,21 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, ...@@ -657,20 +658,21 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
return NULL; return NULL;
} }
exit_dest = loop->exit_edges[0]->dest; exit_dest = loop->single_exit->dest;
was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS, was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS,
exit_dest) == loop->header ? exit_dest) == loop->header ?
true : false); true : false);
new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes); new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes);
copy_bbs (bbs, loop->num_nodes, new_bbs, NULL, 0, NULL, NULL); copy_bbs (bbs, loop->num_nodes, new_bbs,
&loop->single_exit, 1, &new_loop->single_exit, NULL);
/* Duplicating phi args at exit bbs as coming /* Duplicating phi args at exit bbs as coming
also from exit of duplicated loop. */ also from exit of duplicated loop. */
for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi)) for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi))
{ {
phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->exit_edges[0]); phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->single_exit);
if (phi_arg) if (phi_arg)
{ {
edge new_loop_exit_edge; edge new_loop_exit_edge;
...@@ -720,8 +722,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, ...@@ -720,8 +722,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
set_immediate_dominator (CDI_DOMINATORS, new_loop->header, preheader); set_immediate_dominator (CDI_DOMINATORS, new_loop->header, preheader);
} }
flow_loop_scan (new_loop, LOOP_ALL);
flow_loop_scan (loop, LOOP_ALL);
free (new_bbs); free (new_bbs);
free (bbs); free (bbs);
...@@ -772,7 +772,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb, ...@@ -772,7 +772,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb,
bool bool
slpeel_can_duplicate_loop_p (struct loop *loop, edge e) slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
{ {
edge exit_e = loop->exit_edges [0]; edge exit_e = loop->single_exit;
edge entry_e = loop_preheader_edge (loop); edge entry_e = loop_preheader_edge (loop);
tree orig_cond = get_loop_exit_condition (loop); tree orig_cond = get_loop_exit_condition (loop);
block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src); block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
...@@ -786,8 +786,7 @@ slpeel_can_duplicate_loop_p (struct loop *loop, edge e) ...@@ -786,8 +786,7 @@ slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
|| !loop->outer || !loop->outer
|| loop->num_nodes != 2 || loop->num_nodes != 2
|| !empty_block_p (loop->latch) || !empty_block_p (loop->latch)
|| loop->num_exits != 1 || !loop->single_exit
|| loop->num_entries != 1
/* Verify that new loop exit condition can be trivially modified. */ /* Verify that new loop exit condition can be trivially modified. */
|| (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi)) || (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi))
|| (e != exit_e && e != entry_e)) || (e != exit_e && e != entry_e))
...@@ -801,8 +800,8 @@ void ...@@ -801,8 +800,8 @@ void
slpeel_verify_cfg_after_peeling (struct loop *first_loop, slpeel_verify_cfg_after_peeling (struct loop *first_loop,
struct loop *second_loop) struct loop *second_loop)
{ {
basic_block loop1_exit_bb = first_loop->exit_edges[0]->dest; basic_block loop1_exit_bb = first_loop->single_exit->dest;
basic_block loop2_entry_bb = second_loop->pre_header; basic_block loop2_entry_bb = loop_preheader_edge (second_loop)->src;
basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src; basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src;
/* A guard that controls whether the second_loop is to be executed or skipped /* A guard that controls whether the second_loop is to be executed or skipped
...@@ -812,7 +811,6 @@ slpeel_verify_cfg_after_peeling (struct loop *first_loop, ...@@ -812,7 +811,6 @@ slpeel_verify_cfg_after_peeling (struct loop *first_loop,
*/ */
gcc_assert (EDGE_COUNT (loop1_exit_bb->succs) == 2); gcc_assert (EDGE_COUNT (loop1_exit_bb->succs) == 2);
/* 1. Verify that one of the successors of first_loopt->exit is the preheader /* 1. Verify that one of the successors of first_loopt->exit is the preheader
of second_loop. */ of second_loop. */
...@@ -880,7 +878,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, ...@@ -880,7 +878,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
basic_block bb_before_second_loop, bb_after_second_loop; basic_block bb_before_second_loop, bb_after_second_loop;
basic_block bb_before_first_loop; basic_block bb_before_first_loop;
basic_block bb_between_loops; basic_block bb_between_loops;
edge exit_e = loop->exit_edges [0]; edge exit_e = loop->single_exit;
LOC loop_loc; LOC loop_loc;
if (!slpeel_can_duplicate_loop_p (loop, e)) if (!slpeel_can_duplicate_loop_p (loop, e))
...@@ -961,10 +959,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, ...@@ -961,10 +959,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
bb_before_first_loop = split_edge (loop_preheader_edge (first_loop)); bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
add_bb_to_loop (bb_before_first_loop, first_loop->outer); add_bb_to_loop (bb_before_first_loop, first_loop->outer);
bb_before_second_loop = split_edge (first_loop->exit_edges[0]); bb_before_second_loop = split_edge (first_loop->single_exit);
add_bb_to_loop (bb_before_second_loop, first_loop->outer); add_bb_to_loop (bb_before_second_loop, first_loop->outer);
flow_loop_scan (first_loop, LOOP_ALL);
flow_loop_scan (second_loop, LOOP_ALL);
pre_condition = pre_condition =
build2 (LE_EXPR, boolean_type_node, first_niters, integer_zero_node); build2 (LE_EXPR, boolean_type_node, first_niters, integer_zero_node);
...@@ -1000,12 +996,10 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, ...@@ -1000,12 +996,10 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
orig_exit_bb: orig_exit_bb:
*/ */
bb_between_loops = split_edge (first_loop->exit_edges[0]); bb_between_loops = split_edge (first_loop->single_exit);
add_bb_to_loop (bb_between_loops, first_loop->outer); add_bb_to_loop (bb_between_loops, first_loop->outer);
bb_after_second_loop = split_edge (second_loop->exit_edges[0]); bb_after_second_loop = split_edge (second_loop->single_exit);
add_bb_to_loop (bb_after_second_loop, second_loop->outer); add_bb_to_loop (bb_after_second_loop, second_loop->outer);
flow_loop_scan (first_loop, LOOP_ALL);
flow_loop_scan (second_loop, LOOP_ALL);
pre_condition = build2 (EQ_EXPR, boolean_type_node, first_niters, niters); pre_condition = build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition, skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition,
...@@ -1014,8 +1008,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, ...@@ -1014,8 +1008,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
second_loop == new_loop); second_loop == new_loop);
/* Flow loop scan does not update loop->single_exit field. */ /* Flow loop scan does not update loop->single_exit field. */
first_loop->single_exit = first_loop->exit_edges[0]; first_loop->single_exit = first_loop->single_exit;
second_loop->single_exit = second_loop->exit_edges[0]; second_loop->single_exit = second_loop->single_exit;
/* 4. Make first-loop iterate FIRST_NITERS times, if requested. /* 4. Make first-loop iterate FIRST_NITERS times, if requested.
*/ */
......
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