From 598ec7bdbe0e6e2f7c58961fd0f61e0898a3083e Mon Sep 17 00:00:00 2001 From: Zdenek Dvorak Date: Fri, 17 Nov 2006 12:29:17 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 83 +++++++++++++++++++++++++++++++++++ gcc/Makefile.in | 2 +- gcc/basic-block.h | 1 + gcc/cfghooks.c | 87 ++++++++++++++++++++++++++++++++++++- gcc/cfglayout.c | 4 +- gcc/cfgloop.c | 43 +++---------------- gcc/cfgloop.h | 24 ++--------- gcc/cfgloopanal.c | 63 ++++++++++++++------------- gcc/cfgloopmanip.c | 107 +++++++++++++--------------------------------- gcc/doc/loop.texi | 12 +----- gcc/function.h | 4 ++ gcc/ifcvt.c | 11 ++--- gcc/lambda-code.c | 2 +- gcc/loop-doloop.c | 7 ++- gcc/loop-init.c | 72 ++++++++++++++++--------------- gcc/loop-unroll.c | 35 ++++++++------- gcc/loop-unswitch.c | 4 +- gcc/modulo-sched.c | 37 ++++++++-------- gcc/predict.c | 67 +++++++++++++++++------------ gcc/tree-cfg.c | 15 ++----- gcc/tree-flow.h | 2 - gcc/tree-if-conv.c | 17 ++------ gcc/tree-ssa-dom.c | 10 +++-- gcc/tree-ssa-loop-ch.c | 21 +++++---- gcc/tree-ssa-loop-im.c | 23 +--------- gcc/tree-ssa-loop-manip.c | 42 ++++-------------- gcc/tree-ssa-loop.c | 24 +++-------- gcc/tree-ssa-pre.c | 7 +-- gcc/tree-ssa-sink.c | 4 +- gcc/tree-vect-transform.c | 4 +- gcc/tree-vectorizer.c | 5 --- gcc/tree-vrp.c | 5 +-- 32 files changed, 425 insertions(+), 419 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab9b552..12c61b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,88 @@ 2006-11-17 Zdenek Dvorak + * 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 + PR tree-optimization/29801 * tree-ssa-ccp.c (get_symbol_constant_value): New function. (get_default_value): Use get_symbol_constant_value. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index fda394c1..8136290 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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) \ diff --git a/gcc/basic-block.h b/gcc/basic-block.h index aa41486..6b6820c 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.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); diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index 4d89aea..0378b13 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -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; } diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 6bd63c2..cf76cdb 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -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. */ diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 9afd48b..25549db 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -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--; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 311c43e..17a1cf7 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -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); diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index da54583..9aa75e4 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -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; + src = BB_REPR (act); + dest = BB_REPR (e->dest); - /* 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. + if (loops) + { + /* Ignore latch edges. */ + if (e->dest->loop_father->header == e->dest + && e->dest->loop_father->latch == act) + continue; - Edges exiting loops should lead from representative - of the son of nearest common ancestor of the loops in that - act lays. */ + /* 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. - src = BB_REPR (act); - dest = BB_REPR (e->dest); + 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 (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); + 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. */ diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 8c5a0f1..edb3697 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -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; } diff --git a/gcc/doc/loop.texi b/gcc/doc/loop.texi index b207b38..8c6f52c 100644 --- a/gcc/doc/loop.texi +++ b/gcc/doc/loop.texi @@ -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. diff --git a/gcc/function.h b/gcc/function.h index 1903b16..94c8101 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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. */ diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index f2226c4..ef0c51c 100644 --- a/gcc/ifcvt.c +++ b/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); } diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c index 14a1ba3..d2876a7 100644 --- a/gcc/lambda-code.c +++ b/gcc/lambda-code.c @@ -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. */ diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index 7b9d168..afe65cb 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -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 diff --git a/gcc/loop-init.c b/gcc/loop-init.c index d2c6340..dd8eec1 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -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; } diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 711b021..49af45d 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -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; } diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c index c76f481..0b378f3 100644 --- a/gcc/loop-unswitch.c +++ b/gcc/loop-unswitch.c @@ -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; } diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 8426ba6..62918a0 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -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 diff --git a/gcc/predict.c b/gcc/predict.c index 6b493e2..caf867e 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -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) diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index fc30f22..292fa48 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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. */ diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 6492630..2444ced 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -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 *); diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 3a50741..a4daaa2 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -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 diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 085a5d6..4ec276d 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index 1663807..30db10c 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -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; } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index db9f42f6..de0429e 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -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; } } diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index dde0e8d..68e0fa6 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -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); diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index e415448..69d353b 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -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; } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index d83d81e..2a0ac96 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -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 diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index 4db67c5..fa711b3 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -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. */ diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index e59c152..6091575 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -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 diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index d5b33d6..8bc6885 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -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); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 8b43770..7b8996c 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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 -- 2.7.4