diff options
author | Steven Bosscher <steven@gcc.gnu.org> | 2003-12-30 10:40:56 +0000 |
---|---|---|
committer | Steven Bosscher <steven@gcc.gnu.org> | 2003-12-30 10:40:56 +0000 |
commit | d47cc544b60738db5e983c4b1ac6b40236b9633c (patch) | |
tree | 10047b16072acc29f1f177189825f45ac62aba97 /gcc | |
parent | 58496de135a8b4fdfe552d0d9b18c9d1db147582 (diff) | |
download | gcc-d47cc544b60738db5e983c4b1ac6b40236b9633c.zip gcc-d47cc544b60738db5e983c4b1ac6b40236b9633c.tar.gz gcc-d47cc544b60738db5e983c4b1ac6b40236b9633c.tar.bz2 |
backport: et-forest.h (et_forest_create, [...]): Declarations removed.
Backport from tree-ssa (relevant changes only):
2003-12-18 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* et-forest.h (et_forest_create, et_forest_delete,
et_forest_add_node, et_forest_add_edge, et_forest_remove_node,
et_forest_remove_edge, et_forest_parent,
et_forest_common_ancestor, et_forest_node_value,
et_forest_enumerate_sons): Declarations removed.
(struct et_node): New.
(et_new_tree, et_free_tree, et_set_father, et_split, et_nca,
et_below): Declare.
* et-forest.c (struct et_forest_occurrence, struct et_forest,
struct et_forest_node): Removed.
(et_forest_create, et_forest_delete,
et_forest_add_node, et_forest_add_edge, et_forest_remove_node,
et_forest_remove_edge, et_forest_parent,
et_forest_common_ancestor, et_forest_node_value,
et_forest_enumerate_sons, splay, remove_all_occurrences,
find_leftmost_node, find_rightmost_node, calculate_value): Removed.
(struct et_occ): New.
(et_nodes, et_occurences): New.
(set_depth, set_depth_add, set_prev, set_next, et_recomp_min,
et_check_occ_sanity, et_check_sanity, et_check_tree_sanity,
record_path_before_1, record_path_before, check_path_after_1,
check_path_after, et_splay, et_new_occ, et_new_tree,
et_free_tree, et_set_father, et_split, et_nca, et_below): New.
* basic-block.h (struct basic_block_def): New field dom.
(struct dominance_info): Type removed.
(calculate_dominance_info, free_dominance_info,
nearest_common_dominator, set_immediate_dominator,
get_immediate_dominator, dominated_by_p, get_dominated_by,
add_to_dominance_info, delete_from_dominance_info,
recount_dominator, redirect_immediate_dominators,
iterate_fix_dominators, verify_dominators): Declarations
changed.
(enum dom_state): New.
(dom_computed): New variable.
(first_dom_son, next_dom_son): Declare.
* dominance.c (struct dominance_info): Removed.
(BB_NODE, SET_BB_NODE): Removed.
(calculate_dominance_info, free_dominance_info,
nearest_common_dominator, set_immediate_dominator,
get_immediate_dominator, dominated_by_p, get_dominated_by,
add_to_dominance_info, delete_from_dominance_info,
recount_dominator, redirect_immediate_dominators,
iterate_fix_dominators, verify_dominators,
debug_dominance_info): Work over new datastructure. Access
dominance datastructures through CFG.
(assign_dfs_numbers, compute_dom_fast_query, first_dom_son,
next_dom_son): New.
* bt-load.c (dom): Variable removed.
(augment_live_range, combine_btr_defs, migrate_btr_def,
migrate_btr_defs, branch_target_load_optimize): Updated for the
new interface for dominance information.
* cfg.c {exit_entry_blocks): Update initializer.
* cfglayout.c (copy_bbs): Removed loops argument. Updated for
the new interface for dominance information.
* cfglayout.h (copy_bbs): Declaration changed.
* cfgloop.c (flow_loop_pre_header_find, flow_loops_cfg_dump,
flow_loop_scan, canonicalize_loop_headers, flow_loops_find): Updated
for the new interface for dominance information.
(flow_loop_scan): Loops argument removed.
(flow_loops_free): Don't release dominators.
* cfgloop.h (struct cfg): Dom field removed.
(flow_loop_scan, loop_split_edge_with, simple_loop_p,
just_once_each_iteration_p, split_loop_bb): Declaration changed.
* cfgloopanal.c (simple_loop_exit_p, simple_increment,
just_once_each_iteration_p, simple_loop_p): Remove loops argument.
Updated for the new interface for dominance information.
* cfgloopmanip.c (remove_bbs, find_path, create_preheader,
split_loop_bb, loopify, duplicate_loop_to_header_edge,
force_single_succ_latches, loop_split_edge_with): Ditto.
* gcse.c (dominators): Variable removed.
(free_code_hoist_mem, compute_code_hoist_data, hoist_code):
Updated for the new interface for dominance information.
* ifcvt.c (post_dominators): Variable removed.
(mark_loop_exit_edges, merge_if_block, find_if_header,
find_cond_trap, find_if_case_1, find_if_case_2, if_convert):
Updated for the new interface for dominance information.
* loop-init.c (rtl_loop_optimizer_init,
rtl_loop_optimizer_finalize): Ditto.
* loop-unroll.c (decide_peel_simple, decide_peel_once_rolling,
decide_peel_completely, decide_unroll_stupid,
decide_unroll_constant_iterations,
decide_unroll_runtime_iterations): Loops argument removed.
Updated for the new interface for dominance information.
(unroll_and_peel_loops, peel_loops_completely,
unroll_loop_runtime_iterations): Updated for the new interface for
dominance information.
* loop-unswitch.c (may_unswitch_on_p, unswitch_loops,
unswitch_single_loop, unswitch_loop): Updated for the new
interface for dominance information.
* predict.c (process_note_predictions, process_note_prediction,
estimate_probability, note_prediction_to_br_prob): Ditto.
* sched-rgn.c (find_rgns, init_regions): Ditto.
* toplev.c (rest_of_handle_branch_prob): Free the dominators.
From-SVN: r75226
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 99 | ||||
-rw-r--r-- | gcc/Makefile.in | 4 | ||||
-rw-r--r-- | gcc/basic-block.h | 46 | ||||
-rw-r--r-- | gcc/bt-load.c | 19 | ||||
-rw-r--r-- | gcc/cfg.c | 2 | ||||
-rw-r--r-- | gcc/cfglayout.c | 8 | ||||
-rw-r--r-- | gcc/cfglayout.h | 4 | ||||
-rw-r--r-- | gcc/cfgloop.c | 41 | ||||
-rw-r--r-- | gcc/cfgloop.h | 14 | ||||
-rw-r--r-- | gcc/cfgloopanal.c | 29 | ||||
-rw-r--r-- | gcc/cfgloopmanip.c | 133 | ||||
-rw-r--r-- | gcc/dominance.c | 346 | ||||
-rw-r--r-- | gcc/et-forest.c | 1090 | ||||
-rw-r--r-- | gcc/et-forest.h | 42 | ||||
-rw-r--r-- | gcc/function.c | 2 | ||||
-rw-r--r-- | gcc/function.h | 4 | ||||
-rw-r--r-- | gcc/gcse.c | 25 | ||||
-rw-r--r-- | gcc/graph.c | 25 | ||||
-rw-r--r-- | gcc/ifcvt.c | 49 | ||||
-rw-r--r-- | gcc/loop-init.c | 5 | ||||
-rw-r--r-- | gcc/loop-unroll.c | 80 | ||||
-rw-r--r-- | gcc/loop-unswitch.c | 21 | ||||
-rw-r--r-- | gcc/predict.c | 60 | ||||
-rw-r--r-- | gcc/sched-rgn.c | 13 | ||||
-rw-r--r-- | gcc/toplev.c | 5 |
25 files changed, 1206 insertions, 960 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a6c5491..4b5b073 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,102 @@ +2003-12-30 Steven Bosscher <steven@gcc.gnu.org> + + Backport from tree-ssa (relevant changes only): + 2003-12-18 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> + + * et-forest.h (et_forest_create, et_forest_delete, + et_forest_add_node, et_forest_add_edge, et_forest_remove_node, + et_forest_remove_edge, et_forest_parent, + et_forest_common_ancestor, et_forest_node_value, + et_forest_enumerate_sons): Declarations removed. + (struct et_node): New. + (et_new_tree, et_free_tree, et_set_father, et_split, et_nca, + et_below): Declare. + * et-forest.c (struct et_forest_occurrence, struct et_forest, + struct et_forest_node): Removed. + (et_forest_create, et_forest_delete, + et_forest_add_node, et_forest_add_edge, et_forest_remove_node, + et_forest_remove_edge, et_forest_parent, + et_forest_common_ancestor, et_forest_node_value, + et_forest_enumerate_sons, splay, remove_all_occurrences, + find_leftmost_node, find_rightmost_node, calculate_value): Removed. + (struct et_occ): New. + (et_nodes, et_occurences): New. + (set_depth, set_depth_add, set_prev, set_next, et_recomp_min, + et_check_occ_sanity, et_check_sanity, et_check_tree_sanity, + record_path_before_1, record_path_before, check_path_after_1, + check_path_after, et_splay, et_new_occ, et_new_tree, + et_free_tree, et_set_father, et_split, et_nca, et_below): New. + * basic-block.h (struct basic_block_def): New field dom. + (struct dominance_info): Type removed. + (calculate_dominance_info, free_dominance_info, + nearest_common_dominator, set_immediate_dominator, + get_immediate_dominator, dominated_by_p, get_dominated_by, + add_to_dominance_info, delete_from_dominance_info, + recount_dominator, redirect_immediate_dominators, + iterate_fix_dominators, verify_dominators): Declarations + changed. + (enum dom_state): New. + (dom_computed): New variable. + (first_dom_son, next_dom_son): Declare. + * dominance.c (struct dominance_info): Removed. + (BB_NODE, SET_BB_NODE): Removed. + (calculate_dominance_info, free_dominance_info, + nearest_common_dominator, set_immediate_dominator, + get_immediate_dominator, dominated_by_p, get_dominated_by, + add_to_dominance_info, delete_from_dominance_info, + recount_dominator, redirect_immediate_dominators, + iterate_fix_dominators, verify_dominators, + debug_dominance_info): Work over new datastructure. Access + dominance datastructures through CFG. + (assign_dfs_numbers, compute_dom_fast_query, first_dom_son, + next_dom_son): New. + * bt-load.c (dom): Variable removed. + (augment_live_range, combine_btr_defs, migrate_btr_def, + migrate_btr_defs, branch_target_load_optimize): Updated for the + new interface for dominance information. + * cfg.c {exit_entry_blocks): Update initializer. + * cfglayout.c (copy_bbs): Removed loops argument. Updated for + the new interface for dominance information. + * cfglayout.h (copy_bbs): Declaration changed. + * cfgloop.c (flow_loop_pre_header_find, flow_loops_cfg_dump, + flow_loop_scan, canonicalize_loop_headers, flow_loops_find): Updated + for the new interface for dominance information. + (flow_loop_scan): Loops argument removed. + (flow_loops_free): Don't release dominators. + * cfgloop.h (struct cfg): Dom field removed. + (flow_loop_scan, loop_split_edge_with, simple_loop_p, + just_once_each_iteration_p, split_loop_bb): Declaration changed. + * cfgloopanal.c (simple_loop_exit_p, simple_increment, + just_once_each_iteration_p, simple_loop_p): Remove loops argument. + Updated for the new interface for dominance information. + * cfgloopmanip.c (remove_bbs, find_path, create_preheader, + split_loop_bb, loopify, duplicate_loop_to_header_edge, + force_single_succ_latches, loop_split_edge_with): Ditto. + * gcse.c (dominators): Variable removed. + (free_code_hoist_mem, compute_code_hoist_data, hoist_code): + Updated for the new interface for dominance information. + * ifcvt.c (post_dominators): Variable removed. + (mark_loop_exit_edges, merge_if_block, find_if_header, + find_cond_trap, find_if_case_1, find_if_case_2, if_convert): + Updated for the new interface for dominance information. + * loop-init.c (rtl_loop_optimizer_init, + rtl_loop_optimizer_finalize): Ditto. + * loop-unroll.c (decide_peel_simple, decide_peel_once_rolling, + decide_peel_completely, decide_unroll_stupid, + decide_unroll_constant_iterations, + decide_unroll_runtime_iterations): Loops argument removed. + Updated for the new interface for dominance information. + (unroll_and_peel_loops, peel_loops_completely, + unroll_loop_runtime_iterations): Updated for the new interface for + dominance information. + * loop-unswitch.c (may_unswitch_on_p, unswitch_loops, + unswitch_single_loop, unswitch_loop): Updated for the new + interface for dominance information. + * predict.c (process_note_predictions, process_note_prediction, + estimate_probability, note_prediction_to_br_prob): Ditto. + * sched-rgn.c (find_rgns, init_regions): Ditto. + * toplev.c (rest_of_handle_branch_prob): Free the dominators. + 2003-12-30 Jan Hubicka <jh@suse.cz> PR target/13456 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 1390141..bd65e0b 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1322,7 +1322,7 @@ c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h flags.h output.h \ - $(RTL_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h + $(RTL_H) function.h langhooks.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h $(TREE_H) sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \ hard-reg-set.h $(BASIC_BLOCK_H) @@ -1651,7 +1651,7 @@ web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ hard-reg-set.h flags.h $(BASIC_BLOCK_H) function.h output.h toplev.h df.h gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ hard-reg-set.h flags.h real.h insn-config.h $(GGC_H) $(RECOG_H) $(EXPR_H) \ - $(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) \ + $(BASIC_BLOCK_H) function.h langhooks.h output.h toplev.h $(TM_P_H) $(PARAMS_H) \ except.h gt-gcse.h $(TREE_H) sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ function.h hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 9b664a1..2e8f578 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -234,6 +234,9 @@ typedef struct basic_block_def { /* Outermost loop containing the block. */ struct loop *loop_father; + /* The dominance and postdominance information node. */ + struct et_node *dom[2]; + /* Expected number of executions: calculated in profile.c. */ gcov_type count; @@ -373,10 +376,6 @@ extern void clear_edges (void); extern void mark_critical_edges (void); extern rtx first_insn_after_basic_block_note (basic_block); -/* Dominator information for basic blocks. */ - -typedef struct dominance_info *dominance_info; - /* Structure to group all of the information to process IF-THEN and IF-THEN-ELSE blocks for the conditional execution support. This needs to be in a public file in case the IFCVT macros call @@ -612,22 +611,35 @@ enum cdi_direction CDI_POST_DOMINATORS }; -extern dominance_info calculate_dominance_info (enum cdi_direction); -extern void free_dominance_info (dominance_info); -extern basic_block nearest_common_dominator (dominance_info, +enum dom_state +{ + DOM_NONE, /* Not computed at all. */ + DOM_CONS_OK, /* The data is conservatively OK, i.e. if it says you that A dominates B, + it indeed does. */ + DOM_NO_FAST_QUERY, /* The data is OK, but the fast query data are not usable. */ + DOM_OK /* Everything is ok. */ +}; + +extern enum dom_state dom_computed[2]; + +extern void calculate_dominance_info (enum cdi_direction); +extern void free_dominance_info (enum cdi_direction); +extern basic_block nearest_common_dominator (enum cdi_direction, basic_block, basic_block); -extern void set_immediate_dominator (dominance_info, basic_block, +extern void set_immediate_dominator (enum cdi_direction, basic_block, basic_block); -extern basic_block get_immediate_dominator (dominance_info, basic_block); -extern bool dominated_by_p (dominance_info, basic_block, basic_block); -extern int get_dominated_by (dominance_info, basic_block, basic_block **); -extern void add_to_dominance_info (dominance_info, basic_block); -extern void delete_from_dominance_info (dominance_info, basic_block); -basic_block recount_dominator (dominance_info, basic_block); -extern void redirect_immediate_dominators (dominance_info, basic_block, +extern basic_block get_immediate_dominator (enum cdi_direction, basic_block); +extern bool dominated_by_p (enum cdi_direction, basic_block, basic_block); +extern int get_dominated_by (enum cdi_direction, basic_block, basic_block **); +extern void add_to_dominance_info (enum cdi_direction, basic_block); +extern void delete_from_dominance_info (enum cdi_direction, basic_block); +basic_block recount_dominator (enum cdi_direction, basic_block); +extern void redirect_immediate_dominators (enum cdi_direction, basic_block, basic_block); -void iterate_fix_dominators (dominance_info, basic_block *, int); -extern void verify_dominators (dominance_info); +extern void iterate_fix_dominators (enum cdi_direction, basic_block *, int); +extern void verify_dominators (enum cdi_direction); +extern basic_block first_dom_son (enum cdi_direction, basic_block); +extern basic_block next_dom_son (enum cdi_direction, basic_block); #include "cfghooks.h" diff --git a/gcc/bt-load.c b/gcc/bt-load.c index 6f77a20..2a68cd7 100644 --- a/gcc/bt-load.c +++ b/gcc/bt-load.c @@ -155,9 +155,6 @@ static void note_btr_set (rtx, rtx, void *); migrating branch target load instructions. */ static struct obstack migrate_btrl_obstack; -/* Basic block dominator information used when migrating PT instructions. */ -static dominance_info dom; - /* Array indexed by basic block number, giving the set of registers live in that block. */ static HARD_REG_SET *btrs_live; @@ -840,9 +837,9 @@ augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range, tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1)); - if (dominated_by_p (dom, new_bb, head_bb)) + if (dominated_by_p (CDI_DOMINATORS, new_bb, head_bb)) *tos++ = new_bb; - else if (dominated_by_p (dom, head_bb, new_bb)) + else if (dominated_by_p (CDI_DOMINATORS, head_bb, new_bb)) { edge e; int new_block = new_bb->index; @@ -974,7 +971,7 @@ combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range) if (other_def != def && other_def->uses != NULL && ! other_def->has_ambiguous_use - && dominated_by_p (dom, other_def->bb, def->bb)) + && dominated_by_p (CDI_DOMINATORS, other_def->bb, def->bb)) { /* def->bb dominates the other def, so def and other_def could be combined. */ @@ -1226,9 +1223,9 @@ migrate_btr_def (btr_def def, int min_cost) def_basic_block_freq = basic_block_freq (def->bb); - for (try = get_immediate_dominator (dom, def->bb); + for (try = get_immediate_dominator (CDI_DOMINATORS, def->bb); !give_up && try && try != ENTRY_BLOCK_PTR && def->cost >= min_cost; - try = get_immediate_dominator (dom, try)) + try = get_immediate_dominator (CDI_DOMINATORS, try)) { /* Try to move the instruction that sets the target register into basic block TRY. */ @@ -1299,7 +1296,7 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save) "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC " loop-depth = %d idom = %d\n", i, (HOST_WIDEST_INT) bb->count, bb->loop_depth, - get_immediate_dominator (dom, bb)->index); + get_immediate_dominator (CDI_DOMINATORS, bb)->index); } } @@ -1367,12 +1364,12 @@ branch_target_load_optimize (rtx insns, bool after_prologue_epilogue_gen) life_analysis (insns, NULL, 0); /* Dominator info is also needed for migrate_btr_def. */ - dom = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); migrate_btr_defs (class, ((*targetm.branch_target_register_callee_saved) (after_prologue_epilogue_gen))); - free_dominance_info (dom); + free_dominance_info (CDI_DOMINATORS); update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES | PROP_REG_INFO); @@ -111,6 +111,7 @@ struct basic_block_def entry_exit_blocks[2] EXIT_BLOCK_PTR, /* next_bb */ 0, /* loop_depth */ NULL, /* loop_father */ + { NULL, NULL }, /* dom */ 0, /* count */ 0, /* frequency */ 0, /* flags */ @@ -133,6 +134,7 @@ struct basic_block_def entry_exit_blocks[2] NULL, /* next_bb */ 0, /* loop_depth */ NULL, /* loop_father */ + { NULL, NULL }, /* dom */ 0, /* count */ 0, /* frequency */ 0, /* flags */ diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 14138a7..15ec054 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -1253,7 +1253,7 @@ end: void copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, edge *edges, unsigned n_edges, edge *new_edges, - struct loop *base, struct loops *loops) + struct loop *base) { unsigned i, j; basic_block bb, new_bb, dom_bb; @@ -1268,7 +1268,7 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, bb->rbi->duplicated = 1; /* Add to loop. */ add_bb_to_loop (new_bb, bb->loop_father->copy); - add_to_dominance_info (loops->cfg.dom, new_bb); + add_to_dominance_info (CDI_DOMINATORS, new_bb); /* Possibly set header. */ if (bb->loop_father->header == bb && bb->loop_father != base) new_bb->loop_father->header = new_bb; @@ -1283,11 +1283,11 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, bb = bbs[i]; new_bb = new_bbs[i]; - dom_bb = get_immediate_dominator (loops->cfg.dom, bb); + dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb); if (dom_bb->rbi->duplicated) { dom_bb = dom_bb->rbi->copy; - set_immediate_dominator (loops->cfg.dom, new_bb, dom_bb); + set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb); } } diff --git a/gcc/cfglayout.h b/gcc/cfglayout.h index 3258fe8..ca79e26 100644 --- a/gcc/cfglayout.h +++ b/gcc/cfglayout.h @@ -43,5 +43,5 @@ extern void insn_locators_initialize (void); extern void reemit_insn_block_notes (void); extern bool can_copy_bbs_p (basic_block *, unsigned); extern void copy_bbs (basic_block *, unsigned, basic_block *, - edge *, unsigned, edge *, struct loop *, struct loops *); -extern void cfg_layout_initialize_rbi (basic_block); + edge *, unsigned, edge *, struct loop *); +extern void cfg_layout_initialize_rbi (basic_block); diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 413b606..43c52f2 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -38,7 +38,7 @@ static void flow_loop_entry_edges_find (struct loop *); static void flow_loop_exit_edges_find (struct loop *); static int flow_loop_nodes_find (basic_block, struct loop *); static void flow_loop_pre_header_scan (struct loop *); -static basic_block flow_loop_pre_header_find (basic_block, dominance_info); +static basic_block flow_loop_pre_header_find (basic_block); static int flow_loop_level_compute (struct loop *); static int flow_loops_level_compute (struct loops *); static void establish_preds (struct loop *); @@ -55,7 +55,7 @@ flow_loops_cfg_dump (const struct loops *loops, FILE *file) int i; basic_block bb; - if (! loops->num || ! file || ! loops->cfg.dom) + if (! loops->num || ! file) return; FOR_EACH_BB (bb) @@ -212,9 +212,6 @@ flow_loops_free (struct loops *loops) free (loops->parray); loops->parray = NULL; - if (loops->cfg.dom) - free_dominance_info (loops->cfg.dom); - if (loops->cfg.dfs_order) free (loops->cfg.dfs_order); if (loops->cfg.rc_order) @@ -391,11 +388,10 @@ flow_loop_pre_header_scan (struct loop *loop) } /* Return the block for the pre-header of the loop with header - HEADER where DOM specifies the dominator information. Return NULL if - there is no pre-header. */ + HEADER. Return NULL if there is no pre-header. */ static basic_block -flow_loop_pre_header_find (basic_block header, dominance_info dom) +flow_loop_pre_header_find (basic_block header) { basic_block pre_header; edge e; @@ -408,7 +404,7 @@ flow_loop_pre_header_find (basic_block header, dominance_info dom) basic_block node = e->src; if (node != ENTRY_BLOCK_PTR - && ! dominated_by_p (dom, node, header)) + && ! dominated_by_p (CDI_DOMINATORS, node, header)) { if (pre_header == NULL) pre_header = node; @@ -522,7 +518,7 @@ flow_loops_level_compute (struct loops *loops) about it specified by FLAGS. */ int -flow_loop_scan (struct loops *loops, struct loop *loop, int flags) +flow_loop_scan (struct loop *loop, int flags) { if (flags & LOOP_ENTRY_EDGES) { @@ -541,8 +537,7 @@ flow_loop_scan (struct loops *loops, struct loop *loop, int flags) if (flags & LOOP_PRE_HEADER) { /* Look to see if the loop has a pre-header node. */ - loop->pre_header - = flow_loop_pre_header_find (loop->header, loops->cfg.dom); + loop->pre_header = flow_loop_pre_header_find (loop->header); /* Find the blocks within the extended basic block of the loop pre-header. */ @@ -627,12 +622,11 @@ make_forwarder_block (basic_block bb, int redirect_latch, int redirect_nonlatch, static void canonicalize_loop_headers (void) { - dominance_info dom; basic_block header; edge e; /* Compute the dominators. */ - dom = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); alloc_aux_for_blocks (sizeof (int)); alloc_aux_for_edges (sizeof (int)); @@ -651,7 +645,7 @@ canonicalize_loop_headers (void) have_abnormal_edge = 1; if (latch != ENTRY_BLOCK_PTR - && dominated_by_p (dom, latch, header)) + && dominated_by_p (CDI_DOMINATORS, latch, header)) { num_latches++; LATCH_EDGE (e) = 1; @@ -663,6 +657,8 @@ canonicalize_loop_headers (void) HEADER_BLOCK (header) = num_latches; } + free_dominance_info (CDI_DOMINATORS); + if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest)) { basic_block bb; @@ -728,7 +724,6 @@ canonicalize_loop_headers (void) free_aux_for_blocks (); free_aux_for_edges (); - free_dominance_info (dom); } /* Find all the natural loops in the function and save in LOOPS structure and @@ -744,7 +739,6 @@ flow_loops_find (struct loops *loops, int flags) int num_loops; edge e; sbitmap headers; - dominance_info dom; int *dfs_order; int *rc_order; basic_block header; @@ -770,7 +764,7 @@ flow_loops_find (struct loops *loops, int flags) canonicalize_loop_headers (); /* Compute the dominators. */ - dom = loops->cfg.dom = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); /* Count the number of loop headers. This should be the same as the number of natural loops. */ @@ -804,7 +798,8 @@ flow_loops_find (struct loops *loops, int flags) node (header) that dominates all the nodes in the loop. It also has single back edge to the header from a latch node. */ - if (latch != ENTRY_BLOCK_PTR && dominated_by_p (dom, latch, header)) + if (latch != ENTRY_BLOCK_PTR + && dominated_by_p (CDI_DOMINATORS, latch, header)) { /* Shared headers should be eliminated by now. */ if (more_latches) @@ -849,7 +844,6 @@ flow_loops_find (struct loops *loops, int flags) flow_depth_first_order_compute (dfs_order, rc_order); /* Save CFG derived information to avoid recomputing it. */ - loops->cfg.dom = dom; loops->cfg.dfs_order = dfs_order; loops->cfg.rc_order = rc_order; @@ -878,7 +872,7 @@ flow_loops_find (struct loops *loops, int flags) basic_block latch = e->src; if (latch != ENTRY_BLOCK_PTR - && dominated_by_p (dom, latch, header)) + && dominated_by_p (CDI_DOMINATORS, latch, header)) { loop->latch = latch; break; @@ -897,14 +891,13 @@ flow_loops_find (struct loops *loops, int flags) /* Scan the loops. */ for (i = 1; i < num_loops; i++) - flow_loop_scan (loops, loops->parray[i], flags); + flow_loop_scan (loops->parray[i], flags); loops->num = num_loops; } else { - loops->cfg.dom = NULL; - free_dominance_info (dom); + free_dominance_info (CDI_DOMINATORS); } loops->state = 0; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 0ab1590..4d8c67d 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -230,9 +230,6 @@ struct loops /* Information derived from the CFG. */ struct cfg { - /* The bitmap vector of dominators or NULL if not computed. */ - dominance_info dom; - /* The ordering of the basic blocks in a depth first search. */ int *dfs_order; @@ -265,7 +262,7 @@ extern void flow_loops_dump (const struct loops *, FILE *, void (*)(const struct loop *, FILE *, int), int); extern void flow_loop_dump (const struct loop *, FILE *, void (*)(const struct loop *, FILE *, int), int); -extern int flow_loop_scan (struct loops *, struct loop *, int); +extern int flow_loop_scan (struct loop *, int); extern void flow_loop_free (struct loop *); void mark_irreducible_loops (struct loops *); @@ -292,7 +289,7 @@ extern void remove_bb_from_loops (basic_block); extern void cancel_loop (struct loops *, struct loop *); extern void cancel_loop_tree (struct loops *, struct loop *); -extern basic_block loop_split_edge_with (edge, rtx, struct loops *); +extern basic_block loop_split_edge_with (edge, rtx); extern int fix_loop_placement (struct loop *); enum @@ -306,10 +303,9 @@ extern void force_single_succ_latches (struct loops *); extern void verify_loop_structure (struct loops *); /* Loop analysis. */ -extern bool simple_loop_p (struct loops *, struct loop *, struct loop_desc *); +extern bool simple_loop_p (struct loop *, struct loop_desc *); extern rtx count_loop_iterations (struct loop_desc *, rtx, rtx); -extern bool just_once_each_iteration_p (struct loops *,struct loop *, - basic_block); +extern bool just_once_each_iteration_p (struct loop *, basic_block); extern unsigned expected_loop_iterations (const struct loop *); /* Loop manipulation. */ @@ -324,7 +320,7 @@ extern int duplicate_loop_to_header_edge (struct loop *, edge, struct loops *, extern struct loop *loopify (struct loops *, edge, edge, basic_block); extern void unloop (struct loops *, struct loop *); extern bool remove_path (struct loops *, edge); -extern edge split_loop_bb (struct loops *, basic_block, rtx); +extern edge split_loop_bb (basic_block, rtx); /* Loop optimizer initialization. */ extern struct loops *loop_optimizer_init (FILE *); diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 74cebe0..fb5f8ae 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -39,14 +39,13 @@ static bool invariant_rtx_wrto_regs_p (rtx, regset); static rtx test_for_iteration (struct loop_desc *desc, unsigned HOST_WIDE_INT); static bool constant_iterations (struct loop_desc *, unsigned HOST_WIDE_INT *, bool *); -static bool simple_loop_exit_p (struct loops *, struct loop *, edge, regset, +static bool simple_loop_exit_p (struct loop *, edge, regset, rtx *, struct loop_desc *); static rtx variable_initial_value (rtx, regset, rtx, rtx *, enum machine_mode); static rtx variable_initial_values (edge, rtx, enum machine_mode); static bool simple_condition_p (struct loop *, rtx, regset, struct loop_desc *); -static basic_block simple_increment (struct loops *, struct loop *, rtx *, - struct loop_desc *); +static basic_block simple_increment (struct loop *, rtx *, struct loop_desc *); static rtx count_strange_loop_iterations (rtx, rtx, enum rtx_code, int, rtx, enum machine_mode, enum machine_mode); @@ -73,10 +72,10 @@ inverse (unsigned HOST_WIDEST_INT x, int mod) /* Checks whether BB is executed exactly once in each LOOP iteration. */ bool -just_once_each_iteration_p (struct loops *loops, struct loop *loop, basic_block bb) +just_once_each_iteration_p (struct loop *loop, basic_block bb) { /* It must be executed at least once each iteration. */ - if (!dominated_by_p (loops->cfg.dom, loop->latch, bb)) + if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) return false; /* And just once. */ @@ -295,8 +294,8 @@ simple_condition_p (struct loop *loop ATTRIBUTE_UNUSED, rtx condition, iteration. Fills in DESC->stride and returns block in that DESC->var is modified. */ static basic_block -simple_increment (struct loops *loops, struct loop *loop, - rtx *simple_increment_regs, struct loop_desc *desc) +simple_increment (struct loop *loop, rtx *simple_increment_regs, + struct loop_desc *desc) { rtx mod_insn, mod_insn1, set, set_src, set_add; basic_block mod_bb, mod_bb1; @@ -308,7 +307,7 @@ simple_increment (struct loops *loops, struct loop *loop, mod_bb = BLOCK_FOR_INSN (mod_insn); /* Check that it is executed exactly once each iteration. */ - if (!just_once_each_iteration_p (loops, loop, mod_bb)) + if (!just_once_each_iteration_p (loop, mod_bb)) return NULL; /* mod_insn must be a simple increment/decrement. */ @@ -355,7 +354,7 @@ simple_increment (struct loops *loops, struct loop *loop, return NULL; mod_bb1 = BLOCK_FOR_INSN (mod_insn1); - if (!dominated_by_p (loops->cfg.dom, mod_bb, mod_bb1)) + if (!dominated_by_p (CDI_DOMINATORS, mod_bb, mod_bb1)) return NULL; if (mod_bb1 == mod_bb) { @@ -962,7 +961,7 @@ test_for_iteration (struct loop_desc *desc, unsigned HOST_WIDE_INT iter) description joined to it in in DESC. INVARIANT_REGS and SINGLE_SET_REGS are results of blocks_{invariant,single_set}_regs over BODY. */ static bool -simple_loop_exit_p (struct loops *loops, struct loop *loop, edge exit_edge, +simple_loop_exit_p (struct loop *loop, edge exit_edge, regset invariant_regs, rtx *single_set_regs, struct loop_desc *desc) { @@ -979,7 +978,7 @@ simple_loop_exit_p (struct loops *loops, struct loop *loop, edge exit_edge, return false; /* It must be tested (at least) once during any iteration. */ - if (!dominated_by_p (loops->cfg.dom, loop->latch, exit_bb)) + if (!dominated_by_p (CDI_DOMINATORS, loop->latch, exit_bb)) return false; /* It must end in a simple conditional jump. */ @@ -1003,11 +1002,11 @@ simple_loop_exit_p (struct loops *loops, struct loop *loop, edge exit_edge, /* Var must be simply incremented or decremented in exactly one insn that is executed just once every iteration. */ - if (!(mod_bb = simple_increment (loops, loop, single_set_regs, desc))) + if (!(mod_bb = simple_increment (loop, single_set_regs, desc))) return false; /* OK, it is simple loop. Now just fill in remaining info. */ - desc->postincr = !dominated_by_p (loops->cfg.dom, exit_bb, mod_bb); + desc->postincr = !dominated_by_p (CDI_DOMINATORS, exit_bb, mod_bb); desc->neg = !fallthru_out; /* Find initial value of var and alternative values for lim. */ @@ -1026,7 +1025,7 @@ simple_loop_exit_p (struct loops *loops, struct loop *loop, edge exit_edge, /* Tests whether LOOP is simple for loop. Returns simple loop description in DESC. */ bool -simple_loop_p (struct loops *loops, struct loop *loop, struct loop_desc *desc) +simple_loop_p (struct loop *loop, struct loop_desc *desc) { unsigned i; basic_block *body; @@ -1051,7 +1050,7 @@ simple_loop_p (struct loops *loops, struct loop *loop, struct loop_desc *desc) { for (e = body[i]->succ; e; e = e->succ_next) if (!flow_bb_inside_loop_p (loop, e->dest) - && simple_loop_exit_p (loops, loop, e, + && simple_loop_exit_p (loop, e, invariant_regs, single_set_regs, &act)) { /* Prefer constant iterations; the less the better. */ diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 6fa80c7..86af4a2 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -36,9 +36,9 @@ static void copy_loops_to (struct loops *, struct loop **, int, struct loop *); static void loop_redirect_edge (edge, basic_block); static bool loop_delete_branch_edge (edge, int); -static void remove_bbs (dominance_info, basic_block *, int); +static void remove_bbs (basic_block *, int); static bool rpe_enum_p (basic_block, void *); -static int find_path (edge, dominance_info, basic_block **); +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 loop *); @@ -47,17 +47,15 @@ static void fix_bb_placements (struct loops *, basic_block); static void place_new_loop (struct loops *, struct loop *); static void scale_loop_frequencies (struct loop *, int, int); static void scale_bbs_frequencies (basic_block *, int, int, int); -static basic_block create_preheader (struct loop *, dominance_info, int); +static basic_block create_preheader (struct loop *, int); static void fix_irreducible_loops (basic_block); /* Splits basic block BB after INSN, returns created edge. Updates loops and dominators. */ edge -split_loop_bb (struct loops *loops, basic_block bb, rtx insn) +split_loop_bb (basic_block bb, rtx insn) { edge e; - basic_block *dom_bbs; - int n_dom_bbs, i; /* Split the block. */ e = split_block (bb, insn); @@ -66,42 +64,31 @@ split_loop_bb (struct loops *loops, basic_block bb, rtx insn) add_bb_to_loop (e->dest, e->src->loop_father); /* Fix dominators. */ - add_to_dominance_info (loops->cfg.dom, e->dest); - n_dom_bbs = get_dominated_by (loops->cfg.dom, e->src, &dom_bbs); - for (i = 0; i < n_dom_bbs; i++) - set_immediate_dominator (loops->cfg.dom, dom_bbs[i], e->dest); - free (dom_bbs); - set_immediate_dominator (loops->cfg.dom, e->dest, e->src); + add_to_dominance_info (CDI_DOMINATORS, e->dest); + redirect_immediate_dominators (CDI_DOMINATORS, e->src, e->dest); + set_immediate_dominator (CDI_DOMINATORS, e->dest, e->src); return e; } -/* Checks whether basic block BB is dominated by RPE->DOM, where - RPE is passed through DATA. */ -struct rpe_data - { - basic_block dom; - dominance_info doms; - }; - +/* Checks whether basic block BB is dominated by DATA. */ static bool rpe_enum_p (basic_block bb, void *data) { - struct rpe_data *rpe = data; - return dominated_by_p (rpe->doms, bb, rpe->dom); + return dominated_by_p (CDI_DOMINATORS, bb, data); } /* Remove basic blocks BBS from loop structure and dominance info, and delete them afterwards. */ static void -remove_bbs (dominance_info dom, basic_block *bbs, int nbbs) +remove_bbs (basic_block *bbs, int nbbs) { int i; for (i = 0; i < nbbs; i++) { remove_bb_from_loops (bbs[i]); - delete_from_dominance_info (dom, bbs[i]); + delete_from_dominance_info (CDI_DOMINATORS, bbs[i]); delete_block (bbs[i]); } } @@ -113,19 +100,15 @@ remove_bbs (dominance_info dom, basic_block *bbs, int nbbs) alter anything by this function). The number of basic blocks in the path is returned. */ static int -find_path (edge e, dominance_info doms, basic_block **bbs) +find_path (edge e, basic_block **bbs) { - struct rpe_data rpe; - if (e->dest->pred->pred_next) abort (); /* Find bbs in the path. */ - rpe.dom = e->dest; - rpe.doms = doms; *bbs = xcalloc (n_basic_blocks, sizeof (basic_block)); return dfs_enumerate_from (e->dest, 0, rpe_enum_p, *bbs, - n_basic_blocks, &rpe); + n_basic_blocks, e->dest); } /* Fix placement of basic block BB inside loop hierarchy stored in LOOPS -- @@ -353,19 +336,19 @@ 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 (e->dest->pred->pred_next) - e = loop_split_edge_with (e, NULL_RTX, loops)->pred; + e = loop_split_edge_with (e, NULL_RTX)->pred; /* 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 normally. We may assume that e->dest is not a header of any loop, as it now has exactly one predecessor. */ while (e->src->loop_father->outer - && dominated_by_p (loops->cfg.dom, + && dominated_by_p (CDI_DOMINATORS, e->src->loop_father->latch, e->dest)) unloop (loops, e->src->loop_father); /* Identify the path. */ - nrem = find_path (e, loops->cfg.dom, &rem_bbs); + nrem = find_path (e, &rem_bbs); n_bord_bbs = 0; bord_bbs = xcalloc (n_basic_blocks, sizeof (basic_block)); @@ -397,7 +380,7 @@ remove_path (struct loops *loops, edge e) if (rem_bbs[i]->loop_father->header == rem_bbs[i]) cancel_loop_tree (loops, rem_bbs[i]->loop_father); - remove_bbs (loops->cfg.dom, rem_bbs, nrem); + remove_bbs (rem_bbs, nrem); free (rem_bbs); /* Find blocks whose dominators may be affected. */ @@ -405,25 +388,24 @@ remove_path (struct loops *loops, edge e) sbitmap_zero (seen); for (i = 0; i < n_bord_bbs; i++) { - int j, nldom; - basic_block *ldom; + basic_block ldom; - bb = get_immediate_dominator (loops->cfg.dom, bord_bbs[i]); + bb = get_immediate_dominator (CDI_DOMINATORS, bord_bbs[i]); if (TEST_BIT (seen, bb->index)) continue; SET_BIT (seen, bb->index); - nldom = get_dominated_by (loops->cfg.dom, bb, &ldom); - for (j = 0; j < nldom; j++) - if (!dominated_by_p (loops->cfg.dom, from, ldom[j])) - dom_bbs[n_dom_bbs++] = ldom[j]; - free(ldom); + for (ldom = first_dom_son (CDI_DOMINATORS, bb); + ldom; + ldom = next_dom_son (CDI_DOMINATORS, ldom)) + if (!dominated_by_p (CDI_DOMINATORS, from, ldom)) + dom_bbs[n_dom_bbs++] = ldom; } free (seen); /* Recount dominators. */ - iterate_fix_dominators (loops->cfg.dom, dom_bbs, n_dom_bbs); + iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs); free (dom_bbs); /* These blocks have lost some predecessor(s), thus their irreducible @@ -513,7 +495,7 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block swi basic_block succ_bb = latch_edge->dest; basic_block pred_bb = header_edge->src; basic_block *dom_bbs, *body; - unsigned n_dom_bbs, i, j; + unsigned n_dom_bbs, i; sbitmap seen; struct loop *loop = xcalloc (1, sizeof (struct loop)); struct loop *outer = succ_bb->loop_father->outer; @@ -538,9 +520,9 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block swi loop_redirect_edge (switch_bb->succ, succ_bb); /* Update dominators. */ - set_immediate_dominator (loops->cfg.dom, switch_bb, pred_bb); - set_immediate_dominator (loops->cfg.dom, loop->header, switch_bb); - set_immediate_dominator (loops->cfg.dom, succ_bb, switch_bb); + set_immediate_dominator (CDI_DOMINATORS, switch_bb, pred_bb); + set_immediate_dominator (CDI_DOMINATORS, loop->header, switch_bb); + set_immediate_dominator (CDI_DOMINATORS, succ_bb, switch_bb); /* Compute new loop. */ add_loop (loops, loop); @@ -569,20 +551,19 @@ loopify (struct loops *loops, edge latch_edge, edge header_edge, basic_block swi for (i = 0; i < loop->num_nodes; i++) { - unsigned nldom; - basic_block *ldom; + basic_block ldom; - nldom = get_dominated_by (loops->cfg.dom, body[i], &ldom); - for (j = 0; j < nldom; j++) - if (!TEST_BIT (seen, ldom[j]->index)) + for (ldom = first_dom_son (CDI_DOMINATORS, body[i]); + ldom; + ldom = next_dom_son (CDI_DOMINATORS, ldom)) + if (!TEST_BIT (seen, ldom->index)) { - SET_BIT (seen, ldom[j]->index); - dom_bbs[n_dom_bbs++] = ldom[j]; + SET_BIT (seen, ldom->index); + dom_bbs[n_dom_bbs++] = ldom; } - free (ldom); } - iterate_fix_dominators (loops->cfg.dom, dom_bbs, n_dom_bbs); + iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs); free (body); free (seen); @@ -990,7 +971,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, copy_loops_to (loops, orig_loops, n_orig_loops, target); /* Copy bbs. */ - copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop, loops); + copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop); /* Note whether the blocks and edges belong to an irreducible loop. */ if (add_irreducible_flag) @@ -1019,7 +1000,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, redirect_edge_and_branch_force (latch_edge, new_bbs[0]); redirect_edge_and_branch_force (new_spec_edges[SE_LATCH], loop->header); - set_immediate_dominator (loops->cfg.dom, new_bbs[0], latch); + set_immediate_dominator (CDI_DOMINATORS, new_bbs[0], latch); latch = loop->latch = new_bbs[1]; e = latch_edge = new_spec_edges[SE_LATCH]; } @@ -1028,7 +1009,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, redirect_edge_and_branch_force (new_spec_edges[SE_LATCH], loop->header); redirect_edge_and_branch_force (e, new_bbs[0]); - set_immediate_dominator (loops->cfg.dom, new_bbs[0], e->src); + set_immediate_dominator (CDI_DOMINATORS, new_bbs[0], e->src); e = new_spec_edges[SE_LATCH]; } @@ -1056,7 +1037,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, /* Update the original loop. */ if (!is_latch) - set_immediate_dominator (loops->cfg.dom, e->dest, e->src); + set_immediate_dominator (CDI_DOMINATORS, e->dest, e->src); if (flags & DLTHE_FLAG_UPDATE_FREQ) { scale_bbs_frequencies (bbs, n, scale_main, REG_BR_PROB_BASE); @@ -1070,15 +1051,15 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, int n_dom_bbs,j; bb = bbs[i]; - n_dom_bbs = get_dominated_by (loops->cfg.dom, bb, &dom_bbs); + n_dom_bbs = get_dominated_by (CDI_DOMINATORS, bb, &dom_bbs); for (j = 0; j < n_dom_bbs; j++) { dominated = dom_bbs[j]; if (flow_bb_inside_loop_p (loop, dominated)) continue; dom_bb = nearest_common_dominator ( - loops->cfg.dom, first_active[i], first_active_latch); - set_immediate_dominator (loops->cfg.dom, dominated, dom_bb); + CDI_DOMINATORS, first_active[i], first_active_latch); + set_immediate_dominator (CDI_DOMINATORS, dominated, dom_bb); } free (dom_bbs); } @@ -1094,7 +1075,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, entry; otherwise we also force preheader block to have only one successor. The function also updates dominators stored in DOM. */ static basic_block -create_preheader (struct loop *loop, dominance_info dom, int flags) +create_preheader (struct loop *loop, int flags) { edge e, fallthru; basic_block dummy; @@ -1141,7 +1122,7 @@ create_preheader (struct loop *loop, dominance_info dom, int flags) if (ploop->latch == dummy) ploop->latch = fallthru->dest; - add_to_dominance_info (dom, fallthru->dest); + add_to_dominance_info (CDI_DOMINATORS, fallthru->dest); /* Redirect edges. */ for (e = dummy->pred; e; e = e->pred_next) @@ -1159,15 +1140,15 @@ create_preheader (struct loop *loop, dominance_info dom, int flags) jump = redirect_edge_and_branch_force (e, loop->header); if (jump) { - add_to_dominance_info (dom, jump); - set_immediate_dominator (dom, jump, src); + add_to_dominance_info (CDI_DOMINATORS, jump); + set_immediate_dominator (CDI_DOMINATORS, jump, src); add_bb_to_loop (jump, loop); loop->latch = jump; } /* Update structures. */ - redirect_immediate_dominators (dom, dummy, loop->header); - set_immediate_dominator (dom, loop->header, dummy); + redirect_immediate_dominators (CDI_DOMINATORS, dummy, loop->header); + set_immediate_dominator (CDI_DOMINATORS, loop->header, dummy); loop->header->loop_father = loop; add_bb_to_loop (dummy, cloop); if (rtl_dump_file) @@ -1184,7 +1165,7 @@ create_preheaders (struct loops *loops, int flags) { unsigned i; for (i = 1; i < loops->num; i++) - create_preheader (loops->parray[i], loops->cfg.dom, flags); + create_preheader (loops->parray[i], flags); loops->state |= LOOPS_HAVE_PREHEADERS; } @@ -1207,7 +1188,7 @@ force_single_succ_latches (struct loops *loops) for (e = loop->header->pred; e->src != loop->latch; e = e->pred_next) continue; - loop_split_edge_with (e, NULL_RTX, loops); + loop_split_edge_with (e, NULL_RTX); } loops->state |= LOOPS_HAVE_SIMPLE_LATCHES; } @@ -1217,7 +1198,7 @@ force_single_succ_latches (struct loops *loops) 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, struct loops *loops) +loop_split_edge_with (edge e, rtx insns) { basic_block src, dest, new_bb; struct loop *loop_c; @@ -1231,7 +1212,7 @@ loop_split_edge_with (edge e, rtx insns, struct loops *loops) /* Create basic block for it. */ new_bb = split_edge (e); - add_to_dominance_info (loops->cfg.dom, new_bb); + add_to_dominance_info (CDI_DOMINATORS, new_bb); add_bb_to_loop (new_bb, loop_c); new_bb->flags = insns ? BB_SUPERBLOCK : 0; @@ -1245,9 +1226,9 @@ loop_split_edge_with (edge e, rtx insns, struct loops *loops) if (insns) emit_insn_after (insns, BB_END (new_bb)); - set_immediate_dominator (loops->cfg.dom, new_bb, src); - set_immediate_dominator (loops->cfg.dom, dest, - recount_dominator (loops->cfg.dom, dest)); + set_immediate_dominator (CDI_DOMINATORS, new_bb, src); + set_immediate_dominator (CDI_DOMINATORS, dest, + recount_dominator (CDI_DOMINATORS, dest)); if (dest->loop_father->latch == src) dest->loop_father->latch = new_bb; diff --git a/gcc/dominance.c b/gcc/dominance.c index 38182ef..1b6c9fd 100644 --- a/gcc/dominance.c +++ b/gcc/dominance.c @@ -43,16 +43,8 @@ #include "errors.h" #include "et-forest.h" -struct dominance_info -{ - et_forest_t forest; - varray_type varray; -}; - -#define BB_NODE(info, bb) \ - ((et_forest_node_t)VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2)) -#define SET_BB_NODE(info, bb, node) \ - (VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2) = (node)) +/* Whether the dominators and the postdominators are available. */ +enum dom_state dom_computed[2]; /* We name our nodes with integers, beginning with 1. Zero is reserved for 'undefined' or 'end of list'. The name of each node is given by the dfs @@ -124,7 +116,7 @@ static void compress (struct dom_info *, TBB); static TBB eval (struct dom_info *, TBB); static void link_roots (struct dom_info *, TBB, TBB); static void calc_idoms (struct dom_info *, enum cdi_direction); -void debug_dominance_info (dominance_info); +void debug_dominance_info (enum cdi_direction); /* Helper macro for allocating and initializing an array, for aesthetic reasons. */ @@ -526,172 +518,250 @@ calc_idoms (struct dom_info *di, enum cdi_direction reverse) di->dom[v] = di->dom[di->dom[v]]; } -/* The main entry point into this module. IDOM is an integer array with room - for last_basic_block integers, DOMS is a preallocated sbitmap array having - room for last_basic_block^2 bits, and POST is true if the caller wants to - know post-dominators. +/* Assign dfs numbers starting from NUM to NODE and its sons. */ + +static void +assign_dfs_numbers (struct et_node *node, int *num) +{ + struct et_node *son; + + node->dfs_num_in = (*num)++; + + if (node->son) + { + assign_dfs_numbers (node->son, num); + for (son = node->son->right; son != node->son; son = son->right) + assign_dfs_numbers (son, num); + } - On return IDOM[i] will be the BB->index of the immediate (post) dominator - of basic block i, and DOMS[i] will have set bit j if basic block j is a - (post)dominator for block i. + node->dfs_num_out = (*num)++; +} - Either IDOM or DOMS may be NULL (meaning the caller is not interested in - immediate resp. all dominators). */ +/* Compute the data neccesary for fast resolving of dominator queries in a + static dominator tree. */ -dominance_info -calculate_dominance_info (enum cdi_direction reverse) +static void +compute_dom_fast_query (enum cdi_direction dir) +{ + int num = 0; + basic_block bb; + + if (dom_computed[dir] < DOM_NO_FAST_QUERY) + abort (); + + if (dom_computed[dir] == DOM_OK) + return; + + FOR_ALL_BB (bb) + { + if (!bb->dom[dir]->father) + assign_dfs_numbers (bb->dom[dir], &num); + } + + dom_computed[dir] = DOM_OK; +} + +/* The main entry point into this module. DIR is set depending on whether + we want to compute dominators or postdominators. */ + +void +calculate_dominance_info (enum cdi_direction dir) { struct dom_info di; - dominance_info info; basic_block b; - /* Allocate structure for dominance information. */ - info = xmalloc (sizeof (struct dominance_info)); - info->forest = et_forest_create (); - VARRAY_GENERIC_PTR_INIT (info->varray, last_basic_block + 3, "dominance info"); + if (dom_computed[dir] == DOM_OK) + return; - /* Add the two well-known basic blocks. */ - SET_BB_NODE (info, ENTRY_BLOCK_PTR, et_forest_add_node (info->forest, - ENTRY_BLOCK_PTR)); - SET_BB_NODE (info, EXIT_BLOCK_PTR, et_forest_add_node (info->forest, - EXIT_BLOCK_PTR)); - FOR_EACH_BB (b) - SET_BB_NODE (info, b, et_forest_add_node (info->forest, b)); + if (dom_computed[dir] != DOM_NO_FAST_QUERY) + { + if (dom_computed[dir] != DOM_NONE) + free_dominance_info (dir); - init_dom_info (&di); - calc_dfs_tree (&di, reverse); - calc_idoms (&di, reverse); + FOR_ALL_BB (b) + { + b->dom[dir] = et_new_tree (b); + } + init_dom_info (&di); + calc_dfs_tree (&di, dir); + calc_idoms (&di, dir); - FOR_EACH_BB (b) - { - TBB d = di.dom[di.dfs_order[b->index]]; + FOR_EACH_BB (b) + { + TBB d = di.dom[di.dfs_order[b->index]]; + + if (di.dfs_to_bb[d]) + et_set_father (b->dom[dir], di.dfs_to_bb[d]->dom[dir]); + } - if (di.dfs_to_bb[d]) - et_forest_add_edge (info->forest, BB_NODE (info, di.dfs_to_bb[d]), BB_NODE (info, b)); + free_dom_info (&di); + dom_computed[dir] = DOM_NO_FAST_QUERY; } - free_dom_info (&di); - return info; + compute_dom_fast_query (dir); } -/* Free dominance information. */ +/* Free dominance information for direction DIR. */ void -free_dominance_info (dominance_info info) +free_dominance_info (enum cdi_direction dir) { basic_block bb; - /* Allow users to create new basic block without setting up the dominance - information for them. */ - FOR_EACH_BB (bb) - if (bb->index < (int)(info->varray->num_elements - 2) - && BB_NODE (info, bb)) - delete_from_dominance_info (info, bb); - delete_from_dominance_info (info, ENTRY_BLOCK_PTR); - delete_from_dominance_info (info, EXIT_BLOCK_PTR); - et_forest_delete (info->forest); - VARRAY_GROW (info->varray, 0); - free (info); + if (!dom_computed[dir]) + return; + + FOR_ALL_BB (bb) + { + delete_from_dominance_info (dir, bb); + } + + dom_computed[dir] = DOM_NONE; } /* Return the immediate dominator of basic block BB. */ basic_block -get_immediate_dominator (dominance_info dom, basic_block bb) +get_immediate_dominator (enum cdi_direction dir, basic_block bb) { - return et_forest_node_value (dom->forest, - et_forest_parent (dom->forest, - BB_NODE (dom, bb))); + struct et_node *node = bb->dom[dir]; + + if (!dom_computed[dir]) + abort (); + + if (!node->father) + return NULL; + + return node->father->data; } /* Set the immediate dominator of the block possibly removing existing edge. NULL can be used to remove any edge. */ inline void -set_immediate_dominator (dominance_info dom, basic_block bb, basic_block dominated_by) +set_immediate_dominator (enum cdi_direction dir, basic_block bb, + basic_block dominated_by) { - void *aux_bb_node; - et_forest_node_t bb_node = BB_NODE (dom, bb); + struct et_node *node = bb->dom[dir]; + + if (!dom_computed[dir]) + abort (); - aux_bb_node = et_forest_parent (dom->forest, bb_node); - if (aux_bb_node) - et_forest_remove_edge (dom->forest, aux_bb_node, bb_node); - if (dominated_by != NULL) + if (node->father) { - if (bb == dominated_by) - abort (); - if (!et_forest_add_edge (dom->forest, BB_NODE (dom, dominated_by), bb_node)) - abort (); + if (node->father->data == dominated_by) + return; + et_split (node); } + + if (dominated_by) + et_set_father (node, dominated_by->dom[dir]); + + if (dom_computed[dir] == DOM_OK) + dom_computed[dir] = DOM_NO_FAST_QUERY; } -/* Store all basic blocks dominated by BB into BBS and return their number. */ +/* Store all basic blocks immediatelly dominated by BB into BBS and return + their number. */ int -get_dominated_by (dominance_info dom, basic_block bb, basic_block **bbs) +get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs) { - int n, i; + int n; + struct et_node *node = bb->dom[dir], *son = node->son, *ason; + + if (!dom_computed[dir]) + abort (); + + if (!son) + { + *bbs = NULL; + return 0; + } + + for (ason = son->right, n = 1; ason != son; ason = ason->right) + n++; + + *bbs = xmalloc (n * sizeof (basic_block)); + (*bbs)[0] = son->data; + for (ason = son->right, n = 1; ason != son; ason = ason->right) + (*bbs)[n++] = ason->data; - *bbs = xmalloc (n_basic_blocks * sizeof (basic_block)); - n = et_forest_enumerate_sons (dom->forest, BB_NODE (dom, bb), (et_forest_node_t *)*bbs); - for (i = 0; i < n; i++) - (*bbs)[i] = et_forest_node_value (dom->forest, (et_forest_node_t)(*bbs)[i]); return n; } /* Redirect all edges pointing to BB to TO. */ void -redirect_immediate_dominators (dominance_info dom, basic_block bb, basic_block to) +redirect_immediate_dominators (enum cdi_direction dir, basic_block bb, + basic_block to) { - et_forest_node_t *bbs = xmalloc (n_basic_blocks * sizeof (basic_block)); - et_forest_node_t node = BB_NODE (dom, bb); - et_forest_node_t node2 = BB_NODE (dom, to); - int n = et_forest_enumerate_sons (dom->forest, node, bbs); - int i; + struct et_node *bb_node = bb->dom[dir], *to_node = to->dom[dir], *son; + + if (!dom_computed[dir]) + abort (); - for (i = 0; i < n; i++) + if (!bb_node->son) + return; + + while (bb_node->son) { - et_forest_remove_edge (dom->forest, node, bbs[i]); - et_forest_add_edge (dom->forest, node2, bbs[i]); + son = bb_node->son; + + et_split (son); + et_set_father (son, to_node); } - free (bbs); + + if (dom_computed[dir] == DOM_OK) + dom_computed[dir] = DOM_NO_FAST_QUERY; } /* Find first basic block in the tree dominating both BB1 and BB2. */ basic_block -nearest_common_dominator (dominance_info dom, basic_block bb1, basic_block bb2) +nearest_common_dominator (enum cdi_direction dir, basic_block bb1, basic_block bb2) { + if (!dom_computed[dir]) + abort (); + if (!bb1) return bb2; if (!bb2) return bb1; - return et_forest_node_value (dom->forest, - et_forest_common_ancestor (dom->forest, - BB_NODE (dom, bb1), - BB_NODE (dom, - bb2))); + + return et_nca (bb1->dom[dir], bb2->dom[dir])->data; } /* Return TRUE in case BB1 is dominated by BB2. */ bool -dominated_by_p (dominance_info dom, basic_block bb1, basic_block bb2) +dominated_by_p (enum cdi_direction dir, basic_block bb1, basic_block bb2) { - return nearest_common_dominator (dom, bb1, bb2) == bb2; + struct et_node *n1 = bb1->dom[dir], *n2 = bb2->dom[dir]; + + if (!dom_computed[dir]) + abort (); + + if (dom_computed[dir] == DOM_OK) + return (n1->dfs_num_in >= n2->dfs_num_in + && n1->dfs_num_out <= n2->dfs_num_out); + + return et_below (n1, n2); } /* Verify invariants of dominator structure. */ void -verify_dominators (dominance_info dom) +verify_dominators (enum cdi_direction dir) { int err = 0; basic_block bb; + if (!dom_computed[dir]) + abort (); + FOR_EACH_BB (bb) { basic_block dom_bb; - dom_bb = recount_dominator (dom, bb); - if (dom_bb != get_immediate_dominator (dom, bb)) + dom_bb = recount_dominator (dir, bb); + if (dom_bb != get_immediate_dominator (dir, bb)) { error ("dominator of %d should be %d, not %d", - bb->index, dom_bb->index, get_immediate_dominator(dom, bb)->index); + bb->index, dom_bb->index, get_immediate_dominator(dir, bb)->index); err = 1; } } @@ -701,15 +771,18 @@ verify_dominators (dominance_info dom) /* Recount dominator of BB. */ basic_block -recount_dominator (dominance_info dom, basic_block bb) +recount_dominator (enum cdi_direction dir, basic_block bb) { basic_block dom_bb = NULL; edge e; + if (!dom_computed[dir]) + abort (); + for (e = bb->pred; e; e = e->pred_next) { - if (!dominated_by_p (dom, e->src, bb)) - dom_bb = nearest_common_dominator (dom, dom_bb, e->src); + if (!dominated_by_p (dir, e->src, bb)) + dom_bb = nearest_common_dominator (dir, dom_bb, e->src); } return dom_bb; @@ -718,50 +791,85 @@ recount_dominator (dominance_info dom, basic_block bb) /* Iteratively recount dominators of BBS. The change is supposed to be local and not to grow further. */ void -iterate_fix_dominators (dominance_info dom, basic_block *bbs, int n) +iterate_fix_dominators (enum cdi_direction dir, basic_block *bbs, int n) { int i, changed = 1; basic_block old_dom, new_dom; + if (!dom_computed[dir]) + abort (); + while (changed) { changed = 0; for (i = 0; i < n; i++) { - old_dom = get_immediate_dominator (dom, bbs[i]); - new_dom = recount_dominator (dom, bbs[i]); + old_dom = get_immediate_dominator (dir, bbs[i]); + new_dom = recount_dominator (dir, bbs[i]); if (old_dom != new_dom) { changed = 1; - set_immediate_dominator (dom, bbs[i], new_dom); + set_immediate_dominator (dir, bbs[i], new_dom); } } } } void -add_to_dominance_info (dominance_info dom, basic_block bb) +add_to_dominance_info (enum cdi_direction dir, basic_block bb) { - VARRAY_GROW (dom->varray, last_basic_block + 3); -#ifdef ENABLE_CHECKING - if (BB_NODE (dom, bb)) + if (!dom_computed[dir]) abort (); -#endif - SET_BB_NODE (dom, bb, et_forest_add_node (dom->forest, bb)); + + if (bb->dom[dir]) + abort (); + + bb->dom[dir] = et_new_tree (bb); + + if (dom_computed[dir] == DOM_OK) + dom_computed[dir] = DOM_NO_FAST_QUERY; } void -delete_from_dominance_info (dominance_info dom, basic_block bb) +delete_from_dominance_info (enum cdi_direction dir, basic_block bb) +{ + if (!dom_computed[dir]) + abort (); + + et_free_tree (bb->dom[dir]); + bb->dom[dir] = NULL; + + if (dom_computed[dir] == DOM_OK) + dom_computed[dir] = DOM_NO_FAST_QUERY; +} + +/* Returns the first son of BB in the dominator or postdominator tree + as determined by DIR. */ + +basic_block +first_dom_son (enum cdi_direction dir, basic_block bb) { - et_forest_remove_node (dom->forest, BB_NODE (dom, bb)); - SET_BB_NODE (dom, bb, NULL); + struct et_node *son = bb->dom[dir]->son; + + return son ? son->data : NULL; +} + +/* Returns the next dominance son after BB in the dominator or postdominator + tree as determined by DIR, or NULL if it was the last one. */ + +basic_block +next_dom_son (enum cdi_direction dir, basic_block bb) +{ + struct et_node *next = bb->dom[dir]->right; + + return next->father->son == next ? NULL : next->data; } void -debug_dominance_info (dominance_info dom) +debug_dominance_info (enum cdi_direction dir) { basic_block bb, bb2; FOR_EACH_BB (bb) - if ((bb2 = get_immediate_dominator (dom, bb))) + if ((bb2 = get_immediate_dominator (dir, bb))) fprintf (stderr, "%i %i\n", bb->index, bb2->index); } diff --git a/gcc/et-forest.c b/gcc/et-forest.c index ffdce1d..ea7793f 100644 --- a/gcc/et-forest.c +++ b/gcc/et-forest.c @@ -30,638 +30,714 @@ Boston, MA 02111-1307, USA. #include "et-forest.h" #include "alloc-pool.h" -struct et_forest_occurrence; -typedef struct et_forest_occurrence* et_forest_occurrence_t; +/* We do not enable this with ENABLE_CHECKING, since it is awfully slow. */ +#undef DEBUG_ET -/* The ET-forest type. */ -struct et_forest -{ - /* Linked list of nodes is used to destroy the structure. */ - int nnodes; - alloc_pool node_pool; - alloc_pool occur_pool; -}; +#ifdef DEBUG_ET +#include "basic-block.h" +#endif -/* Single occurrence of node in ET-forest. - A single node may have multiple occurrences. - */ -struct et_forest_occurrence +/* The occurence of a node in the et tree. */ +struct et_occ { - /* Parent in the splay-tree. */ - et_forest_occurrence_t parent; + struct et_node *of; /* The node. */ + + struct et_occ *parent; /* Parent in the splay-tree. */ + struct et_occ *prev; /* Left son in the splay-tree. */ + struct et_occ *next; /* Right son in the splay-tree. */ + + int depth; /* The depth of the node is the sum of depth + fields on the path to the root. */ + int min; /* The minimum value of the depth in the subtree + is obtained by adding sum of depth fields + on the path to the root. */ + struct et_occ *min_occ; /* The occurence in the subtree with the minimal + depth. */ +}; - /* Children in the splay-tree. */ - et_forest_occurrence_t left, right; +static alloc_pool et_nodes; +static alloc_pool et_occurences; - /* Counts of vertices in the two splay-subtrees. */ - int count_left, count_right; +/* Changes depth of OCC to D. */ - /* Next occurrence of this node in the sequence. */ - et_forest_occurrence_t next; +static inline void +set_depth (struct et_occ *occ, int d) +{ + if (!occ) + return; - /* The node, which this occurrence is of. */ - et_forest_node_t node; -}; + occ->min += d - occ->depth; + occ->depth = d; +} +/* Adds D to the depth of OCC. */ -/* ET-forest node. */ -struct et_forest_node +static inline void +set_depth_add (struct et_occ *occ, int d) { - et_forest_t forest; - void *value; - - /* First and last occurrence of this node in the sequence. */ - et_forest_occurrence_t first, last; -}; + if (!occ) + return; + occ->min += d; + occ->depth += d; +} -static et_forest_occurrence_t splay (et_forest_occurrence_t); -static void remove_all_occurrences (et_forest_t, et_forest_node_t); -static inline et_forest_occurrence_t find_leftmost_node - (et_forest_occurrence_t); -static inline et_forest_occurrence_t find_rightmost_node - (et_forest_occurrence_t); -static int calculate_value (et_forest_occurrence_t); +/* Sets prev field of OCC to P. */ -/* Return leftmost node present in the tree roted by OCC. */ -static inline et_forest_occurrence_t -find_leftmost_node (et_forest_occurrence_t occ) +static inline void +set_prev (struct et_occ *occ, struct et_occ *t) { - while (occ->left) - occ = occ->left; +#ifdef DEBUG_ET + if (occ == t) + abort (); +#endif - return occ; + occ->prev = t; + if (t) + t->parent = occ; } -/* Return rightmost node present in the tree roted by OCC. */ -static inline et_forest_occurrence_t -find_rightmost_node (et_forest_occurrence_t occ) +/* Sets next field of OCC to P. */ + +static inline void +set_next (struct et_occ *occ, struct et_occ *t) { - while (occ->right) - occ = occ->right; - return occ; +#ifdef DEBUG_ET + if (occ == t) + abort (); +#endif + + occ->next = t; + if (t) + t->parent = occ; } +/* Recompute minimum for occurence OCC. */ -/* Operation splay for splay tree structure representing occurrences. */ -static et_forest_occurrence_t -splay (et_forest_occurrence_t node) +static inline void +et_recomp_min (struct et_occ *occ) { - et_forest_occurrence_t parent; - et_forest_occurrence_t grandparent; + struct et_occ *mson = occ->prev; - while (1) - { - parent = node->parent; + if (!mson + || (occ->next + && mson->min > occ->next->min)) + mson = occ->next; - if (! parent) - return node; /* node == root. */ + if (mson && mson->min < 0) + { + occ->min = mson->min + occ->depth; + occ->min_occ = mson->min_occ; + } + else + { + occ->min = occ->depth; + occ->min_occ = occ; + } +} - grandparent = parent->parent; +#ifdef DEBUG_ET +/* Checks whether neighbourhood of OCC seems sane. */ - if (! grandparent) - break; +static void +et_check_occ_sanity (struct et_occ *occ) +{ + if (!occ) + return; - /* Now there are four possible combinations: */ + if (occ->parent == occ) + abort (); - if (node == parent->left) - { - if (parent == grandparent->left) - { - et_forest_occurrence_t node1, node2; - int count1, count2; - - node1 = node->right; - count1 = node->count_right; - node2 = parent->right; - count2 = parent->count_right; - - grandparent->left = node2; - grandparent->count_left = count2; - if (node2) - node2->parent = grandparent; - parent->left = node1; - parent->count_left = count1; - if (node1) - node1->parent = parent; - parent->right = grandparent; - parent->count_right = count2 + grandparent->count_right + 1; - node->right = parent; - node->count_right = count1 + parent->count_right + 1; - - node->parent = grandparent->parent; - parent->parent = node; - grandparent->parent = parent; - - if (node->parent) - { - if (node->parent->left == grandparent) - node->parent->left = node; - else - node->parent->right = node; - } - } - else - { - /* parent == grandparent->right && node == parent->left*/ - et_forest_occurrence_t node1, node2; - int count1, count2; - - node1 = node->left; - count1 = node->count_left; - node2 = node->right; - count2 = node->count_right; - - grandparent->right = node1; - grandparent->count_right = count1; - if (node1) - node1->parent = grandparent; - parent->left = node2; - parent->count_left = count2; - if (node2) - node2->parent = parent; - node->left = grandparent; - node->count_left = grandparent->count_left + count1 + 1; - node->right = parent; - node->count_right = parent->count_right + count2 + 1; - - node->parent = grandparent->parent; - parent->parent = node; - grandparent->parent = node; - - if (node->parent) - { - if (node->parent->left == grandparent) - node->parent->left = node; - else - node->parent->right = node; - } - } - } - else - { - /* node == parent->right. */ - if (parent == grandparent->left) - { - et_forest_occurrence_t node1, node2; - int count1, count2; - - node1 = node->left; - count1 = node->count_left; - node2 = node->right; - count2 = node->count_right; - - parent->right = node1; - parent->count_right = count1; - if (node1) - node1->parent = parent; - grandparent->left = node2; - grandparent->count_left = count2; - if (node2) - node2->parent = grandparent; - node->left = parent; - node->count_left = parent->count_left + count1 + 1; - node->right = grandparent; - node->count_right = grandparent->count_right + count2 + 1; - - node->parent = grandparent->parent; - parent->parent = node; - grandparent->parent = node; - - if (node->parent) - { - if (node->parent->left == grandparent) - node->parent->left = node; - else - node->parent->right = node; - } - } - else - { - /* parent == grandparent->right && node == parent->right*/ - et_forest_occurrence_t node1, node2; - int count1, count2; - - node1 = node->left; - count1 = node->count_left; - node2 = parent->left; - count2 = parent->count_left; - - grandparent->right = node2; - grandparent->count_right = count2; - if (node2) - node2->parent = grandparent; - parent->right = node1; - parent->count_right = count1; - if (node1) - node1->parent = parent; - parent->left = grandparent; - parent->count_left = count2 + grandparent->count_left + 1; - node->left = parent; - node->count_left = count1 + parent->count_left + 1; - - node->parent = grandparent->parent; - parent->parent = node; - grandparent->parent = parent; - - if (node->parent) - { - if (node->parent->left == grandparent) - node->parent->left = node; - else - node->parent->right = node; - } - } - } + if (occ->prev == occ) + abort (); - } + if (occ->next == occ) + abort (); - /* parent == root. */ - /* There are two possible combinations: */ + if (occ->next && occ->next == occ->prev) + abort (); - if (node == parent->left) + if (occ->next) { - et_forest_occurrence_t node1; - int count1; - - node1 = node->right; - count1 = node->count_right; - - parent->left = node1; - parent->count_left = count1; - if (node1) - node1->parent = parent; - node->right = parent; - node->count_right = parent->count_right + 1 + count1; - node->parent = parent->parent; /* the same as = 0; */ - parent->parent = node; - - if (node->parent) - { - if (node->parent->left == parent) - node->parent->left = node; - else - node->parent->right = node; - } + if (occ->next == occ->parent) + abort (); + + if (occ->next->parent != occ) + abort (); } - else + + if (occ->prev) { - /* node == parent->right. */ - et_forest_occurrence_t node1; - int count1; - - node1 = node->left; - count1 = node->count_left; - - parent->right = node1; - parent->count_right = count1; - if (node1) - node1->parent = parent; - node->left = parent; - node->count_left = parent->count_left + 1 + count1; - node->parent = parent->parent; /* the same as = 0; */ - parent->parent = node; - - if (node->parent) - { - if (node->parent->left == parent) - node->parent->left = node; - else - node->parent->right = node; - } + if (occ->prev == occ->parent) + abort (); + + if (occ->prev->parent != occ) + abort (); } - return node; + if (occ->parent + && occ->parent->prev != occ + && occ->parent->next != occ) + abort (); } -/* Remove all occurrences of the given node before destroying the node. */ +/* Checks whether tree rooted at OCC is sane. */ + static void -remove_all_occurrences (et_forest_t forest, et_forest_node_t forest_node) +et_check_sanity (struct et_occ *occ) { - et_forest_occurrence_t first = forest_node->first; - et_forest_occurrence_t last = forest_node->last; - et_forest_occurrence_t node; + et_check_occ_sanity (occ); + if (occ->prev) + et_check_sanity (occ->prev); + if (occ->next) + et_check_sanity (occ->next); +} - splay (first); +/* Checks whether tree containing OCC is sane. */ - if (first->left) - first->left->parent = 0; - if (first->right) - first->right->parent = 0; +static void +et_check_tree_sanity (struct et_occ *occ) +{ + while (occ->parent) + occ = occ->parent; - if (last != first) - { - splay (last); + et_check_sanity (occ); +} - if (last->left) - last->left->parent = 0; - if (last->right) - last->right->parent = 0; - } +/* For recording the paths. */ - if (last->right && first->left) /* actually, first->left would suffice. */ - { - /* Need to join them. */ - et_forest_occurrence_t prev_node, next_node; - - prev_node = splay (find_rightmost_node (first->left)); - next_node = splay (find_leftmost_node (last->right)); - /* prev_node and next_node are consecutive occurrences - of the same node. */ - if (prev_node->next != next_node) - abort (); +static int len; +static void *datas[100000]; +static int depths[100000]; - prev_node->right = next_node->right; - prev_node->count_right = next_node->count_right; - prev_node->next = next_node->next; - if (prev_node->right) - prev_node->right->parent = prev_node; +/* Records the path represented by OCC, with depth incremented by DEPTH. */ - if (prev_node->node->last == next_node) - prev_node->node->last = prev_node; +static int +record_path_before_1 (struct et_occ *occ, int depth) +{ + int mn, m; - pool_free (forest->occur_pool, next_node); + depth += occ->depth; + mn = depth; + + if (occ->prev) + { + m = record_path_before_1 (occ->prev, depth); + if (m < mn) + mn = m; } - if (first != last) + fprintf (stderr, "%d (%d); ", ((basic_block) occ->of->data)->index, depth); + depths[len] = depth; + datas[len] = occ->of; + len++; + + if (occ->next) { - node = first->next; + m = record_path_before_1 (occ->next, depth); + if (m < mn) + mn = m; + } - while (node != last) - { - et_forest_occurrence_t next_node; + if (mn != occ->min + depth - occ->depth) + abort (); - splay (node); + return mn; +} - if (node->left) - node->left->parent = 0; - if (node->right) - node->right->parent = 0; +/* Records the path represented by a tree containing OCC. */ - next_node = node->next; - pool_free (forest->occur_pool, node); - node = next_node; - } - } +static void +record_path_before (struct et_occ *occ) +{ + while (occ->parent) + occ = occ->parent; - pool_free (forest->occur_pool, first); - if (first != last) - pool_free (forest->occur_pool, last); + len = 0; + record_path_before_1 (occ, 0); + fprintf (stderr, "\n"); } -/* Calculate ET value of the given node. */ -static inline int -calculate_value (et_forest_occurrence_t node) +/* Checks whether the path represented by OCC, with depth incremented by DEPTH, + was not changed since the last recording. */ + +static int +check_path_after_1 (struct et_occ *occ, int depth) { - int value = node->count_left; + int mn, m; + + depth += occ->depth; + mn = depth; - while (node->parent) + if (occ->next) { - if (node == node->parent->right) - value += node->parent->count_left + 1; + m = check_path_after_1 (occ->next, depth); + if (m < mn) + mn = m; + } - node = node->parent; + len--; + if (depths[len] != depth + || datas[len] != occ->of) + abort (); + + if (occ->prev) + { + m = check_path_after_1 (occ->prev, depth); + if (m < mn) + mn = m; } - return value; + if (mn != occ->min + depth - occ->depth) + abort (); + + return mn; } +/* Checks whether the path represented by a tree containing OCC was + not changed since the last recording. */ + +static void +check_path_after (struct et_occ *occ) +{ + while (occ->parent) + occ = occ->parent; + + check_path_after_1 (occ, 0); + if (len != 0) + abort (); +} +#endif +/* Splay the occurence OCC to the root of the tree. */ -/* Create ET-forest structure. */ -et_forest_t -et_forest_create (void) +static inline void +et_splay (struct et_occ *occ) { - et_forest_t forest = xmalloc (sizeof (struct et_forest)); + struct et_occ *f, *gf, *ggf; + int occ_depth, f_depth, gf_depth; + +#ifdef DEBUG_ET + record_path_before (occ); + et_check_tree_sanity (occ); +#endif + + while (occ->parent) + { + occ_depth = occ->depth; - forest->nnodes = 0; - forest->occur_pool = create_alloc_pool ("et_forest_occurrence pool", sizeof (struct et_forest_occurrence), 300); - forest->node_pool = create_alloc_pool ("et_forest_node pool", sizeof (struct et_forest_node), 300); - return forest; -} + f = occ->parent; + f_depth = f->depth; + gf = f->parent; + if (!gf) + { + set_depth_add (occ, f_depth); + occ->min_occ = f->min_occ; + occ->min = f->min; -/* Deallocate the structure. */ -void -et_forest_delete (et_forest_t forest) + if (f->prev == occ) + { + /* zig */ + set_prev (f, occ->next); + set_next (occ, f); + set_depth_add (f->prev, occ_depth); + } + else + { + /* zag */ + set_next (f, occ->prev); + set_prev (occ, f); + set_depth_add (f->next, occ_depth); + } + set_depth (f, -occ_depth); + occ->parent = NULL; + + et_recomp_min (f); +#ifdef DEBUG_ET + et_check_tree_sanity (occ); + check_path_after (occ); +#endif + return; + } + + gf_depth = gf->depth; + + set_depth_add (occ, f_depth + gf_depth); + occ->min_occ = gf->min_occ; + occ->min = gf->min; + + ggf = gf->parent; + + if (gf->prev == f) + { + if (f->prev == occ) + { + /* zig zig */ + set_prev (gf, f->next); + set_prev (f, occ->next); + set_next (occ, f); + set_next (f, gf); + + set_depth (f, -occ_depth); + set_depth_add (f->prev, occ_depth); + set_depth (gf, -f_depth); + set_depth_add (gf->prev, f_depth); + } + else + { + /* zag zig */ + set_prev (gf, occ->next); + set_next (f, occ->prev); + set_prev (occ, f); + set_next (occ, gf); + + set_depth (f, -occ_depth); + set_depth_add (f->next, occ_depth); + set_depth (gf, -occ_depth - f_depth); + set_depth_add (gf->prev, occ_depth + f_depth); + } + } + else + { + if (f->prev == occ) + { + /* zig zag */ + set_next (gf, occ->prev); + set_prev (f, occ->next); + set_prev (occ, gf); + set_next (occ, f); + + set_depth (f, -occ_depth); + set_depth_add (f->prev, occ_depth); + set_depth (gf, -occ_depth - f_depth); + set_depth_add (gf->next, occ_depth + f_depth); + } + else + { + /* zag zag */ + set_next (gf, f->prev); + set_next (f, occ->prev); + set_prev (occ, f); + set_prev (f, gf); + + set_depth (f, -occ_depth); + set_depth_add (f->next, occ_depth); + set_depth (gf, -f_depth); + set_depth_add (gf->next, f_depth); + } + } + + occ->parent = ggf; + if (ggf) + { + if (ggf->prev == gf) + ggf->prev = occ; + else + ggf->next = occ; + } + + et_recomp_min (gf); + et_recomp_min (f); +#ifdef DEBUG_ET + et_check_tree_sanity (occ); +#endif + } + +#ifdef DEBUG_ET + et_check_sanity (occ); + check_path_after (occ); +#endif +} + +/* Create a new et tree occurence of NODE. */ + +static struct et_occ * +et_new_occ (struct et_node *node) { - if (forest->nnodes) - abort (); - free_alloc_pool (forest->occur_pool); - free_alloc_pool (forest->node_pool); - free (forest); + struct et_occ *nw; + + if (!et_occurences) + et_occurences = create_alloc_pool ("et_occ pool", sizeof (struct et_occ), 300); + nw = pool_alloc (et_occurences); + + nw->of = node; + nw->parent = NULL; + nw->prev = NULL; + nw->next = NULL; + + nw->depth = 0; + nw->min_occ = nw; + nw->min = 0; + + return nw; } -/* Create new node with VALUE and return the edge. - Return NULL when memory allocation failed. */ -et_forest_node_t -et_forest_add_node (et_forest_t forest, void *value) +/* Create a new et tree containing DATA. */ + +struct et_node * +et_new_tree (void *data) { - /* Create node with one occurrence. */ - et_forest_node_t node; - et_forest_occurrence_t occ; - - node = pool_alloc (forest->node_pool); - occ = pool_alloc (forest->occur_pool); - - node->first = node->last = occ; - node->value = value; - forest->nnodes++; - - occ->node = node; - occ->left = occ->right = occ->parent = 0; - occ->next = 0; - occ->count_left = occ->count_right = 0; - return node; + struct et_node *nw; + + if (!et_nodes) + et_nodes = create_alloc_pool ("et_node pool", sizeof (struct et_node), 300); + nw = pool_alloc (et_nodes); + + nw->data = data; + nw->father = NULL; + nw->left = NULL; + nw->right = NULL; + nw->son = NULL; + + nw->rightmost_occ = et_new_occ (nw); + nw->parent_occ = NULL; + + return nw; } -/* Add new edge to the tree, return 1 if successful. - 0 indicates that creation of the edge will close the cycle in graph. */ -int -et_forest_add_edge (et_forest_t forest ATTRIBUTE_UNUSED, - et_forest_node_t parent_node, et_forest_node_t child_node) +/* Releases et tree T. */ + +void +et_free_tree (struct et_node *t) { - et_forest_occurrence_t new_occ, parent_occ, child_occ; + while (t->son) + et_split (t->son); - if (! parent_node || ! child_node) - abort (); + if (t->father) + et_split (t); - parent_occ = parent_node->first; - child_occ = child_node->first; - - splay (parent_occ); - splay (child_occ); - - if (parent_occ->parent) - return 0; /* Both child and parent are in the same tree. */ - - if (child_occ->left) - abort (); /* child must be root of its containing tree. */ - - new_occ = pool_alloc (forest->occur_pool); - - new_occ->node = parent_node; - new_occ->left = child_occ; - new_occ->count_left = child_occ->count_right + 1; /* count_left is 0. */ - new_occ->right = parent_occ->right; - new_occ->count_right = parent_occ->count_right; - new_occ->parent = parent_occ; - new_occ->next = parent_occ->next; - child_occ->parent = new_occ; - parent_occ->right = new_occ; - parent_occ->count_right = new_occ->count_left + new_occ->count_right + 1; - parent_occ->next = new_occ; - if (new_occ->right) - new_occ->right->parent = new_occ; - - if (parent_node->last == parent_occ) - parent_node->last = new_occ; - return 1; + pool_free (et_occurences, t->rightmost_occ); + pool_free (et_nodes, t); } -/* Remove NODE from the tree and all connected edges. */ +/* Sets father of et tree T to FATHER. */ + void -et_forest_remove_node (et_forest_t forest, et_forest_node_t node) +et_set_father (struct et_node *t, struct et_node *father) { - remove_all_occurrences (forest, node); - forest->nnodes--; + struct et_node *left, *right; + struct et_occ *rmost, *left_part, *new_f_occ, *p; - pool_free (forest->node_pool, node); -} + /* Update the path represented in the splay tree. */ + new_f_occ = et_new_occ (father); -/* Remove edge from the tree, return 1 if successful, - 0 indicates nonexisting edge. */ -int -et_forest_remove_edge (et_forest_t forest ATTRIBUTE_UNUSED, - et_forest_node_t parent_node, - et_forest_node_t child_node) -{ - et_forest_occurrence_t parent_pre_occ, parent_post_occ; + rmost = father->rightmost_occ; + et_splay (rmost); - splay (child_node->first); + left_part = rmost->prev; - if (! child_node->first->left) - return 0; + p = t->rightmost_occ; + et_splay (p); - parent_pre_occ = find_rightmost_node (child_node->first->left); - if (parent_pre_occ->node != parent_node) - abort (); + set_prev (new_f_occ, left_part); + set_next (new_f_occ, p); + + p->depth++; + p->min++; + et_recomp_min (new_f_occ); - splay (parent_pre_occ); - parent_pre_occ->right->parent = 0; + set_prev (rmost, new_f_occ); - parent_post_occ = parent_pre_occ->next; - splay (parent_post_occ); + if (new_f_occ->min + rmost->depth < rmost->min) + { + rmost->min = new_f_occ->min + rmost->depth; + rmost->min_occ = new_f_occ->min_occ; + } - parent_post_occ->left->parent = 0; + t->parent_occ = new_f_occ; - parent_pre_occ->right = parent_post_occ->right; - parent_pre_occ->count_right = parent_post_occ->count_right; - if (parent_post_occ->right) - parent_post_occ->right->parent = parent_pre_occ; + /* Update the tree. */ + t->father = father; + right = father->son; + if (right) + left = right->left; + else + left = right = t; - parent_pre_occ->next = parent_post_occ->next; + left->right = t; + right->left = t; + t->left = left; + t->right = right; - if (parent_post_occ == parent_node->last) - parent_node->last = parent_pre_occ; + father->son = t; - pool_free (forest->occur_pool, parent_post_occ); - return 1; +#ifdef DEBUG_ET + et_check_tree_sanity (rmost); + record_path_before (rmost); +#endif } -/* Return the parent of the NODE if any, NULL otherwise. */ -et_forest_node_t -et_forest_parent (et_forest_t forest ATTRIBUTE_UNUSED, et_forest_node_t node) +/* Splits the edge from T to its father. */ + +void +et_split (struct et_node *t) { - splay (node->first); + struct et_node *father = t->father; + struct et_occ *r, *l, *rmost, *p_occ; - if (node->first->left) - return find_rightmost_node (node->first->left)->node; - else - return 0; -} + /* Update the path represented by the splay tree. */ + rmost = t->rightmost_occ; + et_splay (rmost); + for (r = rmost->next; r->prev; r = r->prev) + continue; + et_splay (r); -/* Return nearest common ancestor of NODE1 and NODE2. - Return NULL of they are in different trees. */ -et_forest_node_t -et_forest_common_ancestor (et_forest_t forest ATTRIBUTE_UNUSED, - et_forest_node_t node1, et_forest_node_t node2) -{ - int value1, value2, max_value; - et_forest_node_t ancestor; + r->prev->parent = NULL; + p_occ = t->parent_occ; + et_splay (p_occ); + t->parent_occ = NULL; - if (node1 == node2) - return node1; + l = p_occ->prev; + p_occ->next->parent = NULL; - if (! node1 || ! node2) - abort (); + set_prev (r, l); - splay (node1->first); - splay (node2->first); + et_recomp_min (r); - if (! node1->first->parent) /* The two vertices are in different trees. */ - return 0; + et_splay (rmost); + rmost->depth = 0; + rmost->min = 0; - value2 = calculate_value (node2->first); - value1 = calculate_value (node1->first); + pool_free (et_occurences, p_occ); - if (value1 < value2) + /* Update the tree. */ + if (father->son == t) + father->son = t->right; + if (father->son == t) + father->son = NULL; + else { - ancestor = node1; - max_value = value2; + t->left->right = t->right; + t->right->left = t->left; + } + t->left = t->right = NULL; + t->father = NULL; + +#ifdef DEBUG_ET + et_check_tree_sanity (rmost); + record_path_before (rmost); + + et_check_tree_sanity (r); + record_path_before (r); +#endif +} + +/* Finds the nearest common ancestor of the nodes N1 and N2. */ + +struct et_node * +et_nca (struct et_node *n1, struct et_node *n2) +{ + struct et_occ *o1 = n1->rightmost_occ, *o2 = n2->rightmost_occ, *om; + struct et_occ *l, *r, *ret; + int mn; + + if (n1 == n2) + return n1; + + et_splay (o1); + l = o1->prev; + r = o1->next; + if (l) + l->parent = NULL; + if (r) + r->parent = NULL; + et_splay (o2); + + if (l == o2 || (l && l->parent != NULL)) + { + ret = o2->next; + + set_prev (o1, o2); + if (r) + r->parent = o1; } else { - ancestor = node2; - max_value = value1; + ret = o2->prev; + + set_next (o1, o2); + if (l) + l->parent = o1; } - while (calculate_value (ancestor->last) < max_value) + if (0 < o2->depth) { - /* Find parent node. */ - splay (ancestor->first); - ancestor = find_rightmost_node (ancestor->first->left) ->node; + om = o1; + mn = o1->depth; + } + else + { + om = o2; + mn = o2->depth + o1->depth; } - return ancestor; -} +#ifdef DEBUG_ET + et_check_tree_sanity (o2); +#endif -/* Return the value pointer of node set during it's creation. */ -void * -et_forest_node_value (et_forest_t forest ATTRIBUTE_UNUSED, - et_forest_node_t node) -{ - /* Alloc threading NULL as a special node of the forest. */ - if (!node) - return NULL; - return node->value; + if (ret && ret->min + o1->depth + o2->depth < mn) + return ret->min_occ->of; + else + return om->of; } -/* Find all sons of NODE and store them into ARRAY allocated by the caller. - Return number of nodes found. */ -int -et_forest_enumerate_sons (et_forest_t forest ATTRIBUTE_UNUSED, - et_forest_node_t node, et_forest_node_t *array) +/* Checks whether the node UP is an ancestor of the node DOWN. */ + +bool +et_below (struct et_node *down, struct et_node *up) { - int n = 0; - et_forest_occurrence_t occ = node->first, stop = node->last, occ1; + struct et_occ *u = up->rightmost_occ, *d = down->rightmost_occ; + struct et_occ *l, *r; + + if (up == down) + return true; + + et_splay (u); + l = u->prev; + r = u->next; + + if (!l) + return false; + + l->parent = NULL; + + if (r) + r->parent = NULL; - /* Parent is the rightmost node of the left successor. - Look for all occurrences having no right successor - and lookup the sons. */ - while (occ != stop) + et_splay (d); + + if (l == d || l->parent != NULL) { - splay (occ); - if (occ->right) - { - occ1 = find_leftmost_node (occ->right); - if (occ1->node->first == occ1) - array[n++] = occ1->node; - } - occ = occ->next; + if (r) + r->parent = u; + set_prev (u, d); +#ifdef DEBUG_ET + et_check_tree_sanity (u); +#endif } - return n; + else + { + l->parent = u; + + /* In case O1 and O2 are in two different trees, we must just restore the + original state. */ + if (r && r->parent != NULL) + set_next (u, d); + else + set_next (u, r); + +#ifdef DEBUG_ET + et_check_tree_sanity (u); +#endif + return false; + } + + if (0 >= d->depth) + return false; + + return !d->next || d->next->min + d->depth >= 0; } diff --git a/gcc/et-forest.h b/gcc/et-forest.h index f646d59..833146d 100644 --- a/gcc/et-forest.h +++ b/gcc/et-forest.h @@ -55,26 +55,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ extern "C" { #endif /* __cplusplus */ -typedef struct et_forest *et_forest_t; -typedef struct et_forest_node *et_forest_node_t; - -extern et_forest_t et_forest_create (void); - -extern void et_forest_delete (et_forest_t); - -extern et_forest_node_t et_forest_add_node (et_forest_t, void *); -extern int et_forest_add_edge (et_forest_t, et_forest_node_t, - et_forest_node_t); -extern void et_forest_remove_node (et_forest_t, et_forest_node_t); -extern int et_forest_remove_edge (et_forest_t, et_forest_node_t, - et_forest_node_t); -extern et_forest_node_t et_forest_parent (et_forest_t, et_forest_node_t); -extern et_forest_node_t et_forest_common_ancestor (et_forest_t, - et_forest_node_t, - et_forest_node_t); -extern void * et_forest_node_value (et_forest_t, et_forest_node_t); -extern int et_forest_enumerate_sons (et_forest_t, et_forest_node_t, - et_forest_node_t *); +/* The node representing the node in an et tree. */ +struct et_node +{ + void *data; /* The data represented by the node. */ + + int dfs_num_in, dfs_num_out; /* Number of the node in the dfs ordering. */ + + struct et_node *father; /* Father of the node. */ + struct et_node *son; /* The first of the sons of the node. */ + struct et_node *left; + struct et_node *right; /* The brothers of the node. */ + + struct et_occ *rightmost_occ; /* The rightmost occurence. */ + struct et_occ *parent_occ; /* The occurence of the parent node. */ +}; + +struct et_node *et_new_tree (void *data); +void et_free_tree (struct et_node *); +void et_set_father (struct et_node *, struct et_node *); +void et_split (struct et_node *); +struct et_node *et_nca (struct et_node *, struct et_node *); +bool et_below (struct et_node *, struct et_node *); #ifdef __cplusplus } diff --git a/gcc/function.c b/gcc/function.c index 30ede39..1da182a 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -6408,8 +6408,6 @@ allocate_struct_function (tree fndecl) DECL_SAVED_INSNS (fndecl) = cfun; cfun->decl = fndecl; - current_function_name = (*lang_hooks.decl_printable_name) (fndecl, 2); - result = DECL_RESULT (fndecl); if (aggregate_value_p (result, fndecl)) { diff --git a/gcc/function.h b/gcc/function.h index 89a1465..a8c5233 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -183,9 +183,6 @@ struct function GTY(()) /* For function.c. */ - /* Name of this function. */ - const char *name; - /* Points to the FUNCTION_DECL of this function. */ tree decl; @@ -534,7 +531,6 @@ extern int virtuals_instantiated; extern int trampolines_created; /* For backward compatibility... eventually these should all go away. */ -#define current_function_name (cfun->name) #define current_function_pops_args (cfun->pops_args) #define current_function_returns_struct (cfun->returns_struct) #define current_function_returns_pcc_struct (cfun->returns_pcc_struct) @@ -161,6 +161,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "basic-block.h" #include "output.h" #include "function.h" +#include "langhooks.h" #include "expr.h" #include "except.h" #include "ggc.h" @@ -855,7 +856,8 @@ gcse_main (rtx f, FILE *file) if (file) { fprintf (file, "GCSE of %s: %d basic blocks, ", - current_function_name, n_basic_blocks); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + n_basic_blocks); fprintf (file, "%d pass%s, %d bytes\n\n", pass, pass > 1 ? "es" : "", max_pass_bytes); } @@ -3614,7 +3616,8 @@ one_classic_gcse_pass (int pass) { fprintf (gcse_file, "\n"); fprintf (gcse_file, "GCSE of %s, pass %d: %d bytes needed, %d substs,", - current_function_name, pass, bytes_used, gcse_subst_count); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + pass, bytes_used, gcse_subst_count); fprintf (gcse_file, "%d insns created\n", gcse_create_count); } @@ -4686,7 +4689,8 @@ one_cprop_pass (int pass, int cprop_jumps, int bypass_jumps) if (gcse_file) { fprintf (gcse_file, "CPROP of %s, pass %d: %d bytes needed, ", - current_function_name, pass, bytes_used); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + pass, bytes_used); fprintf (gcse_file, "%d const props, %d copy props\n\n", const_prop_count, copy_prop_count); } @@ -5788,7 +5792,8 @@ one_pre_gcse_pass (int pass) if (gcse_file) { fprintf (gcse_file, "\nPRE GCSE of %s, pass %d: %d bytes needed, ", - current_function_name, pass, bytes_used); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + pass, bytes_used); fprintf (gcse_file, "%d substs, %d insns created\n", gcse_subst_count, gcse_create_count); } @@ -6182,9 +6187,6 @@ static sbitmap *hoist_vbeout; /* Hoistable expressions. */ static sbitmap *hoist_exprs; -/* Dominator bitmaps. */ -dominance_info dominators; - /* ??? We could compute post dominators and run this algorithm in reverse to perform tail merging, doing so would probably be more effective than the tail merging code in jump.c. @@ -6221,7 +6223,7 @@ free_code_hoist_mem (void) sbitmap_vector_free (hoist_exprs); sbitmap_vector_free (transpout); - free_dominance_info (dominators); + free_dominance_info (CDI_DOMINATORS); } /* Compute the very busy expressions at entry/exit from each block. @@ -6270,7 +6272,7 @@ compute_code_hoist_data (void) compute_local_properties (transp, comp, antloc, &expr_hash_table); compute_transpout (); compute_code_hoist_vbeinout (); - dominators = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); if (gcse_file) fprintf (gcse_file, "\n"); } @@ -6362,7 +6364,7 @@ hoist_code (void) int found = 0; int insn_inserted_p; - domby_len = get_dominated_by (dominators, bb, &domby); + domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby); /* Examine each expression that is very busy at the exit of this block. These are the potentially hoistable expressions. */ for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++) @@ -8020,7 +8022,8 @@ bypass_jumps (FILE *file) if (file) { fprintf (file, "BYPASS of %s: %d basic blocks, ", - current_function_name, n_basic_blocks); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + n_basic_blocks); fprintf (file, "%d bytes\n\n", bytes_used); } diff --git a/gcc/graph.c b/gcc/graph.c index d82dd91..483cc7e 100644 --- a/gcc/graph.c +++ b/gcc/graph.c @@ -25,9 +25,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm.h" #include "rtl.h" +#include "tree.h" #include "flags.h" #include "output.h" #include "function.h" +#include "langhooks.h" #include "hard-reg-set.h" #include "basic-block.h" #include "toplev.h" @@ -55,7 +57,8 @@ start_fct (FILE *fp) case vcg: fprintf (fp, "\ graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n", - current_function_name, current_function_name); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + (*lang_hooks.decl_printable_name) (current_function_decl, 2)); break; case no_graph: break; @@ -71,7 +74,8 @@ start_bb (FILE *fp, int bb) fprintf (fp, "\ graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\ label: \"basic block %d", - current_function_name, bb, bb); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + bb, bb); break; case no_graph: break; @@ -113,8 +117,9 @@ node_data (FILE *fp, rtx tmp_rtx) case vcg: fprintf (fp, "\ edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n", - current_function_name, - current_function_name, XINT (tmp_rtx, 0)); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + XINT (tmp_rtx, 0)); break; case no_graph: break; @@ -126,7 +131,8 @@ edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n", case vcg: fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \ label: \"%s %d\n", - current_function_name, XINT (tmp_rtx, 0), + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + XINT (tmp_rtx, 0), GET_CODE (tmp_rtx) == NOTE ? "lightgrey" : GET_CODE (tmp_rtx) == INSN ? "green" : GET_CODE (tmp_rtx) == JUMP_INSN ? "darkgreen" @@ -178,8 +184,11 @@ draw_edge (FILE *fp, int from, int to, int bb_edge, int class) color = "color: green "; fprintf (fp, "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s", - current_function_name, from, - current_function_name, to, color); + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + from, + (*lang_hooks.decl_printable_name) (current_function_decl, 2), + to, + color); if (class) fprintf (fp, "class: %d ", class); fputs ("}\n", fp); @@ -209,7 +218,7 @@ end_fct (FILE *fp) { case vcg: fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n", - current_function_name); + (*lang_hooks.decl_printable_name) (current_function_decl, 2)); break; case no_graph: break; diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 24c8fd8..2b10e18 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -84,9 +84,6 @@ static int cond_exec_changed_p; /* True if life data ok at present. */ static bool life_data_ok; -/* The post-dominator relation on the original block numbers. */ -static dominance_info post_dominators; - /* Forward references. */ static int count_bb_insns (basic_block); static rtx first_active_insn (basic_block); @@ -123,6 +120,7 @@ mark_loop_exit_edges (void) edge e; flow_loops_find (&loops, LOOP_TREE); + free_dominance_info (CDI_DOMINATORS); if (loops.num > 1) { @@ -2105,8 +2103,8 @@ merge_if_block (struct ce_if_block * ce_info) { bb = fallthru; fallthru = block_fallthru (bb); - if (post_dominators) - delete_from_dominance_info (post_dominators, bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, bb); merge_blocks (combo_bb, bb); num_true_changes++; } @@ -2122,8 +2120,8 @@ merge_if_block (struct ce_if_block * ce_info) if (combo_bb->global_live_at_end) COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end); - if (post_dominators) - delete_from_dominance_info (post_dominators, then_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb); merge_blocks (combo_bb, then_bb); num_true_changes++; } @@ -2133,8 +2131,8 @@ merge_if_block (struct ce_if_block * ce_info) get their addresses taken. */ if (else_bb) { - if (post_dominators) - delete_from_dominance_info (post_dominators, else_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb); merge_blocks (combo_bb, else_bb); num_true_changes++; } @@ -2190,8 +2188,8 @@ merge_if_block (struct ce_if_block * ce_info) COPY_REG_SET (combo_bb->global_live_at_end, join_bb->global_live_at_end); - if (post_dominators) - delete_from_dominance_info (post_dominators, join_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, join_bb); merge_blocks (combo_bb, join_bb); num_true_changes++; } @@ -2271,7 +2269,7 @@ find_if_header (basic_block test_bb, int pass) && find_cond_trap (test_bb, then_edge, else_edge)) goto success; - if (post_dominators + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY && (! HAVE_conditional_execution || reload_completed)) { if (find_if_case_1 (test_bb, then_edge, else_edge)) @@ -2646,8 +2644,8 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge) remove_edge (trap_bb == then_bb ? then_edge : else_edge); if (trap_bb->pred == NULL) { - if (post_dominators) - delete_from_dominance_info (post_dominators, trap_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, trap_bb); delete_block (trap_bb); } @@ -2831,8 +2829,8 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge) new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb); then_bb_index = then_bb->index; - if (post_dominators) - delete_from_dominance_info (post_dominators, then_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb); delete_block (then_bb); /* Make rest of code believe that the newly created block is the THEN_BB @@ -2841,8 +2839,8 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge) { new_bb->index = then_bb_index; BASIC_BLOCK (then_bb_index) = new_bb; - if (post_dominators) - add_to_dominance_info (post_dominators, new_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + add_to_dominance_info (CDI_POST_DOMINATORS, new_bb); } /* We've possibly created jump to next insn, cleanup_cfg will solve that later. */ @@ -2884,7 +2882,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ; else if (else_succ->dest->index < 0 - || dominated_by_p (post_dominators, then_bb, + || dominated_by_p (CDI_POST_DOMINATORS, then_bb, else_succ->dest)) ; else @@ -2911,8 +2909,8 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) then_bb->global_live_at_start, else_bb->global_live_at_end, BITMAP_IOR); - if (post_dominators) - delete_from_dominance_info (post_dominators, else_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb); delete_block (else_bb); num_true_changes++; @@ -3217,11 +3215,9 @@ if_convert (int x_life_data_ok) free_basic_block_vars (1); /* Compute postdominators if we think we'll use them. */ - post_dominators = NULL; if (HAVE_conditional_execution || life_data_ok) - { - post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS); - } + calculate_dominance_info (CDI_POST_DOMINATORS); + if (life_data_ok) clear_bb_flags (); @@ -3258,8 +3254,7 @@ if_convert (int x_life_data_ok) fprintf (rtl_dump_file, "\n\n========== no more changes\n"); #endif - if (post_dominators) - free_dominance_info (post_dominators); + free_dominance_info (CDI_POST_DOMINATORS); if (rtl_dump_file) fflush (rtl_dump_file); diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 13285a3..0b882d9 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -53,7 +53,9 @@ loop_optimizer_init (FILE *dumpfile) /* No loops. */ flow_loops_free (loops); + free_dominance_info (CDI_DOMINATORS); free (loops); + /* Make chain. */ FOR_EACH_BB (bb) if (bb->next_bb != EXIT_BLOCK_PTR) @@ -81,7 +83,7 @@ loop_optimizer_init (FILE *dumpfile) flow_loops_dump (loops, dumpfile, NULL, 1); #ifdef ENABLE_CHECKING - verify_dominators (loops->cfg.dom); + verify_dominators (CDI_DOMINATORS); verify_loop_structure (loops); #endif @@ -105,6 +107,7 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile) /* Clean up. */ flow_loops_free (loops); + free_dominance_info (CDI_DOMINATORS); free (loops); /* Finalize changes. */ diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index dde3c74..6c796af 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -68,14 +68,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA static void decide_unrolling_and_peeling (struct loops *, int); static void peel_loops_completely (struct loops *, int); -static void decide_peel_simple (struct loops *, struct loop *, int); -static void decide_peel_once_rolling (struct loops *, struct loop *, int); -static void decide_peel_completely (struct loops *, struct loop *, int); -static void decide_unroll_stupid (struct loops *, struct loop *, int); -static void decide_unroll_constant_iterations (struct loops *, - struct loop *, int); -static void decide_unroll_runtime_iterations (struct loops *, struct loop *, - int); +static void decide_peel_simple (struct loop *, int); +static void decide_peel_once_rolling (struct loop *, int); +static void decide_peel_completely (struct loop *, int); +static void decide_unroll_stupid (struct loop *, int); +static void decide_unroll_constant_iterations (struct loop *, int); +static void decide_unroll_runtime_iterations (struct loop *, int); static void peel_loop_simple (struct loops *, struct loop *); static void peel_loop_completely (struct loops *, struct loop *); static void unroll_loop_stupid (struct loops *, struct loop *); @@ -140,7 +138,7 @@ unroll_and_peel_loops (struct loops *loops, int flags) if (check) { #ifdef ENABLE_CHECKING - verify_dominators (loops->cfg.dom); + verify_dominators (CDI_DOMINATORS); verify_loop_structure (loops); #endif } @@ -178,15 +176,15 @@ peel_loops_completely (struct loops *loops, int flags) loop->ninsns = num_loop_insns (loop); - decide_peel_once_rolling (loops, loop, flags); + decide_peel_once_rolling (loop, flags); if (loop->lpt_decision.decision == LPT_NONE) - decide_peel_completely (loops, loop, flags); + decide_peel_completely (loop, flags); if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY) { peel_loop_completely (loops, loop); #ifdef ENABLE_CHECKING - verify_dominators (loops->cfg.dom); + verify_dominators (CDI_DOMINATORS); verify_loop_structure (loops); #endif } @@ -254,13 +252,13 @@ decide_unrolling_and_peeling (struct loops *loops, int flags) /* Try transformations one by one in decreasing order of priority. */ - decide_unroll_constant_iterations (loops, loop, flags); + decide_unroll_constant_iterations (loop, flags); if (loop->lpt_decision.decision == LPT_NONE) - decide_unroll_runtime_iterations (loops, loop, flags); + decide_unroll_runtime_iterations (loop, flags); if (loop->lpt_decision.decision == LPT_NONE) - decide_unroll_stupid (loops, loop, flags); + decide_unroll_stupid (loop, flags); if (loop->lpt_decision.decision == LPT_NONE) - decide_peel_simple (loops, loop, flags); + decide_peel_simple (loop, flags); loop = next; } @@ -269,8 +267,7 @@ decide_unrolling_and_peeling (struct loops *loops, int flags) /* Decide whether the LOOP is once rolling and suitable for complete peeling. */ static void -decide_peel_once_rolling (struct loops *loops, struct loop *loop, - int flags ATTRIBUTE_UNUSED) +decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED) { if (rtl_dump_file) fprintf (rtl_dump_file, ";; Considering peeling once rolling loop\n"); @@ -284,7 +281,7 @@ decide_peel_once_rolling (struct loops *loops, struct loop *loop, } /* Check for simple loops. */ - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; /* Check number of iterations. */ @@ -303,8 +300,7 @@ decide_peel_once_rolling (struct loops *loops, struct loop *loop, /* Decide whether the LOOP is suitable for complete peeling. */ static void -decide_peel_completely (struct loops *loops, struct loop *loop, - int flags ATTRIBUTE_UNUSED) +decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED) { unsigned npeel; @@ -352,7 +348,7 @@ decide_peel_completely (struct loops *loops, struct loop *loop, /* Check for simple loops. */ if (!loop->has_desc) { - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; } @@ -441,8 +437,7 @@ peel_loop_completely (struct loops *loops, struct loop *loop) /* Decide whether to unroll LOOP iterating constant number of times and how much. */ static void -decide_unroll_constant_iterations (struct loops *loops, struct loop *loop, - int flags) +decide_unroll_constant_iterations (struct loop *loop, int flags) { unsigned nunroll, nunroll_by_av, best_copies, best_unroll = -1, n_copies, i; @@ -475,7 +470,7 @@ decide_unroll_constant_iterations (struct loops *loops, struct loop *loop, /* Check for simple loops. */ if (!loop->has_desc) { - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; } @@ -649,8 +644,7 @@ unroll_loop_constant_iterations (struct loops *loops, struct loop *loop) /* Decide whether to unroll LOOP iterating runtime computable number of times and how much. */ static void -decide_unroll_runtime_iterations (struct loops *loops, struct loop *loop, - int flags) +decide_unroll_runtime_iterations (struct loop *loop, int flags) { unsigned nunroll, nunroll_by_av, i; @@ -683,7 +677,7 @@ decide_unroll_runtime_iterations (struct loops *loops, struct loop *loop, /* Check for simple loops. */ if (!loop->has_desc) { - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; } @@ -774,7 +768,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) unsigned nldom; basic_block *ldom; - nldom = get_dominated_by (loops->cfg.dom, body[i], &ldom); + nldom = get_dominated_by (CDI_DOMINATORS, body[i], &ldom); for (j = 0; j < nldom; j++) if (!flow_bb_inside_loop_p (loop, ldom[j])) dom_bbs[n_dom_bbs++] = ldom[j]; @@ -821,7 +815,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, loops); + loop_split_edge_with (loop_preheader_edge (loop), init_code); remove_edges = xcalloc (max_unroll + n_peel + 1, sizeof (edge)); n_remove_edges = 0; @@ -844,7 +838,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) /* Record the place where switch will be built for preconditioning. */ swtch = loop_split_edge_with (loop_preheader_edge (loop), - NULL_RTX, loops); + NULL_RTX); for (i = 0; i < n_peel; i++) { @@ -862,8 +856,7 @@ 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, loops); + preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX); label = block_label (preheader); start_sequence (); do_compare_rtx_and_jump (copy_rtx (niter), GEN_INT (j), EQ, 0, @@ -879,8 +872,8 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) branch_code = get_insns (); end_sequence (); - swtch = loop_split_edge_with (swtch->pred, branch_code, loops); - set_immediate_dominator (loops->cfg.dom, preheader, swtch); + swtch = loop_split_edge_with (swtch->pred, branch_code); + set_immediate_dominator (CDI_DOMINATORS, preheader, swtch); swtch->succ->probability = REG_BR_PROB_BASE - p; e = make_edge (swtch, preheader, swtch->succ->flags & EDGE_IRREDUCIBLE_LOOP); @@ -892,8 +885,7 @@ 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, loops); + preheader = loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX); label = block_label (preheader); start_sequence (); do_compare_rtx_and_jump (copy_rtx (niter), const0_rtx, EQ, 0, @@ -909,8 +901,8 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) branch_code = get_insns (); end_sequence (); - swtch = loop_split_edge_with (swtch->succ, branch_code, loops); - set_immediate_dominator (loops->cfg.dom, preheader, swtch); + swtch = loop_split_edge_with (swtch->succ, branch_code); + set_immediate_dominator (CDI_DOMINATORS, preheader, swtch); swtch->succ->probability = REG_BR_PROB_BASE - p; e = make_edge (swtch, preheader, swtch->succ->flags & EDGE_IRREDUCIBLE_LOOP); @@ -918,7 +910,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) } /* Recount dominators for outer blocks. */ - iterate_fix_dominators (loops->cfg.dom, dom_bbs, n_dom_bbs); + iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, n_dom_bbs); /* And unroll loop. */ @@ -946,7 +938,7 @@ unroll_loop_runtime_iterations (struct loops *loops, struct loop *loop) /* Decide whether to simply peel LOOP and how much. */ static void -decide_peel_simple (struct loops *loops, struct loop *loop, int flags) +decide_peel_simple (struct loop *loop, int flags) { unsigned npeel; @@ -975,7 +967,7 @@ decide_peel_simple (struct loops *loops, struct loop *loop, int flags) /* Check for simple loops. */ if (!loop->has_desc) { - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; } @@ -1062,7 +1054,7 @@ peel_loop_simple (struct loops *loops, struct loop *loop) /* Decide whether to unroll LOOP stupidly and how much. */ static void -decide_unroll_stupid (struct loops *loops, struct loop *loop, int flags) +decide_unroll_stupid (struct loop *loop, int flags) { unsigned nunroll, nunroll_by_av, i; @@ -1095,7 +1087,7 @@ decide_unroll_stupid (struct loops *loops, struct loop *loop, int flags) /* Check for simple loops. */ if (!loop->has_desc) { - loop->simple = simple_loop_p (loops, loop, &loop->desc); + loop->simple = simple_loop_p (loop, &loop->desc); loop->has_desc = 1; } diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c index 25728c2..4cfaa2f 100644 --- a/gcc/loop-unswitch.c +++ b/gcc/loop-unswitch.c @@ -81,7 +81,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA static struct loop *unswitch_loop (struct loops *, struct loop *, basic_block); static void unswitch_single_loop (struct loops *, struct loop *, rtx, int); -static bool may_unswitch_on_p (struct loops *, basic_block, struct loop *, +static bool may_unswitch_on_p (basic_block, struct loop *, basic_block *); static rtx reversed_condition (rtx); @@ -107,7 +107,7 @@ unswitch_loops (struct loops *loops) unswitch_single_loop (loops, loop, NULL_RTX, 0); #ifdef ENABLE_CHECKING - verify_dominators (loops->cfg.dom); + verify_dominators (CDI_DOMINATORS); verify_loop_structure (loops); #endif } @@ -117,8 +117,7 @@ unswitch_loops (struct loops *loops) basic blocks (for what it means see comments below). List of basic blocks inside LOOP is provided in BODY to save time. */ static bool -may_unswitch_on_p (struct loops *loops, basic_block bb, struct loop *loop, - basic_block *body) +may_unswitch_on_p (basic_block bb, struct loop *loop, basic_block *body) { rtx test; unsigned i; @@ -136,7 +135,7 @@ may_unswitch_on_p (struct loops *loops, basic_block bb, struct loop *loop, /* It must be executed just once each iteration (because otherwise we are unable to update dominator/irreducible loop information correctly). */ - if (!just_once_each_iteration_p (loops, loop, bb)) + if (!just_once_each_iteration_p (loop, bb)) return false; /* Condition must be invariant. We use just a stupid test of invariantness @@ -239,7 +238,7 @@ unswitch_single_loop (struct loops *loops, struct loop *loop, /* Find a bb to unswitch on. */ bbs = get_loop_body (loop); for (i = 0; i < loop->num_nodes; i++) - if (may_unswitch_on_p (loops, bbs[i], loop, bbs)) + if (may_unswitch_on_p (bbs[i], loop, bbs)) break; if (i == loop->num_nodes) @@ -295,7 +294,7 @@ unswitch_single_loop (struct loops *loops, struct loop *loop, rconds = cond_checked; /* Separate condition in a single basic block. */ - bb = split_loop_bb (loops, bbs[i], PREV_INSN (split_before))->dest; + bb = split_loop_bb (bbs[i], PREV_INSN (split_before))->dest; free (bbs); true_first = !(bb->succ->flags & EDGE_FALLTHRU); if (rtl_dump_file) @@ -335,7 +334,7 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on) if (!unswitch_on->succ || !unswitch_on->succ->succ_next || unswitch_on->succ->succ_next->succ_next) abort (); - if (!just_once_each_iteration_p (loops, loop, unswitch_on)) + if (!just_once_each_iteration_p (loop, unswitch_on)) abort (); if (loop->inner) abort (); @@ -382,7 +381,7 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on) switch_bb->succ->flags &= ~EDGE_IRREDUCIBLE_LOOP; switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP; } - add_to_dominance_info (loops->cfg.dom, switch_bb); + add_to_dominance_info (CDI_DOMINATORS, switch_bb); unswitch_on->rbi->copy = unswitch_on_alt; /* Loopify from the copy of LOOP body, constructing the new loop. */ @@ -403,8 +402,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, loops); - loop_split_edge_with (loop_preheader_edge (nloop), NULL_RTX, loops); + loop_split_edge_with (loop_preheader_edge (loop), NULL_RTX); + loop_split_edge_with (loop_preheader_edge (nloop), NULL_RTX); return nloop; } diff --git a/gcc/predict.c b/gcc/predict.c index 30de866..74a1f24 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -72,10 +72,8 @@ static void estimate_loops_at_level (struct loop *loop); static void propagate_freq (struct loop *); static void estimate_bb_frequencies (struct loops *); static void counts_to_freqs (void); -static void process_note_predictions (basic_block, int *, dominance_info, - dominance_info); -static void process_note_prediction (basic_block, int *, dominance_info, - dominance_info, int, int); +static void process_note_predictions (basic_block, int *); +static void process_note_prediction (basic_block, int *, int, int); static bool last_basic_block_p (basic_block); static void compute_function_frequency (void); static void choose_function_section (void); @@ -393,13 +391,12 @@ combine_predictions_for_insn (rtx insn, basic_block bb) void estimate_probability (struct loops *loops_info) { - dominance_info dominators, post_dominators; basic_block bb; unsigned i; connect_infinite_loops_to_exit (); - dominators = calculate_dominance_info (CDI_DOMINATORS); - post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_POST_DOMINATORS); /* Try to predict out blocks in a loop that are not part of a natural loop. */ @@ -412,11 +409,10 @@ estimate_probability (struct loops *loops_info) struct loop_desc desc; unsigned HOST_WIDE_INT niter; - flow_loop_scan (loops_info, loop, LOOP_EXIT_EDGES); + flow_loop_scan (loop, LOOP_EXIT_EDGES); exits = loop->num_exits; - if (simple_loop_p (loops_info, loop, &desc) - && desc.const_iter) + if (simple_loop_p (loop, &desc) && desc.const_iter) { int prob; niter = desc.niter + 1; @@ -500,8 +496,8 @@ estimate_probability (struct loops *loops_info) /* Look for block we are guarding (ie we dominate it, but it doesn't postdominate us). */ if (e->dest != EXIT_BLOCK_PTR && e->dest != bb - && dominated_by_p (dominators, e->dest, e->src) - && !dominated_by_p (post_dominators, e->src, e->dest)) + && dominated_by_p (CDI_DOMINATORS, e->dest, e->src) + && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest)) { rtx insn; @@ -618,8 +614,7 @@ estimate_probability (struct loops *loops_info) && bb->succ->succ_next != NULL) combine_predictions_for_insn (BB_END (bb), bb); - free_dominance_info (post_dominators); - free_dominance_info (dominators); + free_dominance_info (CDI_POST_DOMINATORS); remove_fake_edges (); estimate_bb_frequencies (loops_info); @@ -719,10 +714,7 @@ last_basic_block_p (basic_block bb) on demand, so -1 may be there in case this was not needed yet). */ static void -process_note_prediction (basic_block bb, int *heads, - dominance_info dominators, - dominance_info post_dominators, int pred, - int flags) +process_note_prediction (basic_block bb, int *heads, int pred, int flags) { edge e; int y; @@ -736,18 +728,18 @@ process_note_prediction (basic_block bb, int *heads, find first dominator that we do not post-dominate (we are using already known members of heads array). */ basic_block ai = bb; - basic_block next_ai = get_immediate_dominator (dominators, bb); + basic_block next_ai = get_immediate_dominator (CDI_DOMINATORS, bb); int head; while (heads[next_ai->index] < 0) { - if (!dominated_by_p (post_dominators, next_ai, bb)) + if (!dominated_by_p (CDI_POST_DOMINATORS, next_ai, bb)) break; heads[next_ai->index] = ai->index; ai = next_ai; - next_ai = get_immediate_dominator (dominators, next_ai); + next_ai = get_immediate_dominator (CDI_DOMINATORS, next_ai); } - if (!dominated_by_p (post_dominators, next_ai, bb)) + if (!dominated_by_p (CDI_POST_DOMINATORS, next_ai, bb)) head = next_ai->index; else head = heads[next_ai->index]; @@ -769,7 +761,7 @@ process_note_prediction (basic_block bb, int *heads, return; for (e = BASIC_BLOCK (y)->succ; e; e = e->succ_next) if (e->dest->index >= 0 - && dominated_by_p (post_dominators, e->dest, bb)) + && dominated_by_p (CDI_POST_DOMINATORS, e->dest, bb)) predict_edge_def (e, pred, taken); } @@ -778,9 +770,7 @@ process_note_prediction (basic_block bb, int *heads, process_note_prediction. */ static void -process_note_predictions (basic_block bb, int *heads, - dominance_info dominators, - dominance_info post_dominators) +process_note_predictions (basic_block bb, int *heads) { rtx insn; edge e; @@ -813,8 +803,6 @@ process_note_predictions (basic_block bb, int *heads, /* Process single prediction note. */ process_note_prediction (bb, heads, - dominators, - post_dominators, alg, (int) NOTE_PREDICTION_FLAGS (insn)); delete_insn (insn); } @@ -827,10 +815,7 @@ process_note_predictions (basic_block bb, int *heads, /* This block ended from other reasons than because of return. If it is because of noreturn call, this should certainly not be taken. Otherwise it is probably some error recovery. */ - process_note_prediction (bb, - heads, - dominators, - post_dominators, PRED_NORETURN, NOT_TAKEN); + process_note_prediction (bb, heads, PRED_NORETURN, NOT_TAKEN); } } @@ -841,15 +826,14 @@ void note_prediction_to_br_prob (void) { basic_block bb; - dominance_info post_dominators, dominators; int *heads; /* To enable handling of noreturn blocks. */ add_noreturn_fake_exit_edges (); connect_infinite_loops_to_exit (); - post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS); - dominators = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_POST_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); heads = xmalloc (sizeof (int) * last_basic_block); memset (heads, -1, sizeof (int) * last_basic_block); @@ -858,10 +842,10 @@ note_prediction_to_br_prob (void) /* Process all prediction notes. */ FOR_EACH_BB (bb) - process_note_predictions (bb, heads, dominators, post_dominators); + process_note_predictions (bb, heads); - free_dominance_info (post_dominators); - free_dominance_info (dominators); + free_dominance_info (CDI_POST_DOMINATORS); + free_dominance_info (CDI_DOMINATORS); free (heads); remove_fake_edges (); diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 138bab3..b8e474d 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -155,7 +155,7 @@ static int *containing_rgn; void debug_regions (void); static void find_single_block_region (void); -static void find_rgns (struct edge_list *, dominance_info); +static void find_rgns (struct edge_list *); static int too_large (int, int *, int *); extern void debug_live (int, int); @@ -613,7 +613,7 @@ too_large (int block, int *num_bbs, int *num_insns) of edge tables. That would simplify it somewhat. */ static void -find_rgns (struct edge_list *edge_list, dominance_info dom) +find_rgns (struct edge_list *edge_list) { int *max_hdr, *dfs_nr, *stack, *degree; char no_loops = 1; @@ -827,7 +827,7 @@ find_rgns (struct edge_list *edge_list, dominance_info dom) { /* Now verify that the block is dominated by the loop header. */ - if (!dominated_by_p (dom, jbb, bb)) + if (!dominated_by_p (CDI_DOMINATORS, jbb, bb)) break; } } @@ -2597,7 +2597,6 @@ init_regions (void) } else { - dominance_info dom; struct edge_list *edge_list; /* The scheduler runs after estimate_probabilities; therefore, we @@ -2607,7 +2606,7 @@ init_regions (void) edge_list = create_edge_list (); /* Compute the dominators and post dominators. */ - dom = calculate_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); /* build_control_flow will return nonzero if it detects unreachable blocks or any other irregularity with the cfg which prevents @@ -2615,7 +2614,7 @@ init_regions (void) if (build_control_flow (edge_list) != 0) find_single_block_region (); else - find_rgns (edge_list, dom); + find_rgns (edge_list); if (sched_verbose >= 3) debug_regions (); @@ -2625,7 +2624,7 @@ init_regions (void) /* For now. This will move as more and more of haifa is converted to using the cfg code in flow.c. */ - free_dominance_info (dom); + free_dominance_info (CDI_DOMINATORS); } } diff --git a/gcc/toplev.c b/gcc/toplev.c index eb68ce8..6e34c6d 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2477,6 +2477,7 @@ rest_of_handle_branch_prob (tree decl, rtx insns) estimate_probability (&loops); flow_loops_free (&loops); + free_dominance_info (CDI_DOMINATORS); close_dump_file (DFI_bp, print_rtl_with_bb, insns); timevar_pop (TV_BRANCH_PROB); } @@ -3014,8 +3015,9 @@ rest_of_handle_loop_optimize (tree decl, rtx insns) sooner, but we want the profile feedback to work more efficiently. */ static void -rest_of_handle_loop2 (tree decl, rtx insns) +rest_of_handle_loop2 (tree decl ATTRIBUTE_UNUSED, rtx insns ATTRIBUTE_UNUSED) { +#if 0 struct loops *loops; timevar_push (TV_LOOP); open_dump_file (DFI_loop2, decl); @@ -3047,6 +3049,7 @@ rest_of_handle_loop2 (tree decl, rtx insns) close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ()); timevar_pop (TV_LOOP); ggc_collect (); +#endif } /* This is called from finish_function (within langhooks.parse_file) |