tree-vrp.c (execute_vrp): Do not update current_loops.

* tree-vrp.c (execute_vrp): Do not update current_loops.
	* loop-unswitch.c (unswitch_loop): Do not use loop_split_edge_with.
	* doc/loop.texi: Remove documentation for cancelled functions.
	* tree-ssa-loop-im.c (loop_commit_inserts): Removed.
	(move_computations, determine_lsm): Use bsi_commit_edge_inserts
	instead.
	* cfgloopmanip.c (remove_bbs): Do not update loops explicitly.
	(remove_path): Ensure that in delete_basic_blocks, the loops
	are still allocated.
	(add_loop): Work on valid loop structures.
	(loopify): Modify call of add_loop.
	(mfb_update_loops): Removed.
	(create_preheader): Do not update loops explicitly.
	(force_single_succ_latches, loop_version): Do not use
	loop_split_edge_with.
	(loop_split_edge_with): Removed.
	* tree-ssa-loop-manip.c (create_iv, determine_exit_conditions):
	Do not use bsi_insert_on_edge_immediate_loop.
	(split_loop_exit_edge, tree_unroll_loop): Do not use
	loop_split_edge_with.
	(bsi_insert_on_edge_immediate_loop): Removed.
	* tree-ssa-loop-ch.c (copy_loop_headers): Use current_loops.  Do not
	use loop_split_edge_with.
	* cfghooks.c: Include cfgloop.h.
	(verify_flow_info): Verify that loop_father is filled iff current_loops
	are available.
	(redirect_edge_and_branch_force, split_block, delete_basic_block,
	split_edge, merge_blocks, make_forwarder_block, duplicate_block):
	Update cfg.
	* cfgloopanal.c (mark_irreducible_loops): Work if the function contains
	no loops.
	* modulo-sched.c (generate_prolog_epilog, canon_loop): Do not use
	loop_split_edge_with.
	(sms_schedule): Use current_loops.
	* tree-ssa-dom.c (tree_ssa_dominator_optimize): Use current_loops.
	* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Set
	current_loops.
	(rtl_loop_init, rtl_loop_done): Do not set current_loops.
	* tree-ssa-sink.c (execute_sink_code): Use current_loops.
	* ifcvt.c (if_convert): Ditto.
	* predict.c (predict_loops): Do not clear current_loops.
	(tree_estimate_probability): Use current_loops.
	(propagate_freq): Receive head of the region to propagate instead of
	loop.
	(estimate_loops_at_level): Do not use shared to_visit bitmap.
	(estimate_loops): New function.  Handle case current_loops == NULL.
	(estimate_bb_frequencies): Do not allocate tovisit.  Use
	estimate_loops.
	* tree-ssa-loop.c (current_loops): Removed.
	(tree_loop_optimizer_init): Do not return loops.
	(tree_ssa_loop_init, tree_ssa_loop_done): Do not set current_loops.
	* tree-vectorizer.c (slpeel_update_phi_nodes_for_guard1,
	slpeel_update_phi_nodes_for_guard2, slpeel_tree_peel_loop_to_edge):
	Do not update loops explicitly.
	* function.h (struct function): Add x_current_loops field.
	(current_loops): New macro.
	* tree-if-conv.c (combine_blocks): Do not update loops explicitly.
	* loop-unroll.c (split_edge_and_insert): New function.
	(unroll_loop_runtime_iterations, analyze_insns_in_loop): Do not
	use loop_split_edge_with.
	* loop-doloop.c (add_test, doloop_modify): Ditto.
	* tree-ssa-pre.c (init_pre, fini_pre): Do not set current_loops.
	* cfglayout.c (copy_bbs): Do not update loops explicitly.
	* lambda-code.c (perfect_nestify): Do not use loop_split_edge_with.
	* tree-vect-transform.c (vect_transform_loop): Do not update loops
	explicitly.
	* cfgloop.c (flow_loops_cfg_dump): Do not dump dfs_order and rc_order.
	(flow_loops_free): Do not free dfs_order and rc_order.
	(flow_loops_find): Do not set dfs_order and rc_order in loops
	structure.  Do not call loops and flow info verification.
	(add_bb_to_loop, remove_bb_from_loops): Check whether the block
	already belongs to some loop.
	* cfgloop.h (struct loops): Remove struct cfg.
	(current_loops, loop_split_edge_with): Declaration removed.
	(loop_optimizer_init, loop_optimizer_finalize): Declaration changed.
	* tree-flow.h (loop_commit_inserts, bsi_insert_on_edge_immediate_loop):
	Declaration removed.
	* Makefile.in (cfghooks.o): Add CFGLOOP_H dependency.
	* basic-block.h (split_edge_and_insert): Declare.
	* tree-cfg.c (remove_bb): Do not update loops explicitly.

From-SVN: r118931
This commit is contained in:
Zdenek Dvorak 2006-11-17 12:29:17 +01:00 committed by Zdenek Dvorak
parent 31198773e4
commit 598ec7bdbe
32 changed files with 425 additions and 419 deletions

View File

@ -1,3 +1,86 @@
2006-11-17 Zdenek Dvorak <dvorakz@suse.cz>
* tree-vrp.c (execute_vrp): Do not update current_loops.
* loop-unswitch.c (unswitch_loop): Do not use loop_split_edge_with.
* doc/loop.texi: Remove documentation for cancelled functions.
* tree-ssa-loop-im.c (loop_commit_inserts): Removed.
(move_computations, determine_lsm): Use bsi_commit_edge_inserts
instead.
* cfgloopmanip.c (remove_bbs): Do not update loops explicitly.
(remove_path): Ensure that in delete_basic_blocks, the loops
are still allocated.
(add_loop): Work on valid loop structures.
(loopify): Modify call of add_loop.
(mfb_update_loops): Removed.
(create_preheader): Do not update loops explicitly.
(force_single_succ_latches, loop_version): Do not use
loop_split_edge_with.
(loop_split_edge_with): Removed.
* tree-ssa-loop-manip.c (create_iv, determine_exit_conditions):
Do not use bsi_insert_on_edge_immediate_loop.
(split_loop_exit_edge, tree_unroll_loop): Do not use
loop_split_edge_with.
(bsi_insert_on_edge_immediate_loop): Removed.
* tree-ssa-loop-ch.c (copy_loop_headers): Use current_loops. Do not
use loop_split_edge_with.
* cfghooks.c: Include cfgloop.h.
(verify_flow_info): Verify that loop_father is filled iff current_loops
are available.
(redirect_edge_and_branch_force, split_block, delete_basic_block,
split_edge, merge_blocks, make_forwarder_block, duplicate_block):
Update cfg.
* cfgloopanal.c (mark_irreducible_loops): Work if the function contains
no loops.
* modulo-sched.c (generate_prolog_epilog, canon_loop): Do not use
loop_split_edge_with.
(sms_schedule): Use current_loops.
* tree-ssa-dom.c (tree_ssa_dominator_optimize): Use current_loops.
* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Set
current_loops.
(rtl_loop_init, rtl_loop_done): Do not set current_loops.
* tree-ssa-sink.c (execute_sink_code): Use current_loops.
* ifcvt.c (if_convert): Ditto.
* predict.c (predict_loops): Do not clear current_loops.
(tree_estimate_probability): Use current_loops.
(propagate_freq): Receive head of the region to propagate instead of
loop.
(estimate_loops_at_level): Do not use shared to_visit bitmap.
(estimate_loops): New function. Handle case current_loops == NULL.
(estimate_bb_frequencies): Do not allocate tovisit. Use
estimate_loops.
* tree-ssa-loop.c (current_loops): Removed.
(tree_loop_optimizer_init): Do not return loops.
(tree_ssa_loop_init, tree_ssa_loop_done): Do not set current_loops.
* tree-vectorizer.c (slpeel_update_phi_nodes_for_guard1,
slpeel_update_phi_nodes_for_guard2, slpeel_tree_peel_loop_to_edge):
Do not update loops explicitly.
* function.h (struct function): Add x_current_loops field.
(current_loops): New macro.
* tree-if-conv.c (combine_blocks): Do not update loops explicitly.
* loop-unroll.c (split_edge_and_insert): New function.
(unroll_loop_runtime_iterations, analyze_insns_in_loop): Do not
use loop_split_edge_with.
* loop-doloop.c (add_test, doloop_modify): Ditto.
* tree-ssa-pre.c (init_pre, fini_pre): Do not set current_loops.
* cfglayout.c (copy_bbs): Do not update loops explicitly.
* lambda-code.c (perfect_nestify): Do not use loop_split_edge_with.
* tree-vect-transform.c (vect_transform_loop): Do not update loops
explicitly.
* cfgloop.c (flow_loops_cfg_dump): Do not dump dfs_order and rc_order.
(flow_loops_free): Do not free dfs_order and rc_order.
(flow_loops_find): Do not set dfs_order and rc_order in loops
structure. Do not call loops and flow info verification.
(add_bb_to_loop, remove_bb_from_loops): Check whether the block
already belongs to some loop.
* cfgloop.h (struct loops): Remove struct cfg.
(current_loops, loop_split_edge_with): Declaration removed.
(loop_optimizer_init, loop_optimizer_finalize): Declaration changed.
* tree-flow.h (loop_commit_inserts, bsi_insert_on_edge_immediate_loop):
Declaration removed.
* Makefile.in (cfghooks.o): Add CFGLOOP_H dependency.
* basic-block.h (split_edge_and_insert): Declare.
* tree-cfg.c (remove_bb): Do not update loops explicitly.
2006-11-17 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/29801

View File

@ -2427,7 +2427,7 @@ cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
$(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \
$(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h $(HASHTAB_H)
cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h
$(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(CFGLOOP_H)
cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \
coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \

View File

@ -486,6 +486,7 @@ extern void update_bb_for_insn (basic_block);
extern void free_basic_block_vars (void);
extern void insert_insn_on_edge (rtx, edge);
basic_block split_edge_and_insert (edge, rtx);
extern void commit_edge_insertions (void);
extern void commit_edge_insertions_watch_calls (void);

View File

@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA. */
#include "tree-flow.h"
#include "timevar.h"
#include "toplev.h"
#include "cfgloop.h"
/* A pointer to one of the hooks containers. */
static struct cfg_hooks *cfg_hooks;
@ -115,6 +116,18 @@ verify_flow_info (void)
edge e;
edge_iterator ei;
if (bb->loop_father != NULL && current_loops == NULL)
{
error ("verify_flow_info: Block %i has loop_father, but there are no loops",
bb->index);
err = 1;
}
if (bb->loop_father == NULL && current_loops != NULL)
{
error ("verify_flow_info: Block %i lacks loop_father", bb->index);
err = 1;
}
if (bb->count < 0)
{
error ("verify_flow_info: Wrong count of block %i %i",
@ -308,12 +321,19 @@ basic_block
redirect_edge_and_branch_force (edge e, basic_block dest)
{
basic_block ret;
struct loop *loop;
if (!cfg_hooks->redirect_edge_and_branch_force)
internal_error ("%s does not support redirect_edge_and_branch_force",
cfg_hooks->name);
ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
if (current_loops != NULL && ret != NULL)
{
loop = find_common_loop (single_pred (ret)->loop_father,
single_succ (ret)->loop_father);
add_bb_to_loop (ret, loop);
}
return ret;
}
@ -344,6 +364,9 @@ split_block (basic_block bb, void *i)
set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
}
if (current_loops != NULL)
add_bb_to_loop (new_bb, bb->loop_father);
return make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
}
@ -381,6 +404,22 @@ delete_basic_block (basic_block bb)
cfg_hooks->delete_basic_block (bb);
if (current_loops != NULL)
{
struct loop *loop = bb->loop_father;
/* If we remove the header or the latch of a loop, mark the loop for
removal by setting its header and latch to NULL. */
if (loop->latch == bb
|| loop->header == bb)
{
loop->header = NULL;
loop->latch = NULL;
}
remove_bb_from_loops (bb);
}
/* Remove the edges into and out of this block. Note that there may
indeed be edges in, if we are removing an unreachable loop. */
while (EDGE_COUNT (bb->preds) != 0)
@ -407,6 +446,8 @@ split_edge (edge e)
int freq = EDGE_FREQUENCY (e);
edge f;
bool irr = (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
struct loop *loop;
basic_block src = e->src, dest = e->dest;
if (!cfg_hooks->split_edge)
internal_error ("%s does not support split_edge", cfg_hooks->name);
@ -455,7 +496,16 @@ split_edge (edge e)
if (!f)
set_immediate_dominator (CDI_DOMINATORS, single_succ (ret), ret);
}
};
}
if (current_loops != NULL)
{
loop = find_common_loop (src->loop_father, dest->loop_father);
add_bb_to_loop (ret, loop);
if (loop->latch == src)
loop->latch = ret;
}
return ret;
}
@ -534,6 +584,9 @@ merge_blocks (basic_block a, basic_block b)
if (!cfg_hooks->merge_blocks)
internal_error ("%s does not support merge_blocks", cfg_hooks->name);
if (current_loops != NULL)
remove_bb_from_loops (b);
cfg_hooks->merge_blocks (a, b);
/* Normally there should only be one successor of A and that is B, but
@ -575,6 +628,7 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
edge e, fallthru;
edge_iterator ei;
basic_block dummy, jump;
struct loop *loop, *ploop, *cloop;
if (!cfg_hooks->make_forwarder_block)
internal_error ("%s does not support make_forwarder_block",
@ -617,6 +671,33 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, 2);
}
if (current_loops != NULL)
{
/* If we do not split a loop header, then both blocks belong to the
same loop. In case we split loop header and do not redirect the
latch edge to DUMMY, then DUMMY belongs to the outer loop, and
BB becomes the new header. */
loop = dummy->loop_father;
if (loop->header == dummy
&& find_edge (loop->latch, dummy) == NULL)
{
remove_bb_from_loops (dummy);
loop->header = bb;
cloop = loop;
FOR_EACH_EDGE (e, ei, dummy->preds)
{
cloop = find_common_loop (cloop, e->src->loop_father);
}
add_bb_to_loop (dummy, cloop);
}
/* In case we split loop latch, update it. */
for (ploop = loop; ploop; ploop = ploop->outer)
if (ploop->latch == dummy)
ploop->latch = bb;
}
cfg_hooks->make_forwarder_block (fallthru);
return fallthru;
@ -768,6 +849,10 @@ duplicate_block (basic_block bb, edge e, basic_block after)
set_bb_original (new_bb, bb);
set_bb_copy (bb, new_bb);
/* Add the new block to the prescribed loop. */
if (current_loops != NULL)
add_bb_to_loop (new_bb, bb->loop_father->copy);
return new_bb;
}

View File

@ -1230,9 +1230,7 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
after = new_bb;
bb->flags |= BB_DUPLICATED;
/* Add to loop. */
add_bb_to_loop (new_bb, bb->loop_father->copy);
/* Possibly set header. */
/* Possibly set loop header. */
if (bb->loop_father->header == bb && bb->loop_father != base)
new_bb->loop_father->header = new_bb;
/* Or latch. */

View File

@ -52,7 +52,6 @@ static bool glb_enum_p (basic_block, void *);
static void
flow_loops_cfg_dump (const struct loops *loops, FILE *file)
{
int i;
basic_block bb;
if (! loops->num || ! file)
@ -68,26 +67,6 @@ flow_loops_cfg_dump (const struct loops *loops, FILE *file)
fprintf (file, "%d ", succ->dest->index);
fprintf (file, "}\n");
}
/* Dump the DFS node order. */
if (loops->cfg.dfs_order)
{
fputs (";; DFS order: ", file);
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.dfs_order[i]);
fputs ("\n", file);
}
/* Dump the reverse completion node order. */
if (loops->cfg.rc_order)
{
fputs (";; RC order: ", file);
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.rc_order[i]);
fputs ("\n", file);
}
}
/* Return nonzero if the nodes of LOOP are a subset of OUTER. */
@ -208,12 +187,6 @@ flow_loops_free (struct loops *loops)
free (loops->parray);
loops->parray = NULL;
if (loops->cfg.dfs_order)
free (loops->cfg.dfs_order);
if (loops->cfg.rc_order)
free (loops->cfg.rc_order);
}
}
@ -697,10 +670,6 @@ flow_loops_find (struct loops *loops)
rc_order = XNEWVEC (int, n_basic_blocks);
pre_and_rev_post_order_compute (dfs_order, rc_order, false);
/* Save CFG derived information to avoid recomputing it. */
loops->cfg.dfs_order = dfs_order;
loops->cfg.rc_order = rc_order;
num_loops = 1;
for (b = 0; b < n_basic_blocks - NUM_FIXED_BLOCKS; b++)
@ -744,16 +713,14 @@ flow_loops_find (struct loops *loops)
loops->num = num_loops;
initialize_loops_parallel_p (loops);
free (dfs_order);
free (rc_order);
}
sbitmap_free (headers);
loops->state = 0;
#ifdef ENABLE_CHECKING
verify_flow_info ();
verify_loop_structure (loops);
#endif
return loops->num;
}
@ -969,12 +936,13 @@ add_bb_to_loop (basic_block bb, struct loop *loop)
{
int i;
gcc_assert (bb->loop_father == NULL);
bb->loop_father = loop;
bb->loop_depth = loop->depth;
loop->num_nodes++;
for (i = 0; i < loop->depth; i++)
loop->pred[i]->num_nodes++;
}
}
/* Remove basic block BB from loops. */
void
@ -983,6 +951,7 @@ remove_bb_from_loops (basic_block bb)
int i;
struct loop *loop = bb->loop_father;
gcc_assert (loop != NULL);
loop->num_nodes--;
for (i = 0; i < loop->depth; i++)
loop->pred[i]->num_nodes--;

View File

@ -187,25 +187,10 @@ struct loops
/* Pointer to root of loop hierarchy tree. */
struct loop *tree_root;
/* Information derived from the CFG. */
struct cfg
{
/* The ordering of the basic blocks in a depth first search. */
int *dfs_order;
/* The reverse completion ordering of the basic blocks found in a
depth first search. */
int *rc_order;
} cfg;
/* Headers shared by multiple loops that should be merged. */
sbitmap shared_headers;
};
/* The loop tree currently optimized. */
extern struct loops *current_loops;
/* Loop recognition. */
extern int flow_loops_find (struct loops *);
extern void flow_loops_free (struct loops *);
@ -248,7 +233,6 @@ extern void remove_bb_from_loops (basic_block);
extern void cancel_loop_tree (struct loops *, struct loop *);
extern basic_block loop_split_edge_with (edge, rtx);
extern int fix_loop_placement (struct loop *);
enum
@ -410,8 +394,8 @@ extern unsigned global_cost_for_size (unsigned, unsigned, unsigned);
extern void init_set_costs (void);
/* Loop optimizer initialization. */
extern struct loops *loop_optimizer_init (unsigned);
extern void loop_optimizer_finalize (struct loops *);
extern void loop_optimizer_init (unsigned);
extern void loop_optimizer_finalize (void);
/* Optimization passes. */
extern void unswitch_loops (struct loops *);
@ -419,8 +403,8 @@ extern void unswitch_loops (struct loops *);
enum
{
UAP_PEEL = 1, /* Enables loop peeling. */
UAP_UNROLL = 2, /* Enables peeling of loops if it seems profitable. */
UAP_UNROLL_ALL = 4 /* Enables peeling of all loops. */
UAP_UNROLL = 2, /* Enables unrolling of loops if it seems profitable. */
UAP_UNROLL_ALL = 4 /* Enables unrolling of all loops. */
};
extern void unroll_and_peel_loops (struct loops *, int);

View File

@ -273,8 +273,9 @@ mark_irreducible_loops (struct loops *loops)
edge_iterator ei;
int i, src, dest;
struct graph *g;
int *queue1 = XNEWVEC (int, last_basic_block + loops->num);
int *queue2 = XNEWVEC (int, last_basic_block + loops->num);
int num = loops ? loops->num : 1;
int *queue1 = XNEWVEC (int, last_basic_block + num);
int *queue2 = XNEWVEC (int, last_basic_block + num);
int nq, depth;
struct loop *cloop;
@ -287,7 +288,7 @@ mark_irreducible_loops (struct loops *loops)
}
/* Create the edge lists. */
g = new_graph (last_basic_block + loops->num);
g = new_graph (last_basic_block + num);
FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
FOR_EACH_EDGE (e, ei, act->succs)
@ -296,35 +297,38 @@ mark_irreducible_loops (struct loops *loops)
if (e->dest == EXIT_BLOCK_PTR)
continue;
/* And latch edges. */
if (e->dest->loop_father->header == e->dest
&& e->dest->loop_father->latch == act)
continue;
/* Edges inside a single loop should be left where they are. Edges
to subloop headers should lead to representative of the subloop,
but from the same place.
Edges exiting loops should lead from representative
of the son of nearest common ancestor of the loops in that
act lays. */
src = BB_REPR (act);
dest = BB_REPR (e->dest);
if (e->dest->loop_father->header == e->dest)
dest = LOOP_REPR (e->dest->loop_father);
if (!flow_bb_inside_loop_p (act->loop_father, e->dest))
if (loops)
{
depth = find_common_loop (act->loop_father,
e->dest->loop_father)->depth + 1;
if (depth == act->loop_father->depth)
cloop = act->loop_father;
else
cloop = act->loop_father->pred[depth];
/* Ignore latch edges. */
if (e->dest->loop_father->header == e->dest
&& e->dest->loop_father->latch == act)
continue;
src = LOOP_REPR (cloop);
/* Edges inside a single loop should be left where they are. Edges
to subloop headers should lead to representative of the subloop,
but from the same place.
Edges exiting loops should lead from representative
of the son of nearest common ancestor of the loops in that
act lays. */
if (e->dest->loop_father->header == e->dest)
dest = LOOP_REPR (e->dest->loop_father);
if (!flow_bb_inside_loop_p (act->loop_father, e->dest))
{
depth = find_common_loop (act->loop_father,
e->dest->loop_father)->depth + 1;
if (depth == act->loop_father->depth)
cloop = act->loop_father;
else
cloop = act->loop_father->pred[depth];
src = LOOP_REPR (cloop);
}
}
add_edge (g, src, dest, e);
@ -339,7 +343,7 @@ mark_irreducible_loops (struct loops *loops)
{
queue1[nq++] = BB_REPR (act);
}
for (i = 1; i < (int) loops->num; i++)
for (i = 1; i < num; i++)
if (loops->parray[i])
queue1[nq++] = LOOP_REPR (loops->parray[i]);
dfs (g, queue1, nq, queue2, false);
@ -354,7 +358,8 @@ mark_irreducible_loops (struct loops *loops)
free (queue1);
free (queue2);
loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
if (loops)
loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
}
/* Counts number of insns inside LOOP. */

View File

@ -40,7 +40,6 @@ static void remove_bbs (basic_block *, int);
static bool rpe_enum_p (basic_block, void *);
static int find_path (edge, basic_block **);
static bool alp_enum_p (basic_block, void *);
static void add_loop (struct loops *, struct loop *);
static void fix_loop_placements (struct loops *, struct loop *, bool *);
static bool fix_bb_placement (struct loops *, basic_block);
static void fix_bb_placements (struct loops *, basic_block, bool *);
@ -58,18 +57,15 @@ rpe_enum_p (basic_block bb, void *data)
return dominated_by_p (CDI_DOMINATORS, bb, data);
}
/* Remove basic blocks BBS from loop structure and dominance info,
and delete them afterwards. */
/* Remove basic blocks BBS. NBBS is the number of the basic blocks. */
static void
remove_bbs (basic_block *bbs, int nbbs)
{
int i;
for (i = 0; i < nbbs; i++)
{
remove_bb_from_loops (bbs[i]);
delete_basic_block (bbs[i]);
}
delete_basic_block (bbs[i]);
}
/* Find path -- i.e. the basic blocks dominated by edge E and put them
@ -247,9 +243,10 @@ remove_path (struct loops *loops, edge e)
{
edge ae;
basic_block *rem_bbs, *bord_bbs, *dom_bbs, from, bb;
int i, nrem, n_bord_bbs, n_dom_bbs;
int i, nrem, n_bord_bbs, n_dom_bbs, nreml;
sbitmap seen;
bool deleted, irred_invalidated = false;
struct loop **deleted_loop;
if (!loop_delete_branch_edge (e, 0))
return false;
@ -267,7 +264,7 @@ remove_path (struct loops *loops, edge e)
fix -- when e->dest has exactly one predecessor, this corresponds
to blocks dominated by e->dest, if not, split the edge. */
if (!single_pred_p (e->dest))
e = single_pred_edge (loop_split_edge_with (e, NULL_RTX));
e = single_pred_edge (split_edge (e));
/* It may happen that by removing path we remove one or more loops
we belong to. In this case first unloop the loops, then proceed
@ -311,13 +308,19 @@ remove_path (struct loops *loops, edge e)
dom_bbs = XCNEWVEC (basic_block, n_basic_blocks);
/* Cancel loops contained in the path. */
deleted_loop = XNEWVEC (struct loop *, nrem);
nreml = 0;
for (i = 0; i < nrem; i++)
if (rem_bbs[i]->loop_father->header == rem_bbs[i])
cancel_loop_tree (loops, rem_bbs[i]->loop_father);
deleted_loop[nreml++] = rem_bbs[i]->loop_father;
remove_bbs (rem_bbs, nrem);
free (rem_bbs);
for (i = 0; i < nreml; i++)
cancel_loop_tree (loops, deleted_loop[i]);
free (deleted_loop);
/* Find blocks whose dominators may be affected. */
n_dom_bbs = 0;
sbitmap_zero (seen);
@ -364,15 +367,18 @@ alp_enum_p (basic_block bb, void *alp_header)
}
/* Given LOOP structure with filled header and latch, find the body of the
corresponding loop and add it to LOOPS tree. */
corresponding loop and add it to LOOPS tree. Insert the LOOP as a son of
outer. */
static void
add_loop (struct loops *loops, struct loop *loop)
add_loop (struct loops *loops, struct loop *loop, struct loop *outer)
{
basic_block *bbs;
int i, n;
/* Add it to loop structure. */
place_new_loop (loops, loop);
flow_loop_tree_node_add (outer, loop);
loop->level = 1;
/* Find its nodes. */
@ -381,7 +387,11 @@ add_loop (struct loops *loops, struct loop *loop)
bbs, n_basic_blocks, loop->header);
for (i = 0; i < n; i++)
add_bb_to_loop (bbs[i], loop);
{
remove_bb_from_loops (bbs[i]);
add_bb_to_loop (bbs[i], loop);
}
remove_bb_from_loops (loop->header);
add_bb_to_loop (loop->header, loop);
free (bbs);
@ -453,10 +463,11 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge,
set_immediate_dominator (CDI_DOMINATORS, succ_bb, switch_bb);
/* Compute new loop. */
add_loop (loops, loop);
flow_loop_tree_node_add (outer, loop);
add_loop (loops, loop, outer);
/* Add switch_bb to appropriate loop. */
if (switch_bb->loop_father)
remove_bb_from_loops (switch_bb);
add_bb_to_loop (switch_bb, outer);
/* Fix frequencies. */
@ -1111,21 +1122,6 @@ mfb_keep_just (edge e)
return e != mfb_kj_edge;
}
/* A callback for make_forwarder block, to update data structures for a basic
block JUMP created by redirecting an edge (only the latch edge is being
redirected). */
static void
mfb_update_loops (basic_block jump)
{
struct loop *loop = single_succ (jump)->loop_father;
if (dom_computed[CDI_DOMINATORS])
set_immediate_dominator (CDI_DOMINATORS, jump, single_pred (jump));
add_bb_to_loop (jump, loop);
loop->latch = jump;
}
/* Creates a pre-header for a LOOP. Returns newly created block. Unless
CP_SIMPLE_PREHEADERS is set in FLAGS, we only force LOOP to have single
entry; otherwise we also force preheader block to have only one successor.
@ -1136,15 +1132,12 @@ create_preheader (struct loop *loop, int flags)
{
edge e, fallthru;
basic_block dummy;
struct loop *cloop, *ploop;
int nentry = 0;
bool irred = false;
bool latch_edge_was_fallthru;
edge one_succ_pred = 0;
edge_iterator ei;
cloop = loop->outer;
FOR_EACH_EDGE (e, ei, loop->header->preds)
{
if (e->src == loop->latch)
@ -1168,17 +1161,10 @@ create_preheader (struct loop *loop, int flags)
mfb_kj_edge = loop_latch_edge (loop);
latch_edge_was_fallthru = (mfb_kj_edge->flags & EDGE_FALLTHRU) != 0;
fallthru = make_forwarder_block (loop->header, mfb_keep_just,
mfb_update_loops);
fallthru = make_forwarder_block (loop->header, mfb_keep_just, NULL);
dummy = fallthru->src;
loop->header = fallthru->dest;
/* The header could be a latch of some superloop(s); due to design of
split_block, it would now move to fallthru->dest. */
for (ploop = loop; ploop; ploop = ploop->outer)
if (ploop->latch == dummy)
ploop->latch = fallthru->dest;
/* Try to be clever in placing the newly created preheader. The idea is to
avoid breaking any "fallthruness" relationship between blocks.
@ -1197,9 +1183,6 @@ create_preheader (struct loop *loop, int flags)
move_block_after (dummy, e->src);
}
loop->header->loop_father = loop;
add_bb_to_loop (dummy, cloop);
if (irred)
{
dummy->flags |= BB_IRREDUCIBLE_LOOP;
@ -1241,41 +1224,11 @@ force_single_succ_latches (struct loops *loops)
e = find_edge (loop->latch, loop->header);
loop_split_edge_with (e, NULL_RTX);
split_edge (e);
}
loops->state |= LOOPS_HAVE_SIMPLE_LATCHES;
}
/* A quite stupid function to put INSNS on edge E. They are supposed to form
just one basic block. Jumps in INSNS are not handled, so cfg do not have to
be ok after this function. The created block is placed on correct place
in LOOPS structure and its dominator is set. */
basic_block
loop_split_edge_with (edge e, rtx insns)
{
basic_block src, dest, new_bb;
struct loop *loop_c;
src = e->src;
dest = e->dest;
loop_c = find_common_loop (src->loop_father, dest->loop_father);
/* Create basic block for it. */
new_bb = split_edge (e);
add_bb_to_loop (new_bb, loop_c);
new_bb->flags |= (insns ? BB_SUPERBLOCK : 0);
if (insns)
emit_insn_after (insns, BB_END (new_bb));
if (dest->loop_father->latch == src)
dest->loop_father->latch = new_bb;
return new_bb;
}
/* This function is called from loop_version. It splits the entry edge
of the loop we want to version, adds the versioning condition, and
adjust the edges to the two versions of the loop appropriately.
@ -1424,8 +1377,8 @@ loop_version (struct loops *loops, struct loop * loop,
/* At this point condition_bb is loop predheader with two successors,
first_head and second_head. Make sure that loop predheader has only
one successor. */
loop_split_edge_with (loop_preheader_edge (loop), NULL);
loop_split_edge_with (loop_preheader_edge (nloop), NULL);
split_edge (loop_preheader_edge (loop));
split_edge (loop_preheader_edge (nloop));
return nloop;
}

View File

@ -195,19 +195,11 @@ The loops tree can be manipulated using the following functions:
@item @code{remove_bb_from_loops}: Removes a basic block from loops.
@end itemize
The specialized versions of several low-level CFG functions that also
update loop structures are provided:
Most low-level CFG functions update loops automatically. The following
functions handle some more complicated cases of CFG manipulations:
@itemize
@item @code{loop_split_edge_with}: Splits an edge, and places a
specified RTL code on it. On GIMPLE, the function can still be used,
but the code must be NULL.
@item @code{bsi_insert_on_edge_immediate_loop}: Inserts code on edge,
splitting it if necessary. Only works on GIMPLE.
@item @code{remove_path}: Removes an edge and all blocks it dominates.
@item @code{loop_commit_inserts}: Commits insertions scheduled on edges,
and sets loops for the new blocks. This function can only be used on
GIMPLE.
@item @code{split_loop_exit_edge}: Splits exit edge of the loop,
ensuring that PHI node arguments remain in the loop (this ensures that
loop-closed SSA form is preserved). Only useful on GIMPLE.

View File

@ -189,6 +189,9 @@ struct function GTY(())
/* The control flow graph for this function. */
struct control_flow_graph *cfg;
/* The loops in this function. */
struct loops * GTY((skip)) x_current_loops;
/* For function.c. */
/* Points to the FUNCTION_DECL of this function. */
@ -520,6 +523,7 @@ extern int trampolines_created;
#define avail_temp_slots (cfun->x_avail_temp_slots)
#define temp_slot_level (cfun->x_temp_slot_level)
#define nonlocal_goto_handler_labels (cfun->x_nonlocal_goto_handler_labels)
#define current_loops (cfun->x_current_loops)
/* Given a function decl for a containing function,
return the `struct function' for it. */

View File

@ -3854,11 +3854,12 @@ if_convert (int x_life_data_ok)
&& (!flag_reorder_blocks_and_partition || !no_new_pseudos
|| !targetm.have_named_sections))
{
struct loops loops;
flow_loops_find (&loops);
mark_loop_exit_edges (&loops);
flow_loops_free (&loops);
loop_optimizer_init (0);
if (current_loops)
{
mark_loop_exit_edges (current_loops);
loop_optimizer_finalize ();
}
free_dominance_info (CDI_DOMINATORS);
}

View File

@ -2464,7 +2464,7 @@ perfect_nestify (struct loops *loops,
/* Create the new loop. */
olddest = loop->single_exit->dest;
preheaderbb = loop_split_edge_with (loop->single_exit, NULL);
preheaderbb = split_edge (loop->single_exit);
headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
/* Push the exit phi nodes that we are moving. */

View File

@ -257,7 +257,7 @@ add_test (rtx cond, edge *e, basic_block dest)
seq = get_insns ();
end_sequence ();
bb = loop_split_edge_with (*e, seq);
bb = split_edge_and_insert (*e, seq);
*e = single_succ_edge (bb);
if (any_uncondjump_p (jump))
@ -372,9 +372,9 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
rtx ass = copy_rtx (desc->noloop_assumptions);
basic_block preheader = loop_preheader_edge (loop)->src;
basic_block set_zero
= loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
= split_edge (loop_preheader_edge (loop));
basic_block new_preheader
= loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
= split_edge (loop_preheader_edge (loop));
edge te;
/* Expand the condition testing the assumptions and if it does not pass,
@ -406,7 +406,6 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
{
/* All the conditions were simplified to false, remove the
unreachable set_zero block. */
remove_bb_from_loops (set_zero);
delete_basic_block (set_zero);
}
else

View File

@ -33,17 +33,17 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "flags.h"
/* Initialize loop optimizer. This is used by the tree and RTL loop
/* Initialize loop structures. This is used by the tree and RTL loop
optimizers. FLAGS specify what properties to compute and/or ensure for
loops. */
struct loops *
void
loop_optimizer_init (unsigned flags)
{
struct loops *loops = XCNEW (struct loops);
edge e;
edge_iterator ei;
static bool first_time = true;
struct loops *loops;
if (first_time)
{
@ -51,6 +51,9 @@ loop_optimizer_init (unsigned flags)
init_set_costs ();
}
gcc_assert (!current_loops);
loops = XCNEW (struct loops);
/* Avoid annoying special cases of edges going to exit
block. */
@ -62,63 +65,64 @@ loop_optimizer_init (unsigned flags)
/* Find the loops. */
if (flow_loops_find (loops) <= 1)
flow_loops_find (loops);
current_loops = loops;
if (current_loops->num <= 1)
{
/* No loops. */
flow_loops_free (loops);
free (loops);
return NULL;
loop_optimizer_finalize ();
return;
}
/* Not going to update these. */
free (loops->cfg.rc_order);
loops->cfg.rc_order = NULL;
free (loops->cfg.dfs_order);
loops->cfg.dfs_order = NULL;
/* Create pre-headers. */
if (flags & LOOPS_HAVE_PREHEADERS)
create_preheaders (loops, CP_SIMPLE_PREHEADERS);
create_preheaders (current_loops, CP_SIMPLE_PREHEADERS);
/* Force all latches to have only single successor. */
if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
force_single_succ_latches (loops);
force_single_succ_latches (current_loops);
/* Mark irreducible loops. */
if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
mark_irreducible_loops (loops);
mark_irreducible_loops (current_loops);
if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
mark_single_exit_loops (loops);
mark_single_exit_loops (current_loops);
/* Dump loops. */
flow_loops_dump (loops, dump_file, NULL, 1);
flow_loops_dump (current_loops, dump_file, NULL, 1);
#ifdef ENABLE_CHECKING
verify_dominators (CDI_DOMINATORS);
verify_loop_structure (loops);
verify_loop_structure (current_loops);
#endif
return loops;
}
/* Finalize loop optimizer. */
/* Finalize loop structures. */
void
loop_optimizer_finalize (struct loops *loops)
loop_optimizer_finalize (void)
{
unsigned i;
basic_block bb;
if (!loops)
if (!current_loops)
return;
for (i = 1; i < loops->num; i++)
if (loops->parray[i])
free_simple_loop_desc (loops->parray[i]);
for (i = 1; i < current_loops->num; i++)
if (current_loops->parray[i])
free_simple_loop_desc (current_loops->parray[i]);
/* Clean up. */
flow_loops_free (loops);
free (loops);
flow_loops_free (current_loops);
free (current_loops);
current_loops = NULL;
FOR_ALL_BB (bb)
{
bb->loop_father = NULL;
}
/* Checking. */
#ifdef ENABLE_CHECKING
@ -173,7 +177,7 @@ rtl_loop_init (void)
/* Initialize structures for layout changes. */
cfg_layout_initialize (0);
current_loops = loop_optimizer_init (LOOPS_NORMAL);
loop_optimizer_init (LOOPS_NORMAL);
return 0;
}
@ -196,14 +200,13 @@ struct tree_opt_pass pass_rtl_loop_init =
/* Finalization of the RTL loop passes. */
static unsigned int
rtl_loop_done (void)
{
basic_block bb;
if (current_loops)
loop_optimizer_finalize (current_loops);
loop_optimizer_finalize ();
free_dominance_info (CDI_DOMINATORS);
/* Finalize layout changes. */
@ -218,7 +221,6 @@ rtl_loop_done (void)
if (dump_file)
dump_flow_info (dump_file, dump_flags);
current_loops = NULL;
return 0;
}

View File

@ -899,6 +899,18 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
loop->lpt_decision.times);
}
/* Splits edge E and inserts INSNS on it. */
basic_block
split_edge_and_insert (edge e, rtx insns)
{
basic_block bb = split_edge (e);
gcc_assert (insns != NULL_RTX);
emit_insn_after (insns, BB_END (bb));
bb->flags |= BB_SUPERBLOCK;
return bb;
}
/* Unroll LOOP for that we are able to count number of iterations in runtime
LOOP->LPT_DECISION.TIMES + 1 times. The transformation does this (with some
extra care for case n < 0):
@ -1009,7 +1021,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop)
end_sequence ();
/* Precondition the loop. */
loop_split_edge_with (loop_preheader_edge (loop), init_code);
split_edge_and_insert (loop_preheader_edge (loop), init_code);
remove_edges = XCNEWVEC (edge, max_unroll + n_peel + 1);
n_remove_edges = 0;
@ -1033,8 +1045,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop)
gcc_assert (ok);
/* Record the place where switch will be built for preconditioning. */
swtch = loop_split_edge_with (loop_preheader_edge (loop),
NULL_RTX);
swtch = split_edge (loop_preheader_edge (loop));
for (i = 0; i < n_peel; i++)
{
@ -1053,12 +1064,12 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop)
j = n_peel - i - (extra_zero_check ? 0 : 1);
p = REG_BR_PROB_BASE / (i + 2);
preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
preheader = split_edge (loop_preheader_edge (loop));
branch_code = compare_and_jump_seq (copy_rtx (niter), GEN_INT (j), EQ,
block_label (preheader), p,
NULL_RTX);
swtch = loop_split_edge_with (single_pred_edge (swtch), branch_code);
swtch = split_edge_and_insert (single_pred_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
single_pred_edge (swtch)->probability = REG_BR_PROB_BASE - p;
e = make_edge (swtch, preheader,
@ -1071,12 +1082,12 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop)
/* Add branch for zero iterations. */
p = REG_BR_PROB_BASE / (max_unroll + 1);
swtch = ezc_swtch;
preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
preheader = split_edge (loop_preheader_edge (loop));
branch_code = compare_and_jump_seq (copy_rtx (niter), const0_rtx, EQ,
block_label (preheader), p,
NULL_RTX);
swtch = loop_split_edge_with (single_succ_edge (swtch), branch_code);
swtch = split_edge_and_insert (single_succ_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
e = make_edge (swtch, preheader,
@ -1717,18 +1728,12 @@ analyze_insns_in_loop (struct loop *loop)
si_info_hash, si_info_eq, free);
/* Record the loop exit bb and loop preheader before the unrolling. */
if (!loop_preheader_edge (loop)->src)
{
loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
opt_info->loop_preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
}
else
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
if (num_edges == 1
&& !(edges[0]->flags & EDGE_COMPLEX))
{
opt_info->loop_exit = loop_split_edge_with (edges[0], NULL_RTX);
opt_info->loop_exit = split_edge (edges[0]);
can_apply = true;
}

View File

@ -480,8 +480,8 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on,
fix_loop_placement (nloop);
/* Preserve the simple loop preheaders. */
loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX);
loop_split_edge_with (loop_preheader_edge (nloop), NULL_RTX);
split_edge (loop_preheader_edge (loop));
split_edge (loop_preheader_edge (nloop));
return nloop;
}

View File

@ -742,9 +742,9 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop * loop, rtx count_r
for (i = 0; i < last_stage; i++)
duplicate_insns_of_cycles (ps, 0, i, 1);
/* Put the prolog , on the one and only entry edge. */
/* Put the prolog on the entry edge. */
e = loop_preheader_edge (loop);
loop_split_edge_with(e , get_insns());
split_edge_and_insert (e, get_insns());
end_sequence ();
@ -754,10 +754,10 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop * loop, rtx count_r
for (i = 0; i < last_stage; i++)
duplicate_insns_of_cycles (ps, i + 1, last_stage, 0);
/* Put the epilogue on the one and only one exit edge. */
/* Put the epilogue on the exit edge. */
gcc_assert (loop->single_exit);
e = loop->single_exit;
loop_split_edge_with(e , get_insns());
split_edge_and_insert (e, get_insns());
end_sequence ();
}
@ -848,7 +848,7 @@ canon_loop (struct loop *loop)
block. */
FOR_EACH_EDGE (e, i, EXIT_BLOCK_PTR->preds)
if ((e->flags & EDGE_FALLTHRU) && (EDGE_COUNT (e->src->succs) > 1))
loop_split_edge_with (e, NULL_RTX);
split_edge (e);
if (loop->latch == loop->header
|| EDGE_COUNT (loop->latch->succs) > 1)
@ -856,7 +856,7 @@ canon_loop (struct loop *loop)
FOR_EACH_EDGE (e, i, loop->header->preds)
if (e->src == loop->latch)
break;
loop_split_edge_with (e, NULL_RTX);
split_edge (e);
}
}
@ -873,7 +873,6 @@ sms_schedule (void)
unsigned i,num_loops;
partial_schedule_ptr ps;
struct df *df;
struct loops *loops;
basic_block bb = NULL;
/* vars to the versioning only if needed*/
struct loop * nloop;
@ -881,10 +880,10 @@ sms_schedule (void)
edge latch_edge;
gcov_type trip_count = 0;
loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_MARKED_SINGLE_EXITS);
if (!loops)
return; /* There is no loops to schedule. */
loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_MARKED_SINGLE_EXITS);
if (!current_loops)
return; /* There are no loops to schedule. */
/* Initialize issue_rate. */
if (targetm.sched.issue_rate)
@ -914,16 +913,16 @@ sms_schedule (void)
/* Allocate memory to hold the DDG array one entry for each loop.
We use loop->num as index into this array. */
g_arr = XCNEWVEC (ddg_ptr, loops->num);
g_arr = XCNEWVEC (ddg_ptr, current_loops->num);
/* Build DDGs for all the relevant loops and hold them in G_ARR
indexed by the loop index. */
for (i = 0; i < loops->num; i++)
for (i = 0; i < current_loops->num; i++)
{
rtx head, tail;
rtx count_reg;
struct loop *loop = loops->parray[i];
struct loop *loop = current_loops->parray[i];
/* For debugging. */
if ((passes++ > MAX_SMS_LOOP_NUMBER) && (MAX_SMS_LOOP_NUMBER != -1))
@ -1018,7 +1017,7 @@ sms_schedule (void)
df = NULL;
/* We don't want to perform SMS on new loops - created by versioning. */
num_loops = loops->num;
num_loops = current_loops->num;
/* Go over the built DDGs and perfrom SMS for each one of them. */
for (i = 0; i < num_loops; i++)
{
@ -1027,7 +1026,7 @@ sms_schedule (void)
int mii, rec_mii;
unsigned stage_count = 0;
HOST_WIDEST_INT loop_count = 0;
struct loop *loop = loops->parray[i];
struct loop *loop = current_loops->parray[i];
if (! (g = g_arr[i]))
continue;
@ -1177,8 +1176,8 @@ sms_schedule (void)
rtx comp_rtx = gen_rtx_fmt_ee (GT, VOIDmode, count_reg,
GEN_INT(stage_count));
nloop = loop_version (loops, loop, comp_rtx, &condition_bb,
true);
nloop = loop_version (current_loops, loop, comp_rtx,
&condition_bb, true);
}
/* Set new iteration count of loop kernel. */
@ -1218,7 +1217,7 @@ sms_schedule (void)
/* Release scheduler data, needed until now because of DFA. */
sched_finish ();
loop_optimizer_finalize (loops);
loop_optimizer_finalize ();
}
/* The SMS scheduling algorithm itself

View File

@ -74,8 +74,6 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
static void combine_predictions_for_insn (rtx, basic_block);
static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
static void estimate_loops_at_level (struct loop *, bitmap);
static void propagate_freq (struct loop *, bitmap);
static void estimate_bb_frequencies (struct loops *);
static void predict_paths_leading_to (basic_block, int *, enum br_predictor, enum prediction);
static bool last_basic_block_p (basic_block);
@ -744,7 +742,6 @@ predict_loops (struct loops *loops_info)
}
scev_finalize ();
current_loops = NULL;
}
/* Attempt to predict probabilities of BB outgoing edges using local
@ -1252,11 +1249,10 @@ static unsigned int
tree_estimate_probability (void)
{
basic_block bb;
struct loops loops_info;
flow_loops_find (&loops_info);
loop_optimizer_init (0);
if (dump_file && (dump_flags & TDF_DETAILS))
flow_loops_dump (&loops_info, dump_file, NULL, 0);
flow_loops_dump (current_loops, dump_file, NULL, 0);
add_noreturn_fake_exit_edges ();
connect_infinite_loops_to_exit ();
@ -1265,8 +1261,9 @@ tree_estimate_probability (void)
tree_bb_level_predictions ();
mark_irreducible_loops (&loops_info);
predict_loops (&loops_info);
mark_irreducible_loops (current_loops);
if (current_loops)
predict_loops (current_loops);
FOR_EACH_BB (bb)
{
@ -1328,10 +1325,10 @@ tree_estimate_probability (void)
combine_predictions_for_bb (bb);
strip_builtin_expect ();
estimate_bb_frequencies (&loops_info);
estimate_bb_frequencies (current_loops);
free_dominance_info (CDI_POST_DOMINATORS);
remove_fake_exit_edges ();
flow_loops_free (&loops_info);
loop_optimizer_finalize ();
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags);
if (profile_status == PROFILE_ABSENT)
@ -1437,12 +1434,12 @@ typedef struct edge_info_def
#define EDGE_INFO(E) ((edge_info) (E)->aux)
/* Helper function for estimate_bb_frequencies.
Propagate the frequencies for LOOP. */
Propagate the frequencies in blocks marked in
TOVISIT, starting in HEAD. */
static void
propagate_freq (struct loop *loop, bitmap tovisit)
propagate_freq (basic_block head, bitmap tovisit)
{
basic_block head = loop->header;
basic_block bb;
basic_block last;
unsigned i;
@ -1579,7 +1576,7 @@ propagate_freq (struct loop *loop, bitmap tovisit)
/* Estimate probabilities of loopback edges in loops at same nest level. */
static void
estimate_loops_at_level (struct loop *first_loop, bitmap tovisit)
estimate_loops_at_level (struct loop *first_loop)
{
struct loop *loop;
@ -1588,25 +1585,44 @@ estimate_loops_at_level (struct loop *first_loop, bitmap tovisit)
edge e;
basic_block *bbs;
unsigned i;
bitmap tovisit = BITMAP_ALLOC (NULL);
estimate_loops_at_level (loop->inner, tovisit);
estimate_loops_at_level (loop->inner);
/* Do not do this for dummy function loop. */
if (EDGE_COUNT (loop->latch->succs) > 0)
{
/* Find current loop back edge and mark it. */
e = loop_latch_edge (loop);
EDGE_INFO (e)->back_edge = 1;
}
/* Find current loop back edge and mark it. */
e = loop_latch_edge (loop);
EDGE_INFO (e)->back_edge = 1;
bbs = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++)
bitmap_set_bit (tovisit, bbs[i]->index);
free (bbs);
propagate_freq (loop, tovisit);
propagate_freq (loop->header, tovisit);
BITMAP_FREE (tovisit);
}
}
/* Propates frequencies through structure of LOOPS. */
static void
estimate_loops (struct loops *loops)
{
bitmap tovisit = BITMAP_ALLOC (NULL);
basic_block bb;
/* Start by estimating the frequencies in the loops. */
if (loops)
estimate_loops_at_level (loops->tree_root->inner);
/* Now propagate the frequencies through all the blocks. */
FOR_ALL_BB (bb)
{
bitmap_set_bit (tovisit, bb->index);
}
propagate_freq (ENTRY_BLOCK_PTR, tovisit);
BITMAP_FREE (tovisit);
}
/* Convert counts measured by profile driven feedback to frequencies.
Return nonzero iff there was any nonzero execution count. */
@ -1677,7 +1693,6 @@ estimate_bb_frequencies (struct loops *loops)
if (!flag_branch_probabilities || !counts_to_freqs ())
{
static int real_values_initialized = 0;
bitmap tovisit;
if (!real_values_initialized)
{
@ -1696,7 +1711,6 @@ estimate_bb_frequencies (struct loops *loops)
single_succ_edge (ENTRY_BLOCK_PTR)->probability = REG_BR_PROB_BASE;
/* Set up block info for each basic block. */
tovisit = BITMAP_ALLOC (NULL);
alloc_aux_for_blocks (sizeof (struct block_info_def));
alloc_aux_for_edges (sizeof (struct edge_info_def));
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
@ -1715,7 +1729,7 @@ estimate_bb_frequencies (struct loops *loops)
/* First compute probabilities locally for each loop from innermost
to outermost to examine probabilities for back edges. */
estimate_loops_at_level (loops->tree_root, tovisit);
estimate_loops (loops);
memcpy (&freq_max, &real_zero, sizeof (real_zero));
FOR_EACH_BB (bb)
@ -1734,7 +1748,6 @@ estimate_bb_frequencies (struct loops *loops)
free_aux_for_blocks ();
free_aux_for_edges ();
BITMAP_FREE (tovisit);
}
compute_function_frequency ();
if (flag_reorder_functions)

View File

@ -1998,24 +1998,15 @@ remove_bb (basic_block bb)
}
}
/* If we remove the header or the latch of a loop, mark the loop for
removal by setting its header and latch to NULL. */
if (current_loops)
{
struct loop *loop = bb->loop_father;
/* If a loop gets removed, clean up the information associated
with it. */
if (loop->latch == bb
|| loop->header == bb)
{
loop->latch = NULL;
loop->header = NULL;
/* Also clean up the information associated with the loop. Updating
it would waste time. More importantly, it may refer to ssa
names that were defined in other removed basic block -- these
ssa names are now removed and invalid. */
free_numbers_of_iterations_estimates_loop (loop);
}
free_numbers_of_iterations_estimates_loop (loop);
}
/* Remove all the instructions in the block. */

View File

@ -836,13 +836,11 @@ void free_numbers_of_iterations_estimates (struct loops *);
void free_numbers_of_iterations_estimates_loop (struct loop *);
void rewrite_into_loop_closed_ssa (bitmap, unsigned);
void verify_loop_closed_ssa (void);
void loop_commit_inserts (void);
bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
tree *, tree *);
void split_loop_exit_edge (edge);
unsigned force_expr_to_var_cost (tree);
basic_block bsi_insert_on_edge_immediate_loop (edge, tree);
void standard_iv_increment_position (struct loop *, block_stmt_iterator *,
bool *);
basic_block ip_end_pos (struct loop *);

View File

@ -949,17 +949,9 @@ combine_blocks (struct loop *loop)
/* Update stmt list. */
last = tsi_last (merge_target_bb->stmt_list);
tsi_link_after (&last, bb->stmt_list, TSI_NEW_STMT);
bb->stmt_list = NULL;
bb->stmt_list = alloc_stmt_list ();
/* Update dominator info. */
if (dom_computed[CDI_DOMINATORS])
delete_from_dominance_info (CDI_DOMINATORS, bb);
if (dom_computed[CDI_POST_DOMINATORS])
delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
/* Remove basic block. */
remove_bb_from_loops (bb);
expunge_block (bb);
delete_basic_block (bb);
}
/* Now if possible, merge loop header and block with exit edge.
@ -968,10 +960,7 @@ combine_blocks (struct loop *loop)
if (exit_bb
&& exit_bb != loop->header
&& can_merge_blocks_p (loop->header, exit_bb))
{
remove_bb_from_loops (exit_bb);
merge_blocks (loop->header, exit_bb);
}
merge_blocks (loop->header, exit_bb);
}
/* Make new temp variable of type TYPE. Add MODIFY_EXPR to assign EXP

View File

@ -240,7 +240,6 @@ tree_ssa_dominator_optimize (void)
{
struct dom_walk_data walk_data;
unsigned int i;
struct loops loops_info;
memset (&opt_stats, 0, sizeof (opt_stats));
@ -276,9 +275,12 @@ tree_ssa_dominator_optimize (void)
/* We need to know which edges exit loops so that we can
aggressively thread through loop headers to an exit
edge. */
flow_loops_find (&loops_info);
mark_loop_exit_edges (&loops_info);
flow_loops_free (&loops_info);
loop_optimizer_init (0);
if (current_loops)
{
mark_loop_exit_edges (current_loops);
loop_optimizer_finalize ();
}
/* Clean up the CFG so that any forwarder blocks created by loop
canonicalization are removed. */

View File

@ -123,7 +123,6 @@ do_while_loop_p (struct loop *loop)
static unsigned int
copy_loop_headers (void)
{
struct loops *loops;
unsigned i;
struct loop *loop;
basic_block header;
@ -132,25 +131,25 @@ copy_loop_headers (void)
unsigned n_bbs;
unsigned bbs_size;
loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES);
if (!loops)
loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES);
if (!current_loops)
return 0;
#ifdef ENABLE_CHECKING
verify_loop_structure (loops);
verify_loop_structure (current_loops);
#endif
bbs = XNEWVEC (basic_block, n_basic_blocks);
copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
bbs_size = n_basic_blocks;
for (i = 1; i < loops->num; i++)
for (i = 1; i < current_loops->num; i++)
{
/* Copy at most 20 insns. */
int limit = 20;
loop = loops->parray[i];
loop = current_loops->parray[i];
if (!loop)
continue;
header = loop->header;
@ -194,7 +193,7 @@ copy_loop_headers (void)
/* Ensure that the header will have just the latch as a predecessor
inside the loop. */
if (!single_pred_p (exit->dest))
exit = single_pred_edge (loop_split_edge_with (exit, NULL));
exit = single_pred_edge (split_edge (exit));
entry = loop_preheader_edge (loop);
@ -206,14 +205,14 @@ copy_loop_headers (void)
/* Ensure that the latch and the preheader is simple (we know that they
are not now, since there was the loop exit condition. */
loop_split_edge_with (loop_preheader_edge (loop), NULL);
loop_split_edge_with (loop_latch_edge (loop), NULL);
split_edge (loop_preheader_edge (loop));
split_edge (loop_latch_edge (loop));
}
free (bbs);
free (copied_bbs);
loop_optimizer_finalize (loops);
loop_optimizer_finalize ();
return 0;
}

View File

@ -690,25 +690,6 @@ determine_invariantness (void)
fini_walk_dominator_tree (&walk_data);
}
/* Commits edge insertions and updates loop structures. */
void
loop_commit_inserts (void)
{
unsigned old_last_basic_block, i;
basic_block bb;
old_last_basic_block = last_basic_block;
bsi_commit_edge_inserts ();
for (i = old_last_basic_block; i < (unsigned) last_basic_block; i++)
{
bb = BASIC_BLOCK (i);
add_bb_to_loop (bb,
find_common_loop (single_pred (bb)->loop_father,
single_succ (bb)->loop_father));
}
}
/* Hoist the statements in basic block BB out of the loops prescribed by
data stored in LIM_DATA structures associated with each statement. Callback
for walk_dominator_tree. */
@ -778,7 +759,7 @@ move_computations (void)
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
loop_commit_inserts ();
bsi_commit_edge_inserts ();
if (need_ssa_update_p ())
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
}
@ -1419,7 +1400,7 @@ determine_lsm (struct loops *loops)
loop = loop->outer;
if (loop == loops->tree_root)
{
loop_commit_inserts ();
bsi_commit_edge_inserts ();
return;
}
}

View File

@ -98,7 +98,7 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
loop (i.e. the step should be loop invariant). */
step = force_gimple_operand (step, &stmts, true, var);
if (stmts)
bsi_insert_on_edge_immediate_loop (pe, stmts);
bsi_insert_on_edge_immediate (pe, stmts);
stmt = build2 (MODIFY_EXPR, void_type_node, va,
build2 (incr_op, TREE_TYPE (base),
@ -111,7 +111,7 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
initial = force_gimple_operand (base, &stmts, true, var);
if (stmts)
bsi_insert_on_edge_immediate_loop (pe, stmts);
bsi_insert_on_edge_immediate (pe, stmts);
stmt = create_phi_node (vb, loop->header);
SSA_NAME_DEF_STMT (vb) = stmt;
@ -445,7 +445,7 @@ void
split_loop_exit_edge (edge exit)
{
basic_block dest = exit->dest;
basic_block bb = loop_split_edge_with (exit, NULL);
basic_block bb = split_edge (exit);
tree phi, new_phi, new_name, name;
use_operand_p op_p;
@ -470,32 +470,6 @@ split_loop_exit_edge (edge exit)
}
}
/* Insert statement STMT to the edge E and update the loop structures.
Returns the newly created block (if any). */
basic_block
bsi_insert_on_edge_immediate_loop (edge e, tree stmt)
{
basic_block src, dest, new_bb;
struct loop *loop_c;
src = e->src;
dest = e->dest;
loop_c = find_common_loop (src->loop_father, dest->loop_father);
new_bb = bsi_insert_on_edge_immediate (e, stmt);
if (!new_bb)
return NULL;
add_bb_to_loop (new_bb, loop_c);
if (dest->loop_father->latch == src)
dest->loop_father->latch = new_bb;
return new_bb;
}
/* Returns the basic block in that statements should be emitted for induction
variables incremented at the end of the LOOP. */
@ -749,7 +723,7 @@ determine_exit_conditions (struct loop *loop, struct tree_niter_desc *desc,
cond = force_gimple_operand (unshare_expr (cond), &stmts, false, NULL_TREE);
if (stmts)
bsi_insert_on_edge_immediate_loop (loop_preheader_edge (loop), stmts);
bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
/* cond now may be a gimple comparison, which would be OK, but also any
other gimple rhs (say a && b). In this case we need to force it to
operand. */
@ -757,16 +731,16 @@ determine_exit_conditions (struct loop *loop, struct tree_niter_desc *desc,
{
cond = force_gimple_operand (cond, &stmts, true, NULL_TREE);
if (stmts)
bsi_insert_on_edge_immediate_loop (loop_preheader_edge (loop), stmts);
bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
}
*enter_cond = cond;
base = force_gimple_operand (unshare_expr (base), &stmts, true, NULL_TREE);
if (stmts)
bsi_insert_on_edge_immediate_loop (loop_preheader_edge (loop), stmts);
bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
bound = force_gimple_operand (unshare_expr (bound), &stmts, true, NULL_TREE);
if (stmts)
bsi_insert_on_edge_immediate_loop (loop_preheader_edge (loop), stmts);
bsi_insert_on_edge_immediate (loop_preheader_edge (loop), stmts);
*exit_base = base;
*exit_step = bigstep;
@ -881,7 +855,7 @@ tree_unroll_loop (struct loops *loops, struct loop *loop, unsigned factor,
/* Prepare the cfg and update the phi nodes. */
rest = loop_preheader_edge (new_loop)->src;
precond_edge = single_pred_edge (rest);
loop_split_edge_with (loop_latch_edge (loop), NULL);
split_edge (loop_latch_edge (loop));
exit_bb = single_pred (loop->latch);
new_exit = make_edge (exit_bb, rest, EDGE_FALSE_VALUE | irr);

View File

@ -38,26 +38,17 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "tree-inline.h"
#include "tree-scalar-evolution.h"
/* The loop tree currently optimized. */
struct loops *current_loops = NULL;
/* Initializes the loop structures. */
static struct loops *
static void
tree_loop_optimizer_init (void)
{
struct loops *loops;
loops = loop_optimizer_init (LOOPS_NORMAL
| LOOPS_HAVE_MARKED_SINGLE_EXITS);
if (!loops)
return NULL;
loop_optimizer_init (LOOPS_NORMAL
| LOOPS_HAVE_MARKED_SINGLE_EXITS);
if (!current_loops)
return;
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
return loops;
}
/* The loop superpass. */
@ -90,7 +81,7 @@ struct tree_opt_pass pass_tree_loop =
static unsigned int
tree_ssa_loop_init (void)
{
current_loops = tree_loop_optimizer_init ();
tree_loop_optimizer_init ();
if (!current_loops)
return 0;
@ -487,8 +478,7 @@ tree_ssa_loop_done (void)
free_numbers_of_iterations_estimates (current_loops);
scev_finalize ();
loop_optimizer_finalize (current_loops);
current_loops = NULL;
loop_optimizer_finalize ();
return 0;
}

View File

@ -4065,7 +4065,7 @@ init_pre (bool do_fre)
vn_init ();
if (!do_fre)
current_loops = loop_optimizer_init (LOOPS_NORMAL);
loop_optimizer_init (LOOPS_NORMAL);
connect_infinite_loops_to_exit ();
memset (&pre_stats, 0, sizeof (pre_stats));
@ -4169,10 +4169,7 @@ fini_pre (bool do_fre)
SSA_NAME_VALUE (name) = NULL;
}
if (!do_fre && current_loops)
{
loop_optimizer_finalize (current_loops);
current_loops = NULL;
}
loop_optimizer_finalize ();
}
/* Main entry point to the SSA-PRE pass. DO_FRE is true if the caller

View File

@ -522,7 +522,7 @@ sink_code_in_bb (basic_block bb)
static void
execute_sink_code (void)
{
struct loops *loops = loop_optimizer_init (LOOPS_NORMAL);
loop_optimizer_init (LOOPS_NORMAL);
connect_infinite_loops_to_exit ();
memset (&sink_stats, 0, sizeof (sink_stats));
@ -532,7 +532,7 @@ execute_sink_code (void)
fprintf (dump_file, "Sunk statements:%d\n", sink_stats.sunk);
free_dominance_info (CDI_POST_DOMINATORS);
remove_fake_exit_edges ();
loop_optimizer_finalize (loops);
loop_optimizer_finalize ();
}
/* Gate and execute functions for PRE. */

View File

@ -3845,7 +3845,6 @@ vect_transform_loop (loop_vec_info loop_vinfo,
merge_bb = loop->single_exit->dest;
gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
new_exit_bb = split_edge (loop->single_exit);
add_bb_to_loop (new_exit_bb, loop->outer);
new_exit_e = loop->single_exit;
e = EDGE_SUCC (new_exit_bb, 0);
@ -3897,8 +3896,7 @@ vect_transform_loop (loop_vec_info loop_vinfo,
gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
loop_split_edge_with (loop_preheader_edge (loop), NULL);
split_edge (loop_preheader_edge (loop));
/* FORNOW: the vectorizer supports only loops which body consist
of one basic block (header + empty latch). When the vectorizer will

View File

@ -520,7 +520,6 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
/* Create new bb between loop and new_merge_bb. */
*new_exit_bb = split_edge (loop->single_exit);
add_bb_to_loop (*new_exit_bb, loop->outer);
new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
@ -646,7 +645,6 @@ slpeel_update_phi_nodes_for_guard2 (edge guard_edge, struct loop *loop,
/* Create new bb between loop and new_merge_bb. */
*new_exit_bb = split_edge (loop->single_exit);
add_bb_to_loop (*new_exit_bb, loop->outer);
new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
@ -1157,9 +1155,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
*/
bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
add_bb_to_loop (bb_before_first_loop, first_loop->outer);
bb_before_second_loop = split_edge (first_loop->single_exit);
add_bb_to_loop (bb_before_second_loop, first_loop->outer);
pre_condition =
fold_build2 (LE_EXPR, boolean_type_node, first_niters,
@ -1199,7 +1195,6 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
bb_between_loops = new_exit_bb;
bb_after_second_loop = split_edge (second_loop->single_exit);
add_bb_to_loop (bb_after_second_loop, second_loop->outer);
pre_condition =
fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);

View File

@ -4772,7 +4772,7 @@ execute_vrp (void)
{
insert_range_assertions ();
current_loops = loop_optimizer_init (LOOPS_NORMAL);
loop_optimizer_init (LOOPS_NORMAL);
if (current_loops)
scev_initialize (current_loops);
@ -4783,8 +4783,7 @@ execute_vrp (void)
if (current_loops)
{
scev_finalize ();
loop_optimizer_finalize (current_loops);
current_loops = NULL;
loop_optimizer_finalize ();
}
/* ASSERT_EXPRs must be removed before finalizing jump threads