+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
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)
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)
/* 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;
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
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"
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;
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;
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. */
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. */
"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);
}
}
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);
EXIT_BLOCK_PTR, /* next_bb */
0, /* loop_depth */
NULL, /* loop_father */
+ { NULL, NULL }, /* dom */
0, /* count */
0, /* frequency */
0, /* flags */
NULL, /* next_bb */
0, /* loop_depth */
NULL, /* loop_father */
+ { NULL, NULL }, /* dom */
0, /* count */
0, /* frequency */
0, /* flags */
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;
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;
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);
}
}
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);
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 *);
int i;
basic_block bb;
- if (! loops->num || ! file || ! loops->cfg.dom)
+ if (! loops->num || ! file)
return;
FOR_EACH_BB (bb)
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)
}
/* 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;
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;
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)
{
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. */
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));
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;
HEADER_BLOCK (header) = num_latches;
}
+ free_dominance_info (CDI_DOMINATORS);
+
if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest))
{
basic_block bb;
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
int num_loops;
edge e;
sbitmap headers;
- dominance_info dom;
int *dfs_order;
int *rc_order;
basic_block header;
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. */
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)
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;
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;
/* 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;
/* 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;
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 *);
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
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. */
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 *);
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);
/* 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. */
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;
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. */
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)
{
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)
{
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. */
/* 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. */
/* 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;
{
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. */
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 *);
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);
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]);
}
}
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 --
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));
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. */
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
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;
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);
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);
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)
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];
}
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];
}
/* 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);
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);
}
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;
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)
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)
{
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;
}
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;
}
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;
/* 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;
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;
#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
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. */
di->dom[v] = di->dom[di->dom[v]];
}
-/* The main entry point into this module. IDOM is an integer array with room
- for last_basic_block integers, DOMS is a preallocated sbitmap array having
- room for last_basic_block^2 bits, and POST is true if the caller wants to
- know post-dominators.
+/* Assign dfs numbers starting from NUM to NODE and its sons. */
+
+static void
+assign_dfs_numbers (struct et_node *node, int *num)
+{
+ struct et_node *son;
+
+ node->dfs_num_in = (*num)++;
+
+ if (node->son)
+ {
+ assign_dfs_numbers (node->son, num);
+ for (son = node->son->right; son != node->son; son = son->right)
+ assign_dfs_numbers (son, num);
+ }
- On return IDOM[i] will be the BB->index of the immediate (post) dominator
- of basic block i, and DOMS[i] will have set bit j if basic block j is a
- (post)dominator for block i.
+ node->dfs_num_out = (*num)++;
+}
- Either IDOM or DOMS may be NULL (meaning the caller is not interested in
- immediate resp. all dominators). */
+/* Compute the data neccesary for fast resolving of dominator queries in a
+ static dominator tree. */
-dominance_info
-calculate_dominance_info (enum cdi_direction reverse)
+static void
+compute_dom_fast_query (enum cdi_direction dir)
+{
+ int num = 0;
+ basic_block bb;
+
+ if (dom_computed[dir] < DOM_NO_FAST_QUERY)
+ abort ();
+
+ if (dom_computed[dir] == DOM_OK)
+ return;
+
+ FOR_ALL_BB (bb)
+ {
+ if (!bb->dom[dir]->father)
+ assign_dfs_numbers (bb->dom[dir], &num);
+ }
+
+ dom_computed[dir] = DOM_OK;
+}
+
+/* The main entry point into this module. DIR is set depending on whether
+ we want to compute dominators or postdominators. */
+
+void
+calculate_dominance_info (enum cdi_direction dir)
{
struct dom_info di;
- dominance_info info;
basic_block b;
- /* Allocate structure for dominance information. */
- info = xmalloc (sizeof (struct dominance_info));
- info->forest = et_forest_create ();
- VARRAY_GENERIC_PTR_INIT (info->varray, last_basic_block + 3, "dominance info");
+ if (dom_computed[dir] == DOM_OK)
+ return;
- /* Add the two well-known basic blocks. */
- SET_BB_NODE (info, ENTRY_BLOCK_PTR, et_forest_add_node (info->forest,
- ENTRY_BLOCK_PTR));
- SET_BB_NODE (info, EXIT_BLOCK_PTR, et_forest_add_node (info->forest,
- EXIT_BLOCK_PTR));
- FOR_EACH_BB (b)
- SET_BB_NODE (info, b, et_forest_add_node (info->forest, b));
+ if (dom_computed[dir] != DOM_NO_FAST_QUERY)
+ {
+ if (dom_computed[dir] != DOM_NONE)
+ free_dominance_info (dir);
- init_dom_info (&di);
- calc_dfs_tree (&di, reverse);
- calc_idoms (&di, reverse);
+ FOR_ALL_BB (b)
+ {
+ b->dom[dir] = et_new_tree (b);
+ }
+ init_dom_info (&di);
+ calc_dfs_tree (&di, dir);
+ calc_idoms (&di, dir);
- FOR_EACH_BB (b)
- {
- TBB d = di.dom[di.dfs_order[b->index]];
+ FOR_EACH_BB (b)
+ {
+ TBB d = di.dom[di.dfs_order[b->index]];
+
+ if (di.dfs_to_bb[d])
+ et_set_father (b->dom[dir], di.dfs_to_bb[d]->dom[dir]);
+ }
- if (di.dfs_to_bb[d])
- et_forest_add_edge (info->forest, BB_NODE (info, di.dfs_to_bb[d]), BB_NODE (info, b));
+ free_dom_info (&di);
+ dom_computed[dir] = DOM_NO_FAST_QUERY;
}
- free_dom_info (&di);
- return info;
+ compute_dom_fast_query (dir);
}
-/* Free dominance information. */
+/* Free dominance information for direction DIR. */
void
-free_dominance_info (dominance_info info)
+free_dominance_info (enum cdi_direction dir)
{
basic_block bb;
- /* Allow users to create new basic block without setting up the dominance
- information for them. */
- FOR_EACH_BB (bb)
- if (bb->index < (int)(info->varray->num_elements - 2)
- && BB_NODE (info, bb))
- delete_from_dominance_info (info, bb);
- delete_from_dominance_info (info, ENTRY_BLOCK_PTR);
- delete_from_dominance_info (info, EXIT_BLOCK_PTR);
- et_forest_delete (info->forest);
- VARRAY_GROW (info->varray, 0);
- free (info);
+ if (!dom_computed[dir])
+ return;
+
+ FOR_ALL_BB (bb)
+ {
+ delete_from_dominance_info (dir, bb);
+ }
+
+ dom_computed[dir] = DOM_NONE;
}
/* Return the immediate dominator of basic block BB. */
basic_block
-get_immediate_dominator (dominance_info dom, basic_block bb)
+get_immediate_dominator (enum cdi_direction dir, basic_block bb)
{
- return et_forest_node_value (dom->forest,
- et_forest_parent (dom->forest,
- BB_NODE (dom, bb)));
+ struct et_node *node = bb->dom[dir];
+
+ if (!dom_computed[dir])
+ abort ();
+
+ if (!node->father)
+ return NULL;
+
+ return node->father->data;
}
/* Set the immediate dominator of the block possibly removing
existing edge. NULL can be used to remove any edge. */
inline void
-set_immediate_dominator (dominance_info dom, basic_block bb, basic_block dominated_by)
+set_immediate_dominator (enum cdi_direction dir, basic_block bb,
+ basic_block dominated_by)
{
- void *aux_bb_node;
- et_forest_node_t bb_node = BB_NODE (dom, bb);
+ struct et_node *node = bb->dom[dir];
+
+ if (!dom_computed[dir])
+ abort ();
- aux_bb_node = et_forest_parent (dom->forest, bb_node);
- if (aux_bb_node)
- et_forest_remove_edge (dom->forest, aux_bb_node, bb_node);
- if (dominated_by != NULL)
+ if (node->father)
{
- if (bb == dominated_by)
- abort ();
- if (!et_forest_add_edge (dom->forest, BB_NODE (dom, dominated_by), bb_node))
- abort ();
+ if (node->father->data == dominated_by)
+ return;
+ et_split (node);
}
+
+ if (dominated_by)
+ et_set_father (node, dominated_by->dom[dir]);
+
+ if (dom_computed[dir] == DOM_OK)
+ dom_computed[dir] = DOM_NO_FAST_QUERY;
}
-/* Store all basic blocks dominated by BB into BBS and return their number. */
+/* Store all basic blocks immediatelly dominated by BB into BBS and return
+ their number. */
int
-get_dominated_by (dominance_info dom, basic_block bb, basic_block **bbs)
+get_dominated_by (enum cdi_direction dir, basic_block bb, basic_block **bbs)
{
- int n, i;
+ int n;
+ struct et_node *node = bb->dom[dir], *son = node->son, *ason;
+
+ if (!dom_computed[dir])
+ abort ();
+
+ if (!son)
+ {
+ *bbs = NULL;
+ return 0;
+ }
+
+ for (ason = son->right, n = 1; ason != son; ason = ason->right)
+ n++;
+
+ *bbs = xmalloc (n * sizeof (basic_block));
+ (*bbs)[0] = son->data;
+ for (ason = son->right, n = 1; ason != son; ason = ason->right)
+ (*bbs)[n++] = ason->data;
- *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
- n = et_forest_enumerate_sons (dom->forest, BB_NODE (dom, bb), (et_forest_node_t *)*bbs);
- for (i = 0; i < n; i++)
- (*bbs)[i] = et_forest_node_value (dom->forest, (et_forest_node_t)(*bbs)[i]);
return n;
}
/* Redirect all edges pointing to BB to TO. */
void
-redirect_immediate_dominators (dominance_info dom, basic_block bb, basic_block to)
+redirect_immediate_dominators (enum cdi_direction dir, basic_block bb,
+ basic_block to)
{
- et_forest_node_t *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
- et_forest_node_t node = BB_NODE (dom, bb);
- et_forest_node_t node2 = BB_NODE (dom, to);
- int n = et_forest_enumerate_sons (dom->forest, node, bbs);
- int i;
+ struct et_node *bb_node = bb->dom[dir], *to_node = to->dom[dir], *son;
+
+ if (!dom_computed[dir])
+ abort ();
- for (i = 0; i < n; i++)
+ if (!bb_node->son)
+ return;
+
+ while (bb_node->son)
{
- et_forest_remove_edge (dom->forest, node, bbs[i]);
- et_forest_add_edge (dom->forest, node2, bbs[i]);
+ son = bb_node->son;
+
+ et_split (son);
+ et_set_father (son, to_node);
}
- free (bbs);
+
+ if (dom_computed[dir] == DOM_OK)
+ dom_computed[dir] = DOM_NO_FAST_QUERY;
}
/* Find first basic block in the tree dominating both BB1 and BB2. */
basic_block
-nearest_common_dominator (dominance_info dom, basic_block bb1, basic_block bb2)
+nearest_common_dominator (enum cdi_direction dir, basic_block bb1, basic_block bb2)
{
+ if (!dom_computed[dir])
+ abort ();
+
if (!bb1)
return bb2;
if (!bb2)
return bb1;
- return et_forest_node_value (dom->forest,
- et_forest_common_ancestor (dom->forest,
- BB_NODE (dom, bb1),
- BB_NODE (dom,
- bb2)));
+
+ return et_nca (bb1->dom[dir], bb2->dom[dir])->data;
}
/* Return TRUE in case BB1 is dominated by BB2. */
bool
-dominated_by_p (dominance_info dom, basic_block bb1, basic_block bb2)
+dominated_by_p (enum cdi_direction dir, basic_block bb1, basic_block bb2)
{
- return nearest_common_dominator (dom, bb1, bb2) == bb2;
+ struct et_node *n1 = bb1->dom[dir], *n2 = bb2->dom[dir];
+
+ if (!dom_computed[dir])
+ abort ();
+
+ if (dom_computed[dir] == DOM_OK)
+ return (n1->dfs_num_in >= n2->dfs_num_in
+ && n1->dfs_num_out <= n2->dfs_num_out);
+
+ return et_below (n1, n2);
}
/* Verify invariants of dominator structure. */
void
-verify_dominators (dominance_info dom)
+verify_dominators (enum cdi_direction dir)
{
int err = 0;
basic_block bb;
+ if (!dom_computed[dir])
+ abort ();
+
FOR_EACH_BB (bb)
{
basic_block dom_bb;
- dom_bb = recount_dominator (dom, bb);
- if (dom_bb != get_immediate_dominator (dom, bb))
+ dom_bb = recount_dominator (dir, bb);
+ if (dom_bb != get_immediate_dominator (dir, bb))
{
error ("dominator of %d should be %d, not %d",
- bb->index, dom_bb->index, get_immediate_dominator(dom, bb)->index);
+ bb->index, dom_bb->index, get_immediate_dominator(dir, bb)->index);
err = 1;
}
}
/* 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;
/* Iteratively recount dominators of BBS. The change is supposed to be local
and not to grow further. */
void
-iterate_fix_dominators (dominance_info dom, basic_block *bbs, int n)
+iterate_fix_dominators (enum cdi_direction dir, basic_block *bbs, int n)
{
int i, changed = 1;
basic_block old_dom, new_dom;
+ if (!dom_computed[dir])
+ abort ();
+
while (changed)
{
changed = 0;
for (i = 0; i < n; i++)
{
- old_dom = get_immediate_dominator (dom, bbs[i]);
- new_dom = recount_dominator (dom, bbs[i]);
+ old_dom = get_immediate_dominator (dir, bbs[i]);
+ new_dom = recount_dominator (dir, bbs[i]);
if (old_dom != new_dom)
{
changed = 1;
- set_immediate_dominator (dom, bbs[i], new_dom);
+ set_immediate_dominator (dir, bbs[i], new_dom);
}
}
}
}
void
-add_to_dominance_info (dominance_info dom, basic_block bb)
+add_to_dominance_info (enum cdi_direction dir, basic_block bb)
{
- VARRAY_GROW (dom->varray, last_basic_block + 3);
-#ifdef ENABLE_CHECKING
- if (BB_NODE (dom, bb))
+ if (!dom_computed[dir])
abort ();
-#endif
- SET_BB_NODE (dom, bb, et_forest_add_node (dom->forest, bb));
+
+ if (bb->dom[dir])
+ abort ();
+
+ bb->dom[dir] = et_new_tree (bb);
+
+ if (dom_computed[dir] == DOM_OK)
+ dom_computed[dir] = DOM_NO_FAST_QUERY;
}
void
-delete_from_dominance_info (dominance_info dom, basic_block bb)
+delete_from_dominance_info (enum cdi_direction dir, basic_block bb)
+{
+ if (!dom_computed[dir])
+ abort ();
+
+ et_free_tree (bb->dom[dir]);
+ bb->dom[dir] = NULL;
+
+ if (dom_computed[dir] == DOM_OK)
+ dom_computed[dir] = DOM_NO_FAST_QUERY;
+}
+
+/* Returns the first son of BB in the dominator or postdominator tree
+ as determined by DIR. */
+
+basic_block
+first_dom_son (enum cdi_direction dir, basic_block bb)
{
- et_forest_remove_node (dom->forest, BB_NODE (dom, bb));
- SET_BB_NODE (dom, bb, NULL);
+ struct et_node *son = bb->dom[dir]->son;
+
+ return son ? son->data : NULL;
+}
+
+/* Returns the next dominance son after BB in the dominator or postdominator
+ tree as determined by DIR, or NULL if it was the last one. */
+
+basic_block
+next_dom_son (enum cdi_direction dir, basic_block bb)
+{
+ struct et_node *next = bb->dom[dir]->right;
+
+ return next->father->son == next ? NULL : next->data;
}
void
-debug_dominance_info (dominance_info dom)
+debug_dominance_info (enum cdi_direction dir)
{
basic_block bb, bb2;
FOR_EACH_BB (bb)
- if ((bb2 = get_immediate_dominator (dom, bb)))
+ if ((bb2 = get_immediate_dominator (dir, bb)))
fprintf (stderr, "%i %i\n", bb->index, bb2->index);
}
#include "et-forest.h"
#include "alloc-pool.h"
-struct et_forest_occurrence;
-typedef struct et_forest_occurrence* et_forest_occurrence_t;
+/* We do not enable this with ENABLE_CHECKING, since it is awfully slow. */
+#undef DEBUG_ET
-/* The ET-forest type. */
-struct et_forest
-{
- /* Linked list of nodes is used to destroy the structure. */
- int nnodes;
- alloc_pool node_pool;
- alloc_pool occur_pool;
-};
+#ifdef DEBUG_ET
+#include "basic-block.h"
+#endif
-/* Single occurrence of node in ET-forest.
- A single node may have multiple occurrences.
- */
-struct et_forest_occurrence
+/* The occurence of a node in the et tree. */
+struct et_occ
{
- /* Parent in the splay-tree. */
- et_forest_occurrence_t parent;
+ struct et_node *of; /* The node. */
+
+ struct et_occ *parent; /* Parent in the splay-tree. */
+ struct et_occ *prev; /* Left son in the splay-tree. */
+ struct et_occ *next; /* Right son in the splay-tree. */
+
+ int depth; /* The depth of the node is the sum of depth
+ fields on the path to the root. */
+ int min; /* The minimum value of the depth in the subtree
+ is obtained by adding sum of depth fields
+ on the path to the root. */
+ struct et_occ *min_occ; /* The occurence in the subtree with the minimal
+ depth. */
+};
- /* Children in the splay-tree. */
- et_forest_occurrence_t left, right;
+static alloc_pool et_nodes;
+static alloc_pool et_occurences;
- /* Counts of vertices in the two splay-subtrees. */
- int count_left, count_right;
+/* Changes depth of OCC to D. */
- /* Next occurrence of this node in the sequence. */
- et_forest_occurrence_t next;
+static inline void
+set_depth (struct et_occ *occ, int d)
+{
+ if (!occ)
+ return;
- /* The node, which this occurrence is of. */
- et_forest_node_t node;
-};
+ occ->min += d - occ->depth;
+ occ->depth = d;
+}
+/* Adds D to the depth of OCC. */
-/* ET-forest node. */
-struct et_forest_node
+static inline void
+set_depth_add (struct et_occ *occ, int d)
{
- et_forest_t forest;
- void *value;
-
- /* First and last occurrence of this node in the sequence. */
- et_forest_occurrence_t first, last;
-};
+ if (!occ)
+ return;
+ occ->min += d;
+ occ->depth += d;
+}
-static et_forest_occurrence_t splay (et_forest_occurrence_t);
-static void remove_all_occurrences (et_forest_t, et_forest_node_t);
-static inline et_forest_occurrence_t find_leftmost_node
- (et_forest_occurrence_t);
-static inline et_forest_occurrence_t find_rightmost_node
- (et_forest_occurrence_t);
-static int calculate_value (et_forest_occurrence_t);
+/* Sets prev field of OCC to P. */
-/* Return leftmost node present in the tree roted by OCC. */
-static inline et_forest_occurrence_t
-find_leftmost_node (et_forest_occurrence_t occ)
+static inline void
+set_prev (struct et_occ *occ, struct et_occ *t)
{
- while (occ->left)
- occ = occ->left;
+#ifdef DEBUG_ET
+ if (occ == t)
+ abort ();
+#endif
- return occ;
+ occ->prev = t;
+ if (t)
+ t->parent = occ;
}
-/* Return rightmost node present in the tree roted by OCC. */
-static inline et_forest_occurrence_t
-find_rightmost_node (et_forest_occurrence_t occ)
+/* Sets next field of OCC to P. */
+
+static inline void
+set_next (struct et_occ *occ, struct et_occ *t)
{
- while (occ->right)
- occ = occ->right;
- return occ;
+#ifdef DEBUG_ET
+ if (occ == t)
+ abort ();
+#endif
+
+ occ->next = t;
+ if (t)
+ t->parent = occ;
}
+/* Recompute minimum for occurence OCC. */
-/* Operation splay for splay tree structure representing occurrences. */
-static et_forest_occurrence_t
-splay (et_forest_occurrence_t node)
+static inline void
+et_recomp_min (struct et_occ *occ)
{
- et_forest_occurrence_t parent;
- et_forest_occurrence_t grandparent;
+ struct et_occ *mson = occ->prev;
- while (1)
- {
- parent = node->parent;
+ if (!mson
+ || (occ->next
+ && mson->min > occ->next->min))
+ mson = occ->next;
- if (! parent)
- return node; /* node == root. */
+ if (mson && mson->min < 0)
+ {
+ occ->min = mson->min + occ->depth;
+ occ->min_occ = mson->min_occ;
+ }
+ else
+ {
+ occ->min = occ->depth;
+ occ->min_occ = occ;
+ }
+}
- grandparent = parent->parent;
+#ifdef DEBUG_ET
+/* Checks whether neighbourhood of OCC seems sane. */
- if (! grandparent)
- break;
+static void
+et_check_occ_sanity (struct et_occ *occ)
+{
+ if (!occ)
+ return;
- /* Now there are four possible combinations: */
+ if (occ->parent == occ)
+ abort ();
- if (node == parent->left)
- {
- if (parent == grandparent->left)
- {
- et_forest_occurrence_t node1, node2;
- int count1, count2;
-
- node1 = node->right;
- count1 = node->count_right;
- node2 = parent->right;
- count2 = parent->count_right;
-
- grandparent->left = node2;
- grandparent->count_left = count2;
- if (node2)
- node2->parent = grandparent;
- parent->left = node1;
- parent->count_left = count1;
- if (node1)
- node1->parent = parent;
- parent->right = grandparent;
- parent->count_right = count2 + grandparent->count_right + 1;
- node->right = parent;
- node->count_right = count1 + parent->count_right + 1;
-
- node->parent = grandparent->parent;
- parent->parent = node;
- grandparent->parent = parent;
-
- if (node->parent)
- {
- if (node->parent->left == grandparent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
- }
- else
- {
- /* parent == grandparent->right && node == parent->left*/
- et_forest_occurrence_t node1, node2;
- int count1, count2;
-
- node1 = node->left;
- count1 = node->count_left;
- node2 = node->right;
- count2 = node->count_right;
-
- grandparent->right = node1;
- grandparent->count_right = count1;
- if (node1)
- node1->parent = grandparent;
- parent->left = node2;
- parent->count_left = count2;
- if (node2)
- node2->parent = parent;
- node->left = grandparent;
- node->count_left = grandparent->count_left + count1 + 1;
- node->right = parent;
- node->count_right = parent->count_right + count2 + 1;
-
- node->parent = grandparent->parent;
- parent->parent = node;
- grandparent->parent = node;
-
- if (node->parent)
- {
- if (node->parent->left == grandparent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
- }
- }
- else
- {
- /* node == parent->right. */
- if (parent == grandparent->left)
- {
- et_forest_occurrence_t node1, node2;
- int count1, count2;
-
- node1 = node->left;
- count1 = node->count_left;
- node2 = node->right;
- count2 = node->count_right;
-
- parent->right = node1;
- parent->count_right = count1;
- if (node1)
- node1->parent = parent;
- grandparent->left = node2;
- grandparent->count_left = count2;
- if (node2)
- node2->parent = grandparent;
- node->left = parent;
- node->count_left = parent->count_left + count1 + 1;
- node->right = grandparent;
- node->count_right = grandparent->count_right + count2 + 1;
-
- node->parent = grandparent->parent;
- parent->parent = node;
- grandparent->parent = node;
-
- if (node->parent)
- {
- if (node->parent->left == grandparent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
- }
- else
- {
- /* parent == grandparent->right && node == parent->right*/
- et_forest_occurrence_t node1, node2;
- int count1, count2;
-
- node1 = node->left;
- count1 = node->count_left;
- node2 = parent->left;
- count2 = parent->count_left;
-
- grandparent->right = node2;
- grandparent->count_right = count2;
- if (node2)
- node2->parent = grandparent;
- parent->right = node1;
- parent->count_right = count1;
- if (node1)
- node1->parent = parent;
- parent->left = grandparent;
- parent->count_left = count2 + grandparent->count_left + 1;
- node->left = parent;
- node->count_left = count1 + parent->count_left + 1;
-
- node->parent = grandparent->parent;
- parent->parent = node;
- grandparent->parent = parent;
-
- if (node->parent)
- {
- if (node->parent->left == grandparent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
- }
- }
+ if (occ->prev == occ)
+ abort ();
- }
+ if (occ->next == occ)
+ abort ();
- /* parent == root. */
- /* There are two possible combinations: */
+ if (occ->next && occ->next == occ->prev)
+ abort ();
- if (node == parent->left)
+ if (occ->next)
{
- et_forest_occurrence_t node1;
- int count1;
-
- node1 = node->right;
- count1 = node->count_right;
-
- parent->left = node1;
- parent->count_left = count1;
- if (node1)
- node1->parent = parent;
- node->right = parent;
- node->count_right = parent->count_right + 1 + count1;
- node->parent = parent->parent; /* the same as = 0; */
- parent->parent = node;
-
- if (node->parent)
- {
- if (node->parent->left == parent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
+ if (occ->next == occ->parent)
+ abort ();
+
+ if (occ->next->parent != occ)
+ abort ();
}
- else
+
+ if (occ->prev)
{
- /* node == parent->right. */
- et_forest_occurrence_t node1;
- int count1;
-
- node1 = node->left;
- count1 = node->count_left;
-
- parent->right = node1;
- parent->count_right = count1;
- if (node1)
- node1->parent = parent;
- node->left = parent;
- node->count_left = parent->count_left + 1 + count1;
- node->parent = parent->parent; /* the same as = 0; */
- parent->parent = node;
-
- if (node->parent)
- {
- if (node->parent->left == parent)
- node->parent->left = node;
- else
- node->parent->right = node;
- }
+ if (occ->prev == occ->parent)
+ abort ();
+
+ if (occ->prev->parent != occ)
+ abort ();
}
- return node;
+ if (occ->parent
+ && occ->parent->prev != occ
+ && occ->parent->next != occ)
+ abort ();
}
-/* Remove all occurrences of the given node before destroying the node. */
+/* Checks whether tree rooted at OCC is sane. */
+
static void
-remove_all_occurrences (et_forest_t forest, et_forest_node_t forest_node)
+et_check_sanity (struct et_occ *occ)
{
- et_forest_occurrence_t first = forest_node->first;
- et_forest_occurrence_t last = forest_node->last;
- et_forest_occurrence_t node;
+ et_check_occ_sanity (occ);
+ if (occ->prev)
+ et_check_sanity (occ->prev);
+ if (occ->next)
+ et_check_sanity (occ->next);
+}
- splay (first);
+/* Checks whether tree containing OCC is sane. */
- if (first->left)
- first->left->parent = 0;
- if (first->right)
- first->right->parent = 0;
+static void
+et_check_tree_sanity (struct et_occ *occ)
+{
+ while (occ->parent)
+ occ = occ->parent;
- if (last != first)
- {
- splay (last);
+ et_check_sanity (occ);
+}
- if (last->left)
- last->left->parent = 0;
- if (last->right)
- last->right->parent = 0;
- }
+/* For recording the paths. */
- if (last->right && first->left) /* actually, first->left would suffice. */
- {
- /* Need to join them. */
- et_forest_occurrence_t prev_node, next_node;
-
- prev_node = splay (find_rightmost_node (first->left));
- next_node = splay (find_leftmost_node (last->right));
- /* prev_node and next_node are consecutive occurrences
- of the same node. */
- if (prev_node->next != next_node)
- abort ();
+static int len;
+static void *datas[100000];
+static int depths[100000];
- prev_node->right = next_node->right;
- prev_node->count_right = next_node->count_right;
- prev_node->next = next_node->next;
- if (prev_node->right)
- prev_node->right->parent = prev_node;
+/* Records the path represented by OCC, with depth incremented by DEPTH. */
- if (prev_node->node->last == next_node)
- prev_node->node->last = prev_node;
+static int
+record_path_before_1 (struct et_occ *occ, int depth)
+{
+ int mn, m;
- pool_free (forest->occur_pool, next_node);
+ depth += occ->depth;
+ mn = depth;
+
+ if (occ->prev)
+ {
+ m = record_path_before_1 (occ->prev, depth);
+ if (m < mn)
+ mn = m;
}
- if (first != last)
+ fprintf (stderr, "%d (%d); ", ((basic_block) occ->of->data)->index, depth);
+ depths[len] = depth;
+ datas[len] = occ->of;
+ len++;
+
+ if (occ->next)
{
- node = first->next;
+ m = record_path_before_1 (occ->next, depth);
+ if (m < mn)
+ mn = m;
+ }
- while (node != last)
- {
- et_forest_occurrence_t next_node;
+ if (mn != occ->min + depth - occ->depth)
+ abort ();
- splay (node);
+ return mn;
+}
- if (node->left)
- node->left->parent = 0;
- if (node->right)
- node->right->parent = 0;
+/* Records the path represented by a tree containing OCC. */
- next_node = node->next;
- pool_free (forest->occur_pool, node);
- node = next_node;
- }
- }
+static void
+record_path_before (struct et_occ *occ)
+{
+ while (occ->parent)
+ occ = occ->parent;
- pool_free (forest->occur_pool, first);
- if (first != last)
- pool_free (forest->occur_pool, last);
+ len = 0;
+ record_path_before_1 (occ, 0);
+ fprintf (stderr, "\n");
}
-/* Calculate ET value of the given node. */
-static inline int
-calculate_value (et_forest_occurrence_t node)
+/* Checks whether the path represented by OCC, with depth incremented by DEPTH,
+ was not changed since the last recording. */
+
+static int
+check_path_after_1 (struct et_occ *occ, int depth)
{
- int value = node->count_left;
+ int mn, m;
+
+ depth += occ->depth;
+ mn = depth;
- while (node->parent)
+ if (occ->next)
{
- if (node == node->parent->right)
- value += node->parent->count_left + 1;
+ m = check_path_after_1 (occ->next, depth);
+ if (m < mn)
+ mn = m;
+ }
- node = node->parent;
+ len--;
+ if (depths[len] != depth
+ || datas[len] != occ->of)
+ abort ();
+
+ if (occ->prev)
+ {
+ m = check_path_after_1 (occ->prev, depth);
+ if (m < mn)
+ mn = m;
}
- return value;
+ if (mn != occ->min + depth - occ->depth)
+ abort ();
+
+ return mn;
}
+/* Checks whether the path represented by a tree containing OCC was
+ not changed since the last recording. */
+
+static void
+check_path_after (struct et_occ *occ)
+{
+ while (occ->parent)
+ occ = occ->parent;
+
+ check_path_after_1 (occ, 0);
+ if (len != 0)
+ abort ();
+}
+#endif
+/* Splay the occurence OCC to the root of the tree. */
-/* Create ET-forest structure. */
-et_forest_t
-et_forest_create (void)
+static inline void
+et_splay (struct et_occ *occ)
{
- et_forest_t forest = xmalloc (sizeof (struct et_forest));
+ struct et_occ *f, *gf, *ggf;
+ int occ_depth, f_depth, gf_depth;
+
+#ifdef DEBUG_ET
+ record_path_before (occ);
+ et_check_tree_sanity (occ);
+#endif
+
+ while (occ->parent)
+ {
+ occ_depth = occ->depth;
- forest->nnodes = 0;
- forest->occur_pool = create_alloc_pool ("et_forest_occurrence pool", sizeof (struct et_forest_occurrence), 300);
- forest->node_pool = create_alloc_pool ("et_forest_node pool", sizeof (struct et_forest_node), 300);
- return forest;
-}
+ f = occ->parent;
+ f_depth = f->depth;
+ gf = f->parent;
+ if (!gf)
+ {
+ set_depth_add (occ, f_depth);
+ occ->min_occ = f->min_occ;
+ occ->min = f->min;
-/* Deallocate the structure. */
-void
-et_forest_delete (et_forest_t forest)
+ if (f->prev == occ)
+ {
+ /* zig */
+ set_prev (f, occ->next);
+ set_next (occ, f);
+ set_depth_add (f->prev, occ_depth);
+ }
+ else
+ {
+ /* zag */
+ set_next (f, occ->prev);
+ set_prev (occ, f);
+ set_depth_add (f->next, occ_depth);
+ }
+ set_depth (f, -occ_depth);
+ occ->parent = NULL;
+
+ et_recomp_min (f);
+#ifdef DEBUG_ET
+ et_check_tree_sanity (occ);
+ check_path_after (occ);
+#endif
+ return;
+ }
+
+ gf_depth = gf->depth;
+
+ set_depth_add (occ, f_depth + gf_depth);
+ occ->min_occ = gf->min_occ;
+ occ->min = gf->min;
+
+ ggf = gf->parent;
+
+ if (gf->prev == f)
+ {
+ if (f->prev == occ)
+ {
+ /* zig zig */
+ set_prev (gf, f->next);
+ set_prev (f, occ->next);
+ set_next (occ, f);
+ set_next (f, gf);
+
+ set_depth (f, -occ_depth);
+ set_depth_add (f->prev, occ_depth);
+ set_depth (gf, -f_depth);
+ set_depth_add (gf->prev, f_depth);
+ }
+ else
+ {
+ /* zag zig */
+ set_prev (gf, occ->next);
+ set_next (f, occ->prev);
+ set_prev (occ, f);
+ set_next (occ, gf);
+
+ set_depth (f, -occ_depth);
+ set_depth_add (f->next, occ_depth);
+ set_depth (gf, -occ_depth - f_depth);
+ set_depth_add (gf->prev, occ_depth + f_depth);
+ }
+ }
+ else
+ {
+ if (f->prev == occ)
+ {
+ /* zig zag */
+ set_next (gf, occ->prev);
+ set_prev (f, occ->next);
+ set_prev (occ, gf);
+ set_next (occ, f);
+
+ set_depth (f, -occ_depth);
+ set_depth_add (f->prev, occ_depth);
+ set_depth (gf, -occ_depth - f_depth);
+ set_depth_add (gf->next, occ_depth + f_depth);
+ }
+ else
+ {
+ /* zag zag */
+ set_next (gf, f->prev);
+ set_next (f, occ->prev);
+ set_prev (occ, f);
+ set_prev (f, gf);
+
+ set_depth (f, -occ_depth);
+ set_depth_add (f->next, occ_depth);
+ set_depth (gf, -f_depth);
+ set_depth_add (gf->next, f_depth);
+ }
+ }
+
+ occ->parent = ggf;
+ if (ggf)
+ {
+ if (ggf->prev == gf)
+ ggf->prev = occ;
+ else
+ ggf->next = occ;
+ }
+
+ et_recomp_min (gf);
+ et_recomp_min (f);
+#ifdef DEBUG_ET
+ et_check_tree_sanity (occ);
+#endif
+ }
+
+#ifdef DEBUG_ET
+ et_check_sanity (occ);
+ check_path_after (occ);
+#endif
+}
+
+/* Create a new et tree occurence of NODE. */
+
+static struct et_occ *
+et_new_occ (struct et_node *node)
{
- if (forest->nnodes)
- abort ();
- free_alloc_pool (forest->occur_pool);
- free_alloc_pool (forest->node_pool);
- free (forest);
+ struct et_occ *nw;
+
+ if (!et_occurences)
+ et_occurences = create_alloc_pool ("et_occ pool", sizeof (struct et_occ), 300);
+ nw = pool_alloc (et_occurences);
+
+ nw->of = node;
+ nw->parent = NULL;
+ nw->prev = NULL;
+ nw->next = NULL;
+
+ nw->depth = 0;
+ nw->min_occ = nw;
+ nw->min = 0;
+
+ return nw;
}
-/* Create new node with VALUE and return the edge.
- Return NULL when memory allocation failed. */
-et_forest_node_t
-et_forest_add_node (et_forest_t forest, void *value)
+/* Create a new et tree containing DATA. */
+
+struct et_node *
+et_new_tree (void *data)
{
- /* Create node with one occurrence. */
- et_forest_node_t node;
- et_forest_occurrence_t occ;
-
- node = pool_alloc (forest->node_pool);
- occ = pool_alloc (forest->occur_pool);
-
- node->first = node->last = occ;
- node->value = value;
- forest->nnodes++;
-
- occ->node = node;
- occ->left = occ->right = occ->parent = 0;
- occ->next = 0;
- occ->count_left = occ->count_right = 0;
- return node;
+ struct et_node *nw;
+
+ if (!et_nodes)
+ et_nodes = create_alloc_pool ("et_node pool", sizeof (struct et_node), 300);
+ nw = pool_alloc (et_nodes);
+
+ nw->data = data;
+ nw->father = NULL;
+ nw->left = NULL;
+ nw->right = NULL;
+ nw->son = NULL;
+
+ nw->rightmost_occ = et_new_occ (nw);
+ nw->parent_occ = NULL;
+
+ return nw;
}
-/* Add new edge to the tree, return 1 if successful.
- 0 indicates that creation of the edge will close the cycle in graph. */
-int
-et_forest_add_edge (et_forest_t forest ATTRIBUTE_UNUSED,
- et_forest_node_t parent_node, et_forest_node_t child_node)
+/* Releases et tree T. */
+
+void
+et_free_tree (struct et_node *t)
{
- et_forest_occurrence_t new_occ, parent_occ, child_occ;
+ while (t->son)
+ et_split (t->son);
- if (! parent_node || ! child_node)
- abort ();
+ if (t->father)
+ et_split (t);
- parent_occ = parent_node->first;
- child_occ = child_node->first;
-
- splay (parent_occ);
- splay (child_occ);
-
- if (parent_occ->parent)
- return 0; /* Both child and parent are in the same tree. */
-
- if (child_occ->left)
- abort (); /* child must be root of its containing tree. */
-
- new_occ = pool_alloc (forest->occur_pool);
-
- new_occ->node = parent_node;
- new_occ->left = child_occ;
- new_occ->count_left = child_occ->count_right + 1; /* count_left is 0. */
- new_occ->right = parent_occ->right;
- new_occ->count_right = parent_occ->count_right;
- new_occ->parent = parent_occ;
- new_occ->next = parent_occ->next;
- child_occ->parent = new_occ;
- parent_occ->right = new_occ;
- parent_occ->count_right = new_occ->count_left + new_occ->count_right + 1;
- parent_occ->next = new_occ;
- if (new_occ->right)
- new_occ->right->parent = new_occ;
-
- if (parent_node->last == parent_occ)
- parent_node->last = new_occ;
- return 1;
+ pool_free (et_occurences, t->rightmost_occ);
+ pool_free (et_nodes, t);
}
-/* Remove NODE from the tree and all connected edges. */
+/* Sets father of et tree T to FATHER. */
+
void
-et_forest_remove_node (et_forest_t forest, et_forest_node_t node)
+et_set_father (struct et_node *t, struct et_node *father)
{
- remove_all_occurrences (forest, node);
- forest->nnodes--;
+ struct et_node *left, *right;
+ struct et_occ *rmost, *left_part, *new_f_occ, *p;
- pool_free (forest->node_pool, node);
-}
+ /* Update the path represented in the splay tree. */
+ new_f_occ = et_new_occ (father);
-/* Remove edge from the tree, return 1 if successful,
- 0 indicates nonexisting edge. */
-int
-et_forest_remove_edge (et_forest_t forest ATTRIBUTE_UNUSED,
- et_forest_node_t parent_node,
- et_forest_node_t child_node)
-{
- et_forest_occurrence_t parent_pre_occ, parent_post_occ;
+ rmost = father->rightmost_occ;
+ et_splay (rmost);
- splay (child_node->first);
+ left_part = rmost->prev;
- if (! child_node->first->left)
- return 0;
+ p = t->rightmost_occ;
+ et_splay (p);
- parent_pre_occ = find_rightmost_node (child_node->first->left);
- if (parent_pre_occ->node != parent_node)
- abort ();
+ set_prev (new_f_occ, left_part);
+ set_next (new_f_occ, p);
+
+ p->depth++;
+ p->min++;
+ et_recomp_min (new_f_occ);
- splay (parent_pre_occ);
- parent_pre_occ->right->parent = 0;
+ set_prev (rmost, new_f_occ);
- parent_post_occ = parent_pre_occ->next;
- splay (parent_post_occ);
+ if (new_f_occ->min + rmost->depth < rmost->min)
+ {
+ rmost->min = new_f_occ->min + rmost->depth;
+ rmost->min_occ = new_f_occ->min_occ;
+ }
- parent_post_occ->left->parent = 0;
+ t->parent_occ = new_f_occ;
- parent_pre_occ->right = parent_post_occ->right;
- parent_pre_occ->count_right = parent_post_occ->count_right;
- if (parent_post_occ->right)
- parent_post_occ->right->parent = parent_pre_occ;
+ /* Update the tree. */
+ t->father = father;
+ right = father->son;
+ if (right)
+ left = right->left;
+ else
+ left = right = t;
- parent_pre_occ->next = parent_post_occ->next;
+ left->right = t;
+ right->left = t;
+ t->left = left;
+ t->right = right;
- if (parent_post_occ == parent_node->last)
- parent_node->last = parent_pre_occ;
+ father->son = t;
- pool_free (forest->occur_pool, parent_post_occ);
- return 1;
+#ifdef DEBUG_ET
+ et_check_tree_sanity (rmost);
+ record_path_before (rmost);
+#endif
}
-/* Return the parent of the NODE if any, NULL otherwise. */
-et_forest_node_t
-et_forest_parent (et_forest_t forest ATTRIBUTE_UNUSED, et_forest_node_t node)
+/* Splits the edge from T to its father. */
+
+void
+et_split (struct et_node *t)
{
- splay (node->first);
+ struct et_node *father = t->father;
+ struct et_occ *r, *l, *rmost, *p_occ;
- if (node->first->left)
- return find_rightmost_node (node->first->left)->node;
- else
- return 0;
-}
+ /* Update the path represented by the splay tree. */
+ rmost = t->rightmost_occ;
+ et_splay (rmost);
+ for (r = rmost->next; r->prev; r = r->prev)
+ continue;
+ et_splay (r);
-/* Return nearest common ancestor of NODE1 and NODE2.
- Return NULL of they are in different trees. */
-et_forest_node_t
-et_forest_common_ancestor (et_forest_t forest ATTRIBUTE_UNUSED,
- et_forest_node_t node1, et_forest_node_t node2)
-{
- int value1, value2, max_value;
- et_forest_node_t ancestor;
+ r->prev->parent = NULL;
+ p_occ = t->parent_occ;
+ et_splay (p_occ);
+ t->parent_occ = NULL;
- if (node1 == node2)
- return node1;
+ l = p_occ->prev;
+ p_occ->next->parent = NULL;
- if (! node1 || ! node2)
- abort ();
+ set_prev (r, l);
- splay (node1->first);
- splay (node2->first);
+ et_recomp_min (r);
- if (! node1->first->parent) /* The two vertices are in different trees. */
- return 0;
+ et_splay (rmost);
+ rmost->depth = 0;
+ rmost->min = 0;
- value2 = calculate_value (node2->first);
- value1 = calculate_value (node1->first);
+ pool_free (et_occurences, p_occ);
- if (value1 < value2)
+ /* Update the tree. */
+ if (father->son == t)
+ father->son = t->right;
+ if (father->son == t)
+ father->son = NULL;
+ else
{
- ancestor = node1;
- max_value = value2;
+ t->left->right = t->right;
+ t->right->left = t->left;
+ }
+ t->left = t->right = NULL;
+ t->father = NULL;
+
+#ifdef DEBUG_ET
+ et_check_tree_sanity (rmost);
+ record_path_before (rmost);
+
+ et_check_tree_sanity (r);
+ record_path_before (r);
+#endif
+}
+
+/* Finds the nearest common ancestor of the nodes N1 and N2. */
+
+struct et_node *
+et_nca (struct et_node *n1, struct et_node *n2)
+{
+ struct et_occ *o1 = n1->rightmost_occ, *o2 = n2->rightmost_occ, *om;
+ struct et_occ *l, *r, *ret;
+ int mn;
+
+ if (n1 == n2)
+ return n1;
+
+ et_splay (o1);
+ l = o1->prev;
+ r = o1->next;
+ if (l)
+ l->parent = NULL;
+ if (r)
+ r->parent = NULL;
+ et_splay (o2);
+
+ if (l == o2 || (l && l->parent != NULL))
+ {
+ ret = o2->next;
+
+ set_prev (o1, o2);
+ if (r)
+ r->parent = o1;
}
else
{
- ancestor = node2;
- max_value = value1;
+ ret = o2->prev;
+
+ set_next (o1, o2);
+ if (l)
+ l->parent = o1;
}
- while (calculate_value (ancestor->last) < max_value)
+ if (0 < o2->depth)
{
- /* Find parent node. */
- splay (ancestor->first);
- ancestor = find_rightmost_node (ancestor->first->left) ->node;
+ om = o1;
+ mn = o1->depth;
+ }
+ else
+ {
+ om = o2;
+ mn = o2->depth + o1->depth;
}
- return ancestor;
-}
+#ifdef DEBUG_ET
+ et_check_tree_sanity (o2);
+#endif
-/* Return the value pointer of node set during it's creation. */
-void *
-et_forest_node_value (et_forest_t forest ATTRIBUTE_UNUSED,
- et_forest_node_t node)
-{
- /* Alloc threading NULL as a special node of the forest. */
- if (!node)
- return NULL;
- return node->value;
+ if (ret && ret->min + o1->depth + o2->depth < mn)
+ return ret->min_occ->of;
+ else
+ return om->of;
}
-/* Find all sons of NODE and store them into ARRAY allocated by the caller.
- Return number of nodes found. */
-int
-et_forest_enumerate_sons (et_forest_t forest ATTRIBUTE_UNUSED,
- et_forest_node_t node, et_forest_node_t *array)
+/* Checks whether the node UP is an ancestor of the node DOWN. */
+
+bool
+et_below (struct et_node *down, struct et_node *up)
{
- int n = 0;
- et_forest_occurrence_t occ = node->first, stop = node->last, occ1;
+ struct et_occ *u = up->rightmost_occ, *d = down->rightmost_occ;
+ struct et_occ *l, *r;
+
+ if (up == down)
+ return true;
+
+ et_splay (u);
+ l = u->prev;
+ r = u->next;
+
+ if (!l)
+ return false;
+
+ l->parent = NULL;
+
+ if (r)
+ r->parent = NULL;
- /* Parent is the rightmost node of the left successor.
- Look for all occurrences having no right successor
- and lookup the sons. */
- while (occ != stop)
+ et_splay (d);
+
+ if (l == d || l->parent != NULL)
{
- splay (occ);
- if (occ->right)
- {
- occ1 = find_leftmost_node (occ->right);
- if (occ1->node->first == occ1)
- array[n++] = occ1->node;
- }
- occ = occ->next;
+ if (r)
+ r->parent = u;
+ set_prev (u, d);
+#ifdef DEBUG_ET
+ et_check_tree_sanity (u);
+#endif
}
- return n;
+ else
+ {
+ l->parent = u;
+
+ /* In case O1 and O2 are in two different trees, we must just restore the
+ original state. */
+ if (r && r->parent != NULL)
+ set_next (u, d);
+ else
+ set_next (u, r);
+
+#ifdef DEBUG_ET
+ et_check_tree_sanity (u);
+#endif
+ return false;
+ }
+
+ if (0 >= d->depth)
+ return false;
+
+ return !d->next || d->next->min + d->depth >= 0;
}
extern "C" {
#endif /* __cplusplus */
-typedef struct et_forest *et_forest_t;
-typedef struct et_forest_node *et_forest_node_t;
-
-extern et_forest_t et_forest_create (void);
-
-extern void et_forest_delete (et_forest_t);
-
-extern et_forest_node_t et_forest_add_node (et_forest_t, void *);
-extern int et_forest_add_edge (et_forest_t, et_forest_node_t,
- et_forest_node_t);
-extern void et_forest_remove_node (et_forest_t, et_forest_node_t);
-extern int et_forest_remove_edge (et_forest_t, et_forest_node_t,
- et_forest_node_t);
-extern et_forest_node_t et_forest_parent (et_forest_t, et_forest_node_t);
-extern et_forest_node_t et_forest_common_ancestor (et_forest_t,
- et_forest_node_t,
- et_forest_node_t);
-extern void * et_forest_node_value (et_forest_t, et_forest_node_t);
-extern int et_forest_enumerate_sons (et_forest_t, et_forest_node_t,
- et_forest_node_t *);
+/* The node representing the node in an et tree. */
+struct et_node
+{
+ void *data; /* The data represented by the node. */
+
+ int dfs_num_in, dfs_num_out; /* Number of the node in the dfs ordering. */
+
+ struct et_node *father; /* Father of the node. */
+ struct et_node *son; /* The first of the sons of the node. */
+ struct et_node *left;
+ struct et_node *right; /* The brothers of the node. */
+
+ struct et_occ *rightmost_occ; /* The rightmost occurence. */
+ struct et_occ *parent_occ; /* The occurence of the parent node. */
+};
+
+struct et_node *et_new_tree (void *data);
+void et_free_tree (struct et_node *);
+void et_set_father (struct et_node *, struct et_node *);
+void et_split (struct et_node *);
+struct et_node *et_nca (struct et_node *, struct et_node *);
+bool et_below (struct et_node *, struct et_node *);
#ifdef __cplusplus
}
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))
{
/* For function.c. */
- /* Name of this function. */
- const char *name;
-
/* Points to the FUNCTION_DECL of this function. */
tree decl;
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)
#include "basic-block.h"
#include "output.h"
#include "function.h"
+#include "langhooks.h"
#include "expr.h"
#include "except.h"
#include "ggc.h"
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);
}
{
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);
}
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);
}
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);
}
/* 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.
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.
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");
}
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++)
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);
}
#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"
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;
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;
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;
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"
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);
{
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;
/* 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);
edge e;
flow_loops_find (&loops, LOOP_TREE);
+ free_dominance_info (CDI_DOMINATORS);
if (loops.num > 1)
{
{
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++;
}
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++;
}
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++;
}
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++;
}
&& 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))
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);
}
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
{
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. */
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
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++;
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 ();
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);
/* 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)
flow_loops_dump (loops, dumpfile, NULL, 1);
#ifdef ENABLE_CHECKING
- verify_dominators (loops->cfg.dom);
+ verify_dominators (CDI_DOMINATORS);
verify_loop_structure (loops);
#endif
/* Clean up. */
flow_loops_free (loops);
+ free_dominance_info (CDI_DOMINATORS);
free (loops);
/* Finalize changes. */
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 *);
if (check)
{
#ifdef ENABLE_CHECKING
- verify_dominators (loops->cfg.dom);
+ verify_dominators (CDI_DOMINATORS);
verify_loop_structure (loops);
#endif
}
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
}
/* 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;
}
/* 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");
}
/* 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. */
/* 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;
/* 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;
}
/* 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;
/* 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;
}
/* 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;
/* 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;
}
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];
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;
/* 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++)
{
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,
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);
/* 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,
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);
}
/* 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. */
/* 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;
/* 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;
}
/* 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;
/* 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;
}
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);
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
}
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;
/* 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
/* 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)
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)
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 ();
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. */
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;
}
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);
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. */
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;
/* 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;
&& 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);
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;
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];
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);
}
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;
/* Process single prediction note. */
process_note_prediction (bb,
heads,
- dominators,
- post_dominators,
alg, (int) NOTE_PREDICTION_FLAGS (insn));
delete_insn (insn);
}
/* 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);
}
}
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);
/* 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 ();
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);
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;
{
/* 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;
}
}
}
else
{
- dominance_info dom;
struct edge_list *edge_list;
/* The scheduler runs after estimate_probabilities; therefore, we
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
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 ();
/* 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);
}
}
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);
}
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);
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)