basic-block.h (struct basic_block_def): New field loop_father.
* basic-block.h (struct basic_block_def): New field loop_father. (BB_VISITED): New flag. (struct loop): New field pred, removed field shared. (struct loops): New field parray. (LOOP_EXITS_DOMS): Removed. (flow_loop_tree_node_add, flow_loop_tree_node_remove, flow_loop_nested_p, flow_bb_inside_loop_p, get_loop_body, dfs_enumerate_from, loop_preheader_edge, loop_latch_edge, add_bb_to_loop, remove_bb_from_loops, find_common_loop, verify_loop_structure): Declare. * cfg.c (entry_exit_blocks): Initialize loop_father field. * cfganal.c (dfs_enumerate_from): New function. * cfgloop.c (HEAVY_EDGE_RATIO): New constant. (flow_loop_entry_edges_find, flow_loop_exit_edges_find, flow_loop_nodes_find, flow_loop_level_compute, flow_loop_nested_p, flow_loop_dump, flow_loops_dump, flow_loops_free, flow_loop_tree_node_add, flow_loop_level_compute, flow_loops_level_compute, flow_loop_scan, flow_loops_update, flow_loop_outside_edge_p): Modified for new infrastructure. (make_forwarder_block, canonicalize_loop_headers, glb_enum_p, redirect_edge_with_latch_update, flow_loop_free): New static functions. (flow_loop_tree_node_remove, flow_bb_inside_loop_p, get_loop_body, add_bb_to_loop, remove_bb_from_loops, find_common_loop, verify_loop_structure, loop_latch_edge, loop_preheader_edge): New functions. (flow_loops_cfg_dump): Do not show dominators, as this information does not remain up to date long. (flow_loops_find): Store results in new format. * predict.c (propagate_freq, estimate_probability, estimate_loops_at_level, estimate_bb_frequencies): Use new loop infrastructure. From-SVN: r54142
This commit is contained in:
parent
d6ee5ebf93
commit
2ecfd709c2
6 changed files with 883 additions and 418 deletions
|
@ -1,3 +1,37 @@
|
|||
Sat Jun 1 11:23:22 CEST 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
|
||||
|
||||
* basic-block.h (struct basic_block_def): New field loop_father.
|
||||
(BB_VISITED): New flag.
|
||||
(struct loop): New field pred, removed field shared.
|
||||
(struct loops): New field parray.
|
||||
(LOOP_EXITS_DOMS): Removed.
|
||||
(flow_loop_tree_node_add, flow_loop_tree_node_remove,
|
||||
flow_loop_nested_p, flow_bb_inside_loop_p, get_loop_body,
|
||||
dfs_enumerate_from, loop_preheader_edge, loop_latch_edge,
|
||||
add_bb_to_loop, remove_bb_from_loops, find_common_loop,
|
||||
verify_loop_structure): Declare.
|
||||
* cfg.c (entry_exit_blocks): Initialize loop_father field.
|
||||
* cfganal.c (dfs_enumerate_from): New function.
|
||||
* cfgloop.c (HEAVY_EDGE_RATIO): New constant.
|
||||
(flow_loop_entry_edges_find, flow_loop_exit_edges_find,
|
||||
flow_loop_nodes_find, flow_loop_level_compute, flow_loop_nested_p,
|
||||
flow_loop_dump, flow_loops_dump, flow_loops_free,
|
||||
flow_loop_tree_node_add, flow_loop_level_compute,
|
||||
flow_loops_level_compute, flow_loop_scan, flow_loops_update,
|
||||
flow_loop_outside_edge_p): Modified for new infrastructure.
|
||||
(make_forwarder_block, canonicalize_loop_headers, glb_enum_p,
|
||||
redirect_edge_with_latch_update, flow_loop_free): New static functions.
|
||||
(flow_loop_tree_node_remove, flow_bb_inside_loop_p,
|
||||
get_loop_body, add_bb_to_loop, remove_bb_from_loops,
|
||||
find_common_loop, verify_loop_structure, loop_latch_edge,
|
||||
loop_preheader_edge): New functions.
|
||||
(flow_loops_cfg_dump): Do not show dominators, as this information
|
||||
does not remain up to date long.
|
||||
(flow_loops_find): Store results in new format.
|
||||
* predict.c (propagate_freq, estimate_probability,
|
||||
estimate_loops_at_level, estimate_bb_frequencies): Use new loop
|
||||
infrastructure.
|
||||
|
||||
2002-06-01 Alan Lehotsky <apl@alum.mit.edu>
|
||||
|
||||
* except.c (nothrow_function_p): Walk epilogue delay list
|
||||
|
|
|
@ -212,6 +212,9 @@ typedef struct basic_block_def {
|
|||
/* The loop depth of this block. */
|
||||
int loop_depth;
|
||||
|
||||
/* Outermost loop containing the block. */
|
||||
struct loop *loop_father;
|
||||
|
||||
/* Expected number of executions: calculated in profile.c. */
|
||||
gcov_type count;
|
||||
|
||||
|
@ -228,6 +231,7 @@ typedef struct basic_block_def {
|
|||
#define BB_DIRTY 1
|
||||
#define BB_NEW 2
|
||||
#define BB_REACHABLE 4
|
||||
#define BB_VISITED 8
|
||||
|
||||
/* Number of basic blocks in the current function. */
|
||||
|
||||
|
@ -403,6 +407,9 @@ struct loop
|
|||
/* The loop nesting depth. */
|
||||
int depth;
|
||||
|
||||
/* Superloops of the loop. */
|
||||
struct loop **pred;
|
||||
|
||||
/* The height of the loop (enclosed loop levels) within the loop
|
||||
hierarchy tree. */
|
||||
int level;
|
||||
|
@ -416,9 +423,6 @@ struct loop
|
|||
/* Link to the next (sibling) loop. */
|
||||
struct loop *next;
|
||||
|
||||
/* Non-zero if the loop shares a header with another loop. */
|
||||
int shared;
|
||||
|
||||
/* Non-zero if the loop is invalid (e.g., contains setjmp.). */
|
||||
int invalid;
|
||||
|
||||
|
@ -484,6 +488,11 @@ struct loops
|
|||
will find the inner loops before their enclosing outer loops). */
|
||||
struct loop *array;
|
||||
|
||||
/* The above array is unused in new loop infrastructure and is kept only for
|
||||
purposes of the old loop optimizer. Instead we store just pointers to
|
||||
loops here. */
|
||||
struct loop **parray;
|
||||
|
||||
/* Pointer to root of loop heirachy tree. */
|
||||
struct loop *tree_root;
|
||||
|
||||
|
@ -515,6 +524,8 @@ extern void flow_loop_dump PARAMS ((const struct loop *, FILE *,
|
|||
void (*)(const struct loop *,
|
||||
FILE *, int), int));
|
||||
extern int flow_loop_scan PARAMS ((struct loops *, struct loop *, int));
|
||||
extern void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *));
|
||||
extern void flow_loop_tree_node_remove PARAMS ((struct loop *));
|
||||
|
||||
/* This structure maintains an edge list vector. */
|
||||
struct edge_list
|
||||
|
@ -613,8 +624,7 @@ enum update_life_extent
|
|||
#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_EXITS_DOMS 16 /* Find nodes that dom. all exits. */
|
||||
#define LOOP_ALL 31 /* All of the above */
|
||||
#define LOOP_ALL 15 /* All of the above */
|
||||
|
||||
extern void life_analysis PARAMS ((rtx, FILE *, int));
|
||||
extern int update_life_info PARAMS ((sbitmap, enum update_life_extent,
|
||||
|
@ -701,7 +711,24 @@ extern void free_aux_for_edges PARAMS ((void));
|
|||
debugger, and it is declared extern so we don't get warnings about
|
||||
it being unused. */
|
||||
extern void verify_flow_info PARAMS ((void));
|
||||
extern int flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
|
||||
extern bool flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
|
||||
extern bool flow_loop_nested_p PARAMS ((const struct loop *, const struct loop *));
|
||||
extern bool flow_bb_inside_loop_p PARAMS ((const struct loop *, basic_block));
|
||||
extern basic_block *get_loop_body PARAMS ((const struct loop *));
|
||||
extern int dfs_enumerate_from PARAMS ((basic_block, int,
|
||||
bool (*)(basic_block, void *),
|
||||
basic_block *, int, void *));
|
||||
|
||||
extern edge loop_preheader_edge PARAMS ((struct loop *));
|
||||
extern edge loop_latch_edge PARAMS ((struct loop *));
|
||||
|
||||
extern void add_bb_to_loop PARAMS ((basic_block, struct loop *));
|
||||
extern void remove_bb_from_loops PARAMS ((basic_block));
|
||||
extern struct loop * find_common_loop PARAMS ((struct loop *, struct loop *));
|
||||
|
||||
extern void verify_loop_structure PARAMS ((struct loops *, int));
|
||||
#define VLS_EXPECT_PREHEADERS 1
|
||||
#define VLS_EXPECT_SIMPLE_LATCHES 2
|
||||
|
||||
typedef struct conflict_graph_def *conflict_graph;
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ struct basic_block_def entry_exit_blocks[2]
|
|||
NULL, /* prev_bb */
|
||||
EXIT_BLOCK_PTR, /* next_bb */
|
||||
0, /* loop_depth */
|
||||
NULL, /* loop_father */
|
||||
0, /* count */
|
||||
0, /* frequency */
|
||||
0 /* flags */
|
||||
|
@ -120,6 +121,7 @@ struct basic_block_def entry_exit_blocks[2]
|
|||
ENTRY_BLOCK_PTR, /* prev_bb */
|
||||
NULL, /* next_bb */
|
||||
0, /* loop_depth */
|
||||
NULL, /* loop_father */
|
||||
0, /* count */
|
||||
0, /* frequency */
|
||||
0 /* flags */
|
||||
|
|
|
@ -1103,3 +1103,54 @@ flow_dfs_compute_reverse_finish (data)
|
|||
free (data->stack);
|
||||
sbitmap_free (data->visited_blocks);
|
||||
}
|
||||
|
||||
/* Performs dfs search from BB over vertices satisfying PREDICATE;
|
||||
if REVERSE, go against direction of edges. Returns number of blocks
|
||||
found and their list in RSLT. RSLT can contain at most RSLT_MAX items. */
|
||||
int
|
||||
dfs_enumerate_from (bb, reverse, predicate, rslt, rslt_max, data)
|
||||
basic_block bb;
|
||||
int reverse;
|
||||
bool (*predicate) (basic_block, void *);
|
||||
basic_block *rslt;
|
||||
int rslt_max;
|
||||
void *data;
|
||||
{
|
||||
basic_block *st, lbb;
|
||||
int sp = 0, tv = 0;
|
||||
|
||||
st = xcalloc (rslt_max, sizeof (basic_block));
|
||||
rslt[tv++] = st[sp++] = bb;
|
||||
bb->flags |= BB_VISITED;
|
||||
while (sp)
|
||||
{
|
||||
edge e;
|
||||
lbb = st[--sp];
|
||||
if (reverse)
|
||||
{
|
||||
for (e = lbb->pred; e; e = e->pred_next)
|
||||
if (!(e->src->flags & BB_VISITED) && predicate (e->src, data))
|
||||
{
|
||||
if (tv == rslt_max)
|
||||
abort ();
|
||||
rslt[tv++] = st[sp++] = e->src;
|
||||
e->src->flags |= BB_VISITED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (e = lbb->succ; e; e = e->succ_next)
|
||||
if (!(e->dest->flags & BB_VISITED) && predicate (e->dest, data))
|
||||
{
|
||||
if (tv == rslt_max)
|
||||
abort ();
|
||||
rslt[tv++] = st[sp++] = e->dest;
|
||||
e->dest->flags |= BB_VISITED;
|
||||
}
|
||||
}
|
||||
}
|
||||
free (st);
|
||||
for (sp = 0; sp < tv; sp++)
|
||||
rslt[sp]->flags &= ~BB_VISITED;
|
||||
return tv;
|
||||
}
|
||||
|
|
1059
gcc/cfgloop.c
1059
gcc/cfgloop.c
File diff suppressed because it is too large
Load diff
116
gcc/predict.c
116
gcc/predict.c
|
@ -70,7 +70,7 @@ static void combine_predictions_for_insn PARAMS ((rtx, basic_block));
|
|||
static void dump_prediction PARAMS ((enum br_predictor, int,
|
||||
basic_block, int));
|
||||
static void estimate_loops_at_level PARAMS ((struct loop *loop));
|
||||
static void propagate_freq PARAMS ((basic_block));
|
||||
static void propagate_freq PARAMS ((struct loop *));
|
||||
static void estimate_bb_frequencies PARAMS ((struct loops *));
|
||||
static void counts_to_freqs PARAMS ((void));
|
||||
static void process_note_predictions PARAMS ((basic_block, int *, int *,
|
||||
|
@ -419,19 +419,23 @@ estimate_probability (loops_info)
|
|||
|
||||
/* Try to predict out blocks in a loop that are not part of a
|
||||
natural loop. */
|
||||
for (i = 0; i < loops_info->num; i++)
|
||||
for (i = 1; i < loops_info->num; i++)
|
||||
{
|
||||
basic_block bb, *bbs;
|
||||
int j;
|
||||
int exits;
|
||||
struct loop *loop = &loops_info->array[i];
|
||||
struct loop *loop = loops_info->parray[i];
|
||||
|
||||
flow_loop_scan (loops_info, loop, LOOP_EXIT_EDGES);
|
||||
exits = loop->num_exits;
|
||||
|
||||
FOR_BB_BETWEEN (bb, loop->first, loop->last->next_bb, next_bb)
|
||||
if (TEST_BIT (loop->nodes, bb->index))
|
||||
{
|
||||
int header_found = 0;
|
||||
edge e;
|
||||
bbs = get_loop_body (loop);
|
||||
for (j = 0; j < loop->num_nodes; j++)
|
||||
{
|
||||
int header_found = 0;
|
||||
edge e;
|
||||
|
||||
bb = bbs[j];
|
||||
|
||||
/* Bypass loop heuristics on continue statement. These
|
||||
statements construct loops via "non-loop" constructs
|
||||
|
@ -440,28 +444,28 @@ estimate_probability (loops_info)
|
|||
if (predicted_by_p (bb, PRED_CONTINUE))
|
||||
continue;
|
||||
|
||||
/* Loop branch heuristics - predict an edge back to a
|
||||
loop's head as taken. */
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
if (e->dest == loop->header
|
||||
&& e->src == loop->latch)
|
||||
{
|
||||
header_found = 1;
|
||||
predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
|
||||
}
|
||||
/* Loop branch heuristics - predict an edge back to a
|
||||
loop's head as taken. */
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
if (e->dest == loop->header
|
||||
&& e->src == loop->latch)
|
||||
{
|
||||
header_found = 1;
|
||||
predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
|
||||
}
|
||||
|
||||
/* Loop exit heuristics - predict an edge exiting the loop if the
|
||||
conditinal has no loop header successors as not taken. */
|
||||
if (!header_found)
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
if (e->dest->index < 0
|
||||
|| !TEST_BIT (loop->nodes, e->dest->index))
|
||||
predict_edge
|
||||
(e, PRED_LOOP_EXIT,
|
||||
(REG_BR_PROB_BASE
|
||||
- predictor_info [(int) PRED_LOOP_EXIT].hitrate)
|
||||
/ exits);
|
||||
}
|
||||
/* Loop exit heuristics - predict an edge exiting the loop if the
|
||||
conditinal has no loop header successors as not taken. */
|
||||
if (!header_found)
|
||||
for (e = bb->succ; e; e = e->succ_next)
|
||||
if (e->dest->index < 0
|
||||
|| !flow_bb_inside_loop_p (loop, e->dest))
|
||||
predict_edge
|
||||
(e, PRED_LOOP_EXIT,
|
||||
(REG_BR_PROB_BASE
|
||||
- predictor_info [(int) PRED_LOOP_EXIT].hitrate)
|
||||
/ exits);
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to predict conditional jumps using a number of heuristics. */
|
||||
|
@ -896,12 +900,13 @@ typedef struct edge_info_def
|
|||
#define EDGE_INFO(E) ((edge_info) (E)->aux)
|
||||
|
||||
/* Helper function for estimate_bb_frequencies.
|
||||
Propagate the frequencies for loops headed by HEAD. */
|
||||
Propagate the frequencies for LOOP. */
|
||||
|
||||
static void
|
||||
propagate_freq (head)
|
||||
basic_block head;
|
||||
propagate_freq (loop)
|
||||
struct loop *loop;
|
||||
{
|
||||
basic_block head = loop->header;
|
||||
basic_block bb;
|
||||
basic_block last;
|
||||
edge e;
|
||||
|
@ -1028,41 +1033,28 @@ static void
|
|||
estimate_loops_at_level (first_loop)
|
||||
struct loop *first_loop;
|
||||
{
|
||||
struct loop *l, *loop = first_loop;
|
||||
struct loop *loop;
|
||||
|
||||
for (loop = first_loop; loop; loop = loop->next)
|
||||
{
|
||||
int n;
|
||||
edge e;
|
||||
basic_block *bbs;
|
||||
int i;
|
||||
|
||||
estimate_loops_at_level (loop->inner);
|
||||
|
||||
/* Find current loop back edge and mark it. */
|
||||
for (e = loop->latch->succ; e->dest != loop->header; e = e->succ_next)
|
||||
;
|
||||
|
||||
EDGE_INFO (e)->back_edge = 1;
|
||||
|
||||
/* In case the loop header is shared, ensure that it is the last
|
||||
one sharing the same header, so we avoid redundant work. */
|
||||
if (loop->shared)
|
||||
|
||||
if (loop->latch->succ) /* Do not do this for dummy function loop. */
|
||||
{
|
||||
for (l = loop->next; l; l = l->next)
|
||||
if (l->header == loop->header)
|
||||
break;
|
||||
/* Find current loop back edge and mark it. */
|
||||
e = loop_latch_edge (loop);
|
||||
EDGE_INFO (e)->back_edge = 1;
|
||||
}
|
||||
|
||||
if (l)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now merge all nodes of all loops with given header as not visited. */
|
||||
for (l = loop->shared ? first_loop : loop; l != loop->next; l = l->next)
|
||||
if (loop->header == l->header)
|
||||
EXECUTE_IF_SET_IN_SBITMAP (l->nodes, 0, n,
|
||||
BLOCK_INFO (BASIC_BLOCK (n))->tovisit = 1
|
||||
);
|
||||
|
||||
propagate_freq (loop->header);
|
||||
bbs = get_loop_body (loop);
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
BLOCK_INFO (bbs[i])->tovisit = 1;
|
||||
free (bbs);
|
||||
propagate_freq (loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1202,12 +1194,6 @@ estimate_bb_frequencies (loops)
|
|||
to outermost to examine probabilities for back edges. */
|
||||
estimate_loops_at_level (loops->tree_root);
|
||||
|
||||
/* Now fake loop around whole function to finalize probabilities. */
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
|
||||
BLOCK_INFO (bb)->tovisit = 1;
|
||||
|
||||
propagate_freq (ENTRY_BLOCK_PTR);
|
||||
|
||||
memcpy (&freq_max, &real_zero, sizeof (real_zero));
|
||||
FOR_EACH_BB (bb)
|
||||
if (REAL_VALUES_LESS
|
||||
|
|
Loading…
Add table
Reference in a new issue