tree-ssa-loop-im.c (schedule_sm, [...]): Use vector of edges instead of array.
* tree-ssa-loop-im.c (schedule_sm, determine_lsm_ref, hoist_memory_references, loop_suitable_for_sm, determine_lsm_loop): Use vector of edges instead of array. * tree-ssa-loop-niter.c (find_loop_niter, find_loop_niter_by_eval, estimate_numbers_of_iterations_loop): Ditto. * predict.c (predict_loops): Ditto. * loop-unroll.c (analyze_insns_in_loop): Ditto. * tree-ssa-threadupdate.c: Remove declaration of heap allocation for edge vectors. * basic-block.h: Declare heap allocation for edge vectors. * tree-outof-ssa.c: Ditto. * cfgloop.c (get_loop_exit_edges): Return vector of edges. * cfgloop.h (get_loop_exit_edges): Declaration changed. From-SVN: r119039
This commit is contained in:
parent
c61191974b
commit
ca83d38556
10 changed files with 88 additions and 78 deletions
|
@ -1,3 +1,19 @@
|
|||
2006-11-21 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* tree-ssa-loop-im.c (schedule_sm, determine_lsm_ref,
|
||||
hoist_memory_references, loop_suitable_for_sm, determine_lsm_loop):
|
||||
Use vector of edges instead of array.
|
||||
* tree-ssa-loop-niter.c (find_loop_niter, find_loop_niter_by_eval,
|
||||
estimate_numbers_of_iterations_loop): Ditto.
|
||||
* predict.c (predict_loops): Ditto.
|
||||
* loop-unroll.c (analyze_insns_in_loop): Ditto.
|
||||
* tree-ssa-threadupdate.c: Remove declaration of heap allocation for
|
||||
edge vectors.
|
||||
* basic-block.h: Declare heap allocation for edge vectors.
|
||||
* tree-outof-ssa.c: Ditto.
|
||||
* cfgloop.c (get_loop_exit_edges): Return vector of edges.
|
||||
* cfgloop.h (get_loop_exit_edges): Declaration changed.
|
||||
|
||||
2006-11-20 Zack Weinberg <zackw@panix.com>
|
||||
|
||||
* gengtype.c (process_gc_options): Remove unnecessary forward decl.
|
||||
|
|
|
@ -146,6 +146,7 @@ struct edge_def GTY(())
|
|||
typedef struct edge_def *edge;
|
||||
DEF_VEC_P(edge);
|
||||
DEF_VEC_ALLOC_P(edge,gc);
|
||||
DEF_VEC_ALLOC_P(edge,heap);
|
||||
|
||||
#define EDGE_FALLTHRU 1 /* 'Straight line' flow */
|
||||
#define EDGE_ABNORMAL 2 /* Strange flow, like computed
|
||||
|
|
|
@ -881,30 +881,24 @@ get_loop_body_in_bfs_order (const struct loop *loop)
|
|||
return blocks;
|
||||
}
|
||||
|
||||
/* Gets exit edges of a LOOP, returning their number in N_EDGES. */
|
||||
edge *
|
||||
get_loop_exit_edges (const struct loop *loop, unsigned int *num_edges)
|
||||
/* Returns the list of the exit edges of a LOOP. */
|
||||
|
||||
VEC (edge, heap) *
|
||||
get_loop_exit_edges (const struct loop *loop)
|
||||
{
|
||||
edge *edges, e;
|
||||
unsigned i, n;
|
||||
basic_block * body;
|
||||
VEC (edge, heap) *edges = NULL;
|
||||
edge e;
|
||||
unsigned i;
|
||||
basic_block *body;
|
||||
edge_iterator ei;
|
||||
|
||||
gcc_assert (loop->latch != EXIT_BLOCK_PTR);
|
||||
|
||||
body = get_loop_body (loop);
|
||||
n = 0;
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
FOR_EACH_EDGE (e, ei, body[i]->succs)
|
||||
if (!flow_bb_inside_loop_p (loop, e->dest))
|
||||
n++;
|
||||
edges = XNEWVEC (edge, n);
|
||||
*num_edges = n;
|
||||
n = 0;
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
FOR_EACH_EDGE (e, ei, body[i]->succs)
|
||||
if (!flow_bb_inside_loop_p (loop, e->dest))
|
||||
edges[n++] = e;
|
||||
VEC_safe_push (edge, heap, edges, e);
|
||||
free (body);
|
||||
|
||||
return edges;
|
||||
|
|
|
@ -222,7 +222,7 @@ extern void mark_loop_exit_edges (struct loops *);
|
|||
extern basic_block *get_loop_body (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
|
||||
extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
|
||||
extern VEC (edge, heap) *get_loop_exit_edges (const struct loop *);
|
||||
extern unsigned num_loop_branches (const struct loop *);
|
||||
|
||||
extern edge loop_preheader_edge (const struct loop *);
|
||||
|
|
|
@ -1709,14 +1709,15 @@ static struct opt_info *
|
|||
analyze_insns_in_loop (struct loop *loop)
|
||||
{
|
||||
basic_block *body, bb;
|
||||
unsigned i, num_edges = 0;
|
||||
unsigned i;
|
||||
struct opt_info *opt_info = XCNEW (struct opt_info);
|
||||
rtx insn;
|
||||
struct iv_to_split *ivts = NULL;
|
||||
struct var_to_expand *ves = NULL;
|
||||
PTR *slot1;
|
||||
PTR *slot2;
|
||||
edge *edges = get_loop_exit_edges (loop, &num_edges);
|
||||
VEC (edge, heap) *edges = get_loop_exit_edges (loop);
|
||||
edge exit;
|
||||
bool can_apply = false;
|
||||
|
||||
iv_analysis_loop_init (loop);
|
||||
|
@ -1730,11 +1731,14 @@ analyze_insns_in_loop (struct loop *loop)
|
|||
/* Record the loop exit bb and loop preheader before the unrolling. */
|
||||
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
|
||||
|
||||
if (num_edges == 1
|
||||
&& !(edges[0]->flags & EDGE_COMPLEX))
|
||||
if (VEC_length (edge, edges) == 1)
|
||||
{
|
||||
opt_info->loop_exit = split_edge (edges[0]);
|
||||
can_apply = true;
|
||||
exit = VEC_index (edge, edges, 0);
|
||||
if (!(exit->flags & EDGE_COMPLEX))
|
||||
{
|
||||
opt_info->loop_exit = split_edge (exit);
|
||||
can_apply = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_variable_expansion_in_unroller
|
||||
|
@ -1774,7 +1778,7 @@ analyze_insns_in_loop (struct loop *loop)
|
|||
}
|
||||
}
|
||||
|
||||
free (edges);
|
||||
VEC_free (edge, heap, edges);
|
||||
free (body);
|
||||
return opt_info;
|
||||
}
|
||||
|
|
|
@ -640,23 +640,23 @@ predict_loops (struct loops *loops_info)
|
|||
for (i = 1; i < loops_info->num; i++)
|
||||
{
|
||||
basic_block bb, *bbs;
|
||||
unsigned j;
|
||||
unsigned n_exits;
|
||||
unsigned j, n_exits;
|
||||
struct loop *loop = loops_info->parray[i];
|
||||
edge *exits;
|
||||
VEC (edge, heap) *exits;
|
||||
struct tree_niter_desc niter_desc;
|
||||
edge ex;
|
||||
|
||||
exits = get_loop_exit_edges (loop, &n_exits);
|
||||
exits = get_loop_exit_edges (loop);
|
||||
n_exits = VEC_length (edge, exits);
|
||||
|
||||
|
||||
for (j = 0; j < n_exits; j++)
|
||||
for (j = 0; VEC_iterate (edge, exits, j, ex); j++)
|
||||
{
|
||||
tree niter = NULL;
|
||||
|
||||
if (number_of_iterations_exit (loop, exits[j], &niter_desc, false))
|
||||
if (number_of_iterations_exit (loop, ex, &niter_desc, false))
|
||||
niter = niter_desc.niter;
|
||||
if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)
|
||||
niter = loop_niter_by_eval (loop, exits[j]);
|
||||
niter = loop_niter_by_eval (loop, ex);
|
||||
|
||||
if (TREE_CODE (niter) == INTEGER_CST)
|
||||
{
|
||||
|
@ -673,10 +673,10 @@ predict_loops (struct loops *loops_info)
|
|||
else
|
||||
probability = ((REG_BR_PROB_BASE + max / 2) / max);
|
||||
|
||||
predict_edge (exits[j], PRED_LOOP_ITERATIONS, probability);
|
||||
predict_edge (ex, PRED_LOOP_ITERATIONS, probability);
|
||||
}
|
||||
}
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
|
||||
bbs = get_loop_body (loop);
|
||||
|
||||
|
|
|
@ -1976,9 +1976,6 @@ rewrite_trees (var_map map, tree *values)
|
|||
delete_elim_graph (g);
|
||||
}
|
||||
|
||||
|
||||
DEF_VEC_ALLOC_P(edge,heap);
|
||||
|
||||
/* These are the local work structures used to determine the best place to
|
||||
insert the copies that were placed on edges by the SSA->normal pass.. */
|
||||
static VEC(edge,heap) *edge_leader;
|
||||
|
|
|
@ -1016,13 +1016,12 @@ get_lsm_tmp_name (tree ref)
|
|||
/* Records request for store motion of memory reference REF from LOOP.
|
||||
MEM_REFS is the list of occurrences of the reference REF inside LOOP;
|
||||
these references are rewritten by a new temporary variable.
|
||||
Exits from the LOOP are stored in EXITS, there are N_EXITS of them.
|
||||
The initialization of the temporary variable is put to the preheader
|
||||
of the loop, and assignments to the reference from the temporary variable
|
||||
are emitted to exits. */
|
||||
Exits from the LOOP are stored in EXITS. The initialization of the
|
||||
temporary variable is put to the preheader of the loop, and assignments
|
||||
to the reference from the temporary variable are emitted to exits. */
|
||||
|
||||
static void
|
||||
schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
|
||||
schedule_sm (struct loop *loop, VEC (edge, heap) *exits, tree ref,
|
||||
struct mem_ref_loc *mem_refs)
|
||||
{
|
||||
struct mem_ref_loc *aref;
|
||||
|
@ -1030,6 +1029,7 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
|
|||
unsigned i;
|
||||
tree load, store;
|
||||
struct fmt_data fmt_data;
|
||||
edge ex;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
|
@ -1060,11 +1060,11 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
|
|||
all dependencies. */
|
||||
bsi_insert_on_edge (loop_latch_edge (loop), load);
|
||||
|
||||
for (i = 0; i < n_exits; i++)
|
||||
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
|
||||
{
|
||||
store = build2 (MODIFY_EXPR, void_type_node,
|
||||
unshare_expr (ref), tmp_var);
|
||||
bsi_insert_on_edge (exits[i], store);
|
||||
bsi_insert_on_edge (ex, store);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,12 +1072,12 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
|
|||
is true, prepare the statements that load the value of the memory reference
|
||||
to a temporary variable in the loop preheader, store it back on the loop
|
||||
exits, and replace all the references inside LOOP by this temporary variable.
|
||||
LOOP has N_EXITS stored in EXITS. CLOBBERED_VOPS is the bitmap of virtual
|
||||
EXITS is the list of exits of LOOP. CLOBBERED_VOPS is the bitmap of virtual
|
||||
operands that are clobbered by a call or accessed through multiple references
|
||||
in loop. */
|
||||
|
||||
static void
|
||||
determine_lsm_ref (struct loop *loop, edge *exits, unsigned n_exits,
|
||||
determine_lsm_ref (struct loop *loop, VEC (edge, heap) *exits,
|
||||
bitmap clobbered_vops, struct mem_ref *ref)
|
||||
{
|
||||
struct mem_ref_loc *aref;
|
||||
|
@ -1123,35 +1123,36 @@ determine_lsm_ref (struct loop *loop, edge *exits, unsigned n_exits,
|
|||
return;
|
||||
}
|
||||
|
||||
schedule_sm (loop, exits, n_exits, ref->mem, ref->locs);
|
||||
schedule_sm (loop, exits, ref->mem, ref->locs);
|
||||
}
|
||||
|
||||
/* Hoists memory references MEM_REFS out of LOOP. CLOBBERED_VOPS is the list
|
||||
of vops clobbered by call in loop or accessed by multiple memory references.
|
||||
EXITS is the list of N_EXITS exit edges of the LOOP. */
|
||||
EXITS is the list of exit edges of the LOOP. */
|
||||
|
||||
static void
|
||||
hoist_memory_references (struct loop *loop, struct mem_ref *mem_refs,
|
||||
bitmap clobbered_vops, edge *exits, unsigned n_exits)
|
||||
bitmap clobbered_vops, VEC (edge, heap) *exits)
|
||||
{
|
||||
struct mem_ref *ref;
|
||||
|
||||
for (ref = mem_refs; ref; ref = ref->next)
|
||||
determine_lsm_ref (loop, exits, n_exits, clobbered_vops, ref);
|
||||
determine_lsm_ref (loop, exits, clobbered_vops, ref);
|
||||
}
|
||||
|
||||
/* Checks whether LOOP (with N_EXITS exits stored in EXITS array) is suitable
|
||||
/* Checks whether LOOP (with exits stored in EXITS array) is suitable
|
||||
for a store motion optimization (i.e. whether we can insert statement
|
||||
on its exits). */
|
||||
|
||||
static bool
|
||||
loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED, edge *exits,
|
||||
unsigned n_exits)
|
||||
loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED,
|
||||
VEC (edge, heap) *exits)
|
||||
{
|
||||
unsigned i;
|
||||
edge ex;
|
||||
|
||||
for (i = 0; i < n_exits; i++)
|
||||
if (exits[i]->flags & EDGE_ABNORMAL)
|
||||
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
|
||||
if (ex->flags & EDGE_ABNORMAL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -1345,14 +1346,13 @@ free_mem_refs (struct mem_ref *refs)
|
|||
static void
|
||||
determine_lsm_loop (struct loop *loop)
|
||||
{
|
||||
unsigned n_exits;
|
||||
edge *exits = get_loop_exit_edges (loop, &n_exits);
|
||||
VEC (edge, heap) *exits = get_loop_exit_edges (loop);
|
||||
bitmap clobbered_vops;
|
||||
struct mem_ref *mem_refs;
|
||||
|
||||
if (!loop_suitable_for_sm (loop, exits, n_exits))
|
||||
if (!loop_suitable_for_sm (loop, exits))
|
||||
{
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1364,10 +1364,10 @@ determine_lsm_loop (struct loop *loop)
|
|||
find_more_ref_vops (mem_refs, clobbered_vops);
|
||||
|
||||
/* Hoist all suitable memory references. */
|
||||
hoist_memory_references (loop, mem_refs, clobbered_vops, exits, n_exits);
|
||||
hoist_memory_references (loop, mem_refs, clobbered_vops, exits);
|
||||
|
||||
free_mem_refs (mem_refs);
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
BITMAP_FREE (clobbered_vops);
|
||||
}
|
||||
|
||||
|
|
|
@ -1161,16 +1161,15 @@ number_of_iterations_exit (struct loop *loop, edge exit,
|
|||
tree
|
||||
find_loop_niter (struct loop *loop, edge *exit)
|
||||
{
|
||||
unsigned n_exits, i;
|
||||
edge *exits = get_loop_exit_edges (loop, &n_exits);
|
||||
unsigned i;
|
||||
VEC (edge, heap) *exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
tree niter = NULL_TREE, aniter;
|
||||
struct tree_niter_desc desc;
|
||||
|
||||
*exit = NULL;
|
||||
for (i = 0; i < n_exits; i++)
|
||||
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
|
||||
{
|
||||
ex = exits[i];
|
||||
if (!just_once_each_iteration_p (loop, ex->src))
|
||||
continue;
|
||||
|
||||
|
@ -1217,7 +1216,7 @@ find_loop_niter (struct loop *loop, edge *exit)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
|
||||
return niter ? niter : chrec_dont_know;
|
||||
}
|
||||
|
@ -1446,15 +1445,14 @@ loop_niter_by_eval (struct loop *loop, edge exit)
|
|||
tree
|
||||
find_loop_niter_by_eval (struct loop *loop, edge *exit)
|
||||
{
|
||||
unsigned n_exits, i;
|
||||
edge *exits = get_loop_exit_edges (loop, &n_exits);
|
||||
unsigned i;
|
||||
VEC (edge, heap) *exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
tree niter = NULL_TREE, aniter;
|
||||
|
||||
*exit = NULL;
|
||||
for (i = 0; i < n_exits; i++)
|
||||
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
|
||||
{
|
||||
ex = exits[i];
|
||||
if (!just_once_each_iteration_p (loop, ex->src))
|
||||
continue;
|
||||
|
||||
|
@ -1469,7 +1467,7 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit)
|
|||
niter = aniter;
|
||||
*exit = ex;
|
||||
}
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
|
||||
return niter ? niter : chrec_dont_know;
|
||||
}
|
||||
|
@ -1986,20 +1984,21 @@ infer_loop_bounds_from_undefined (struct loop *loop)
|
|||
static void
|
||||
estimate_numbers_of_iterations_loop (struct loop *loop)
|
||||
{
|
||||
edge *exits;
|
||||
VEC (edge, heap) *exits;
|
||||
tree niter, type;
|
||||
unsigned i, n_exits;
|
||||
unsigned i;
|
||||
struct tree_niter_desc niter_desc;
|
||||
edge ex;
|
||||
|
||||
/* Give up if we already have tried to compute an estimation. */
|
||||
if (loop->estimate_state != EST_NOT_COMPUTED)
|
||||
return;
|
||||
loop->estimate_state = EST_NOT_AVAILABLE;
|
||||
|
||||
exits = get_loop_exit_edges (loop, &n_exits);
|
||||
for (i = 0; i < n_exits; i++)
|
||||
exits = get_loop_exit_edges (loop);
|
||||
for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
|
||||
{
|
||||
if (!number_of_iterations_exit (loop, exits[i], &niter_desc, false))
|
||||
if (!number_of_iterations_exit (loop, ex, &niter_desc, false))
|
||||
continue;
|
||||
|
||||
niter = niter_desc.niter;
|
||||
|
@ -2010,10 +2009,10 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
|
|||
niter);
|
||||
record_estimate (loop, niter,
|
||||
niter_desc.additional_info,
|
||||
last_stmt (exits[i]->src),
|
||||
last_stmt (ex->src),
|
||||
true, true);
|
||||
}
|
||||
free (exits);
|
||||
VEC_free (edge, heap, exits);
|
||||
|
||||
infer_loop_bounds_from_undefined (loop);
|
||||
compute_estimated_nb_iterations (loop);
|
||||
|
|
|
@ -149,7 +149,6 @@ struct local_info
|
|||
opportunities as they are discovered. We keep the registered
|
||||
jump threading opportunities in this vector as edge pairs
|
||||
(original_edge, target_edge). */
|
||||
DEF_VEC_ALLOC_P(edge,heap);
|
||||
static VEC(edge,heap) *threaded_edges;
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue