mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 17:40:45 +08:00
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:
parent
31198773e4
commit
598ec7bdbe
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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--;
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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. */
|
||||
|
11
gcc/ifcvt.c
11
gcc/ifcvt.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user