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
This commit is contained in:
parent
58496de135
commit
d47cc544b6
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
360
gcc/dominance.c
360
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. */
|
||||
|
||||
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.
|
||||
|
||||
Either IDOM or DOMS may be NULL (meaning the caller is not interested in
|
||||
immediate resp. all dominators). */
|
||||
|
||||
dominance_info
|
||||
calculate_dominance_info (enum cdi_direction reverse)
|
||||
static void
|
||||
assign_dfs_numbers (struct et_node *node, int *num)
|
||||
{
|
||||
struct dom_info di;
|
||||
dominance_info info;
|
||||
basic_block b;
|
||||
struct et_node *son;
|
||||
|
||||
/* 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");
|
||||
node->dfs_num_in = (*num)++;
|
||||
|
||||
/* 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));
|
||||
|
||||
init_dom_info (&di);
|
||||
calc_dfs_tree (&di, reverse);
|
||||
calc_idoms (&di, reverse);
|
||||
|
||||
|
||||
FOR_EACH_BB (b)
|
||||
if (node->son)
|
||||
{
|
||||
TBB d = di.dom[di.dfs_order[b->index]];
|
||||
|
||||
if (di.dfs_to_bb[d])
|
||||
et_forest_add_edge (info->forest, BB_NODE (info, di.dfs_to_bb[d]), BB_NODE (info, b));
|
||||
assign_dfs_numbers (node->son, num);
|
||||
for (son = node->son->right; son != node->son; son = son->right)
|
||||
assign_dfs_numbers (son, num);
|
||||
}
|
||||
|
||||
free_dom_info (&di);
|
||||
return info;
|
||||
node->dfs_num_out = (*num)++;
|
||||
}
|
||||
|
||||
/* Free dominance information. */
|
||||
/* Compute the data neccesary for fast resolving of dominator queries in a
|
||||
static dominator tree. */
|
||||
|
||||
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
|
||||
free_dominance_info (dominance_info info)
|
||||
calculate_dominance_info (enum cdi_direction dir)
|
||||
{
|
||||
struct dom_info di;
|
||||
basic_block b;
|
||||
|
||||
if (dom_computed[dir] == DOM_OK)
|
||||
return;
|
||||
|
||||
if (dom_computed[dir] != DOM_NO_FAST_QUERY)
|
||||
{
|
||||
if (dom_computed[dir] != DOM_NONE)
|
||||
free_dominance_info (dir);
|
||||
|
||||
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]];
|
||||
|
||||
if (di.dfs_to_bb[d])
|
||||
et_set_father (b->dom[dir], di.dfs_to_bb[d]->dom[dir]);
|
||||
}
|
||||
|
||||
free_dom_info (&di);
|
||||
dom_computed[dir] = DOM_NO_FAST_QUERY;
|
||||
}
|
||||
|
||||
compute_dom_fast_query (dir);
|
||||
}
|
||||
|
||||
/* Free dominance information for direction DIR. */
|
||||
void
|
||||
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];
|
||||
|
||||
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 (!dom_computed[dir])
|
||||
abort ();
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (!dom_computed[dir])
|
||||
abort ();
|
||||
|
||||
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)
|
||||
{
|
||||
et_forest_remove_node (dom->forest, BB_NODE (dom, bb));
|
||||
SET_BB_NODE (dom, bb, NULL);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
1168
gcc/et-forest.c
1168
gcc/et-forest.c
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
/* The node representing the node in an et tree. */
|
||||
struct et_node
|
||||
{
|
||||
void *data; /* The data represented by the node. */
|
||||
|
||||
extern et_forest_t et_forest_create (void);
|
||||
int dfs_num_in, dfs_num_out; /* Number of the node in the dfs ordering. */
|
||||
|
||||
extern void et_forest_delete (et_forest_t);
|
||||
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. */
|
||||
|
||||
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 *);
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
25
gcc/gcse.c
25
gcc/gcse.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
25
gcc/graph.c
25
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;
|
||||
|
|
49
gcc/ifcvt.c
49
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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue