Commit 5d6a16e2 by Michael Hayes Committed by Michael Hayes

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

2000-09-12  Michael Hayes  <mhayes@cygnus.com>

	* basic-block.h (LOOP_TREE, LOOP_PRE_HEADER, LOOP_EDGES): New.
	(LOOP_EXITS_DOMS, LOOP_ALL): Likewise.
	(flow_loops_update): New prototype.
	(flow_loops_find): Add flags to prototype.
	(struct loop): Add `pre_header_root' and `pre_header_trace' fields.
	* flow.c (flow_loop_pre_header_scan): New.
	(flow_loop_dump): Dump pre-header root and trace and exit dominators.
	(flow_loop_free): Free pre-header root and trace and exit dominators.
	(flow_loops_find): New argument flags.
	(flow_loops_update): New function.
	* toplev.c (rest_of_compilation): Add flag argument to flow_loops_find.

From-SVN: r36333
parent c586192c
2000-09-12 Michael Hayes <mhayes@cygnus.com>
* basic-block.h (LOOP_TREE, LOOP_PRE_HEADER, LOOP_EDGES): New.
(LOOP_EXITS_DOMS, LOOP_ALL): Likewise.
(flow_loops_update): New prototype.
(flow_loops_find): Add flags to prototype.
(struct loop): Add `pre_header_root' and `pre_header_trace' fields.
* flow.c (flow_loop_pre_header_scan): New.
(flow_loop_dump): Dump pre-header root and trace and exit dominators.
(flow_loop_free): Free pre-header root and trace and exit dominators.
(flow_loops_find): New argument flags.
(flow_loops_update): New function.
* toplev.c (rest_of_compilation): Add flag argument to flow_loops_find.
2000-09-12 Michael Hayes <mhayes@cygnus.com>
* basic-block.h (split_block, update_bb_for_insn): New prototypes.
* flow.c (split_block, update_bb_for_insn): New functions.
......
......@@ -276,6 +276,12 @@ struct loop
/* Basic block of loop pre-header or NULL if it does not exist. */
basic_block pre_header;
/* Root node of pre_header extended basic block. */
basic_block pre_header_root;
/* Bitmap of blocks of trace from pre_header root to pre_header. */
sbitmap pre_header_trace;
/* The first block in the loop. This is not necessarily the same as
the loop header. */
basic_block first;
......@@ -302,6 +308,9 @@ struct loop
/* 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. */
int depth;
......@@ -404,7 +413,8 @@ struct loops
sbitmap shared_headers;
};
extern int flow_loops_find PARAMS ((struct loops *));
extern int flow_loops_find PARAMS ((struct loops *, int flags));
extern int flow_loops_update PARAMS ((struct loops *, int flags));
extern void flow_loops_free PARAMS ((struct loops *));
extern void flow_loops_dump PARAMS ((const struct loops *, FILE *,
void (*)(const struct loop *,
......@@ -468,6 +478,15 @@ enum update_life_extent
#define PROP_AUTOINC 32 /* Create autoinc mem references. */
#define PROP_FINAL 63 /* All of the above. */
/* Flags for loop discovery. */
#define LOOP_TREE 1 /* Build loop hierarchy tree. */
#define LOOP_PRE_HEADER 2 /* Analyse loop pre-header. */
#define LOOP_EDGES 4 /* Find entry and exit edges. */
#define LOOP_EXITS_DOMS 8 /* Find nodes that dom. all exits. */
#define LOOP_ALL 15 /* All of the above */
extern void life_analysis PARAMS ((rtx, FILE *, int));
extern void update_life_info PARAMS ((sbitmap, enum update_life_extent,
int));
......
......@@ -432,7 +432,9 @@ static basic_block flow_dfs_compute_reverse_execute
PARAMS ((depth_first_search_ds));
static void flow_dfs_compute_reverse_finish
PARAMS ((depth_first_search_ds));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block, const sbitmap *));
static void flow_loop_pre_header_scan PARAMS ((struct loop *));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
const sbitmap *));
static void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *));
static void flow_loops_tree_build PARAMS ((struct loops *));
static int flow_loop_level_compute PARAMS ((struct loop *, int));
......@@ -7374,13 +7376,20 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
loop->depth, loop->level,
(long) (loop->outer ? loop->outer->num : -1));
if (loop->pre_header_root)
fprintf (file, ";; pre-header root %d\n",
loop->pre_header_root->index);
if (loop->pre_header_trace)
flow_nodes_print (";; pre-header trace", loop->pre_header_trace,
file);
flow_edge_list_print (";; entry edges", loop->entry_edges,
loop->num_entries, file);
fprintf (file, ";; %d", loop->num_nodes);
flow_nodes_print (" nodes", loop->nodes, file);
flow_edge_list_print (";; exit edges", loop->exit_edges,
loop->num_exits, file);
if (loop->exits_doms)
flow_nodes_print (";; exit doms", loop->exits_doms, file);
if (loop_dump_aux)
loop_dump_aux (loop, file, verbose);
}
......@@ -7463,12 +7472,16 @@ flow_loops_free (loops)
{
struct loop *loop = &loops->array[i];
if (loop->pre_header_trace)
sbitmap_free (loop->pre_header_trace);
if (loop->nodes)
sbitmap_free (loop->nodes);
if (loop->entry_edges)
free (loop->entry_edges);
if (loop->exit_edges)
free (loop->exit_edges);
if (loop->exits_doms)
sbitmap_free (loop->exits_doms);
}
free (loops->array);
loops->array = NULL;
......@@ -7478,6 +7491,7 @@ flow_loops_free (loops)
if (loops->cfg.dfs_order)
free (loops->cfg.dfs_order);
if (loops->shared_headers)
sbitmap_free (loops->shared_headers);
}
}
......@@ -7839,6 +7853,36 @@ flow_dfs_compute_reverse_finish (data)
return;
}
/* Find the root node of the loop pre-header extended basic block and
the blocks along the trace from the root node to the loop header. */
static void
flow_loop_pre_header_scan (loop)
struct loop *loop;
{
basic_block ebb;
if (loop->num_entries != 1)
return;
/* Find pre_header root note and trace from root node to pre_header. */
loop->pre_header_trace = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (loop->pre_header_trace);
ebb = loop->entry_edges[0]->src;
SET_BIT (loop->pre_header_trace, ebb->index);
while (ebb->pred->src != ENTRY_BLOCK_PTR
&& ! ebb->pred->pred_next)
{
ebb = ebb->pred->src;
SET_BIT (loop->pre_header_trace, ebb->index);
}
loop->pre_header_root = ebb;
}
/* Return the block for the pre-header of the loop with header
HEADER where DOM specifies the dominator information. Return NULL if
there is no pre-header. */
......@@ -7987,13 +8031,16 @@ flow_loops_level_compute (loops)
return levels;
}
/* Find all the natural loops in the function and save in LOOPS structure
and recalculate loop_depth information in basic block structures.
FLAGS controls which loop information is collected.
Return the number of natural loops found. */
int
flow_loops_find (loops)
flow_loops_find (loops, flags)
struct loops *loops;
int flags;
{
int i;
int b;
......@@ -8004,32 +8051,38 @@ flow_loops_find (loops)
int *dfs_order;
int *rc_order;
loops->num = 0;
loops->array = NULL;
loops->tree = NULL;
dfs_order = NULL;
rc_order = NULL;
/* 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. */
if (! (flags & LOOP_TREE))
abort ();
memset (loops, 0, sizeof (*loops));
/* Taking care of this degenerate case makes the rest of
this code simpler. */
if (n_basic_blocks == 0)
return 0;
dfs_order = NULL;
rc_order = NULL;
/* Compute the dominators. */
dom = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
compute_flow_dominators (dom, NULL);
/* Count the number of loop edges (back edges). This should be the
same as the number of natural loops. Also clear the loop_depth
and as we work from inner->outer in a loop nest we call
find_loop_nodes_find which will increment loop_depth for nodes
within the current loop, which happens to enclose inner loops. */
same as the number of natural loops. */
num_loops = 0;
for (b = 0; b < n_basic_blocks; b++)
{
BASIC_BLOCK (b)->loop_depth = 0;
for (e = BASIC_BLOCK (b)->pred; e; e = e->pred_next)
basic_block header;
header = BASIC_BLOCK (b);
header->loop_depth = 0;
for (e = header->pred; e; e = e->pred_next)
{
basic_block latch = e->src;
......@@ -8039,6 +8092,9 @@ flow_loops_find (loops)
loop. It also has single back edge to the header
from a latch node. Note that multiple natural loops
may share the same header. */
if (b != header->index)
abort ();
if (latch != ENTRY_BLOCK_PTR && TEST_BIT (dom[latch->index], b))
num_loops++;
}
......@@ -8069,8 +8125,8 @@ flow_loops_find (loops)
{
basic_block header;
/* Search the nodes of the CFG in DFS order that we can find
outer loops first. */
/* Search the nodes of the CFG in reverse completion order
so that we can find outer loops first. */
header = BASIC_BLOCK (rc_order[b]);
/* Look for all the possible latch blocks for this header. */
......@@ -8095,16 +8151,26 @@ flow_loops_find (loops)
loop->latch = latch;
loop->num = num_loops;
num_loops++;
}
}
}
for (i = 0; i < num_loops; i++)
{
struct loop *loop = &loops->array[i];
int j;
/* Keep track of blocks that are loop headers so
that we can tell which loops should be merged. */
if (TEST_BIT (headers, header->index))
SET_BIT (loops->shared_headers, header->index);
SET_BIT (headers, header->index);
if (TEST_BIT (headers, loop->header->index))
SET_BIT (loops->shared_headers, loop->header->index);
SET_BIT (headers, loop->header->index);
/* Find nodes contained within the loop. */
loop->nodes = sbitmap_alloc (n_basic_blocks);
loop->num_nodes
= flow_loop_nodes_find (header, latch, loop->nodes);
= flow_loop_nodes_find (loop->header, loop->latch, loop->nodes);
/* Compute first and last blocks within the loop.
These are often the same as the loop header and
......@@ -8115,11 +8181,14 @@ flow_loops_find (loops)
loop->last
= BASIC_BLOCK (sbitmap_last_set_bit (loop->nodes));
if (flags & LOOP_EDGES)
{
/* Find edges which enter the loop header.
Note that the entry edges should only
enter the header of a natural loop. */
loop->num_entries
= flow_loop_entry_edges_find (loop->header, loop->nodes,
= flow_loop_entry_edges_find (loop->header,
loop->nodes,
&loop->entry_edges);
/* Find edges which exit the loop. */
......@@ -8127,11 +8196,27 @@ flow_loops_find (loops)
= flow_loop_exit_edges_find (loop->nodes,
&loop->exit_edges);
/* Determine which loop nodes dominate all the exits
of the loop. */
loop->exits_doms = sbitmap_alloc (n_basic_blocks);
sbitmap_copy (loop->exits_doms, loop->nodes);
for (j = 0; j < loop->num_exits; j++)
sbitmap_a_and_b (loop->exits_doms, loop->exits_doms,
dom[loop->exit_edges[j]->src->index]);
/* The header of a natural loop must dominate
all exits. */
if (! TEST_BIT (loop->exits_doms, loop->header->index))
abort ();
}
if (flags & LOOP_PRE_HEADER)
{
/* Look to see if the loop has a pre-header node. */
loop->pre_header = flow_loop_pre_header_find (header, dom);
loop->pre_header
= flow_loop_pre_header_find (loop->header, dom);
num_loops++;
}
flow_loop_pre_header_scan (loop);
}
}
......@@ -8163,6 +8248,23 @@ flow_loops_find (loops)
return num_loops;
}
/* Update the information regarding the loops in the CFG
specified by LOOPS. */
int
flow_loops_update (loops, flags)
struct loops *loops;
int flags;
{
/* One day we may want to update the current loop data. For now
throw away the old stuff and rebuild what we need. */
if (loops->array)
flow_loops_free (loops);
return flow_loops_find (loops, flags);
}
/* Return non-zero if edge E enters header of LOOP from outside of LOOP. */
int
......
......@@ -3211,7 +3211,7 @@ rest_of_compilation (decl)
/* Discover and record the loop depth at the head of each basic
block. The loop infrastructure does the real job for us. */
flow_loops_find (&loops);
flow_loops_find (&loops, LOOP_TREE);
/* Estimate using heuristics if no profiling info is available. */
estimate_probability (&loops);
......
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