Commit f470c378 by Zdenek Dvorak Committed by Zdenek Dvorak

Makefile.in (cfghooks.o): Add TIMEVAR_H and toplev.h dependency.

	* Makefile.in (cfghooks.o): Add TIMEVAR_H and toplev.h dependency.
	* basic-block.h (tidy_fallthru_edge, tidy_fallthru_edges, dump_bb,
	verify_flow_info): Declaration removed.
	* cfg.c (verify_flow_info, dump_bb): Moved to cfghooks.c.
	(debug_bb, debug_bb_n): Add argument to dump_bb call.
	* cfgcleanup.c (try_simplify_condjump, try_crossjump_to_edge,
	try_optimize_cfg, delete_unreachable_blocks): Use delete_basic_block
	instead of delete_block.
	* cfghooks.c: Include timevar.h and toplev.h.
	(cfg_hooks): Define here.
	(verify_flow_info, dump_bb): Moved from cfg.c.
	(redirect_edge_and_branch, redirect_edge_and_branch_force,
	split_block, split_block_after_labels, move_block_after,
	delete_basic_block, split_edge, create_basic_block,
	create_empty_bb, can_merge_blocks_p, merge_blocks,
	make_forwarder_block, tidy_fallthru_edge, tidy_fallthru_edges):
	New functions.
	* cfghooks.h (struct cfg_hooks): Added fields name,
	make_forwarder_block, tidy_fallthru_edge and
	move_block_after. Changed type of verify_flow_info, dump_bb,
	split_block fields. Renamed cfgh_split_edge and delete_block
	fields.
	(redirect_edge_and_branch, redirect_edge_and_branch_force,
	split_block, delete_block, split_edge, create_basic_block,
	can_merge_blocks_p, merge_blocks): Macros removed.
	(cfg_hooks): Do not export.
	(verify_flow_info, dump_bb, redirect_edge_and_branch,
	redirect_edge_and_branch_force, split_block, split_block_after_labels,
	move_block_after, delete_basic_block, split_edge, create_basic_block,
	create_empty_bb, can_merge_blocks_p, merge_blocks,
	make_forwarder_block, tidy_fallthru_edge, tidy_fallthru_edges):
	Declare.
	(cfg_layout_rtl_cfg_hooks): Declare.
	* cfgloop.c (update_latch_info, mfb_keep_just, mfb_keep_nonlatch):
	New functions.
	(canonicalize_loop_headers): Use new semantics of make_forwarder_block.
	(redirect_edge_with_latch_update): Removed.
	(make_forwarder_block): Moved to cfghooks.c, semantics changed.
	* cfgloopmanip.c (remove_bbs): Do not update dominators here.
	* cfgrtl.c (cfg_layout_split_block, rtl_split_block, rtl_dump_bb,
	rtl_delete_block, rtl_split_block, rtl_merge_blocks,
	tidy_fallthru_edge, rtl_split_edge, cfg_layout_delete_block,
	cfg_layout_merge_blocks, cfg_layout_split_edge): Partly moved to
	cfghooks.c.
	(rtl_create_basic_block): Coding style fix.
	(rtl_tidy_fallthru_edge, rtl_move_block_after,
	rtl_make_forwarder_block): New functions.
	(update_cfg_after_block_merging): Removed.
	(rtl_cfg_hooks, cfg_layout_rtl_cfg_hooks): Fill in new entries.
	* flow.c (verify_wide_reg, verify_local_live_at_start): Add argument
	to dump_bb.
	* ifcvt.c (merge_if_block, find_cond_trap, find_if_case_1,
	find_if_case_2): Don't update dominators.
	* timevar.def (TV_CFG_VERIFY): New.
	* loop-unswitch.c (unswitch_loop): Don't call add_to_dominance_info.
	* cfglayout.c (copy_bbs): Don't call add_to_dominance_info.
	* cfgloopmanip.c (split_loop_bb): Don't update dominators.
	(remove_bbs): Don't call remove_bbs.
	(create_preheader): Use make_forwarder_block.
	(mfb_keep_just, mfb_update_loops): New static functions.

From-SVN: r76851
parent 3cea4788
2004-01-29 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* Makefile.in (cfghooks.o): Add TIMEVAR_H and toplev.h dependency.
* basic-block.h (tidy_fallthru_edge, tidy_fallthru_edges, dump_bb,
verify_flow_info): Declaration removed.
* cfg.c (verify_flow_info, dump_bb): Moved to cfghooks.c.
(debug_bb, debug_bb_n): Add argument to dump_bb call.
* cfgcleanup.c (try_simplify_condjump, try_crossjump_to_edge,
try_optimize_cfg, delete_unreachable_blocks): Use delete_basic_block
instead of delete_block.
* cfghooks.c: Include timevar.h and toplev.h.
(cfg_hooks): Define here.
(verify_flow_info, dump_bb): Moved from cfg.c.
(redirect_edge_and_branch, redirect_edge_and_branch_force,
split_block, split_block_after_labels, move_block_after,
delete_basic_block, split_edge, create_basic_block,
create_empty_bb, can_merge_blocks_p, merge_blocks,
make_forwarder_block, tidy_fallthru_edge, tidy_fallthru_edges):
New functions.
* cfghooks.h (struct cfg_hooks): Added fields name,
make_forwarder_block, tidy_fallthru_edge and
move_block_after. Changed type of verify_flow_info, dump_bb,
split_block fields. Renamed cfgh_split_edge and delete_block
fields.
(redirect_edge_and_branch, redirect_edge_and_branch_force,
split_block, delete_block, split_edge, create_basic_block,
can_merge_blocks_p, merge_blocks): Macros removed.
(cfg_hooks): Do not export.
(verify_flow_info, dump_bb, redirect_edge_and_branch,
redirect_edge_and_branch_force, split_block, split_block_after_labels,
move_block_after, delete_basic_block, split_edge, create_basic_block,
create_empty_bb, can_merge_blocks_p, merge_blocks,
make_forwarder_block, tidy_fallthru_edge, tidy_fallthru_edges):
Declare.
(cfg_layout_rtl_cfg_hooks): Declare.
* cfgloop.c (update_latch_info, mfb_keep_just, mfb_keep_nonlatch):
New functions.
(canonicalize_loop_headers): Use new semantics of make_forwarder_block.
(redirect_edge_with_latch_update): Removed.
(make_forwarder_block): Moved to cfghooks.c, semantics changed.
* cfgloopmanip.c (remove_bbs): Do not update dominators here.
* cfgrtl.c (cfg_layout_split_block, rtl_split_block, rtl_dump_bb,
rtl_delete_block, rtl_split_block, rtl_merge_blocks,
tidy_fallthru_edge, rtl_split_edge, cfg_layout_delete_block,
cfg_layout_merge_blocks, cfg_layout_split_edge): Partly moved to
cfghooks.c.
(rtl_create_basic_block): Coding style fix.
(rtl_tidy_fallthru_edge, rtl_move_block_after,
rtl_make_forwarder_block): New functions.
(update_cfg_after_block_merging): Removed.
(rtl_cfg_hooks, cfg_layout_rtl_cfg_hooks): Fill in new entries.
* flow.c (verify_wide_reg, verify_local_live_at_start): Add argument
to dump_bb.
* ifcvt.c (merge_if_block, find_cond_trap, find_if_case_1,
find_if_case_2): Don't update dominators.
* timevar.def (TV_CFG_VERIFY): New.
* loop-unswitch.c (unswitch_loop): Don't call add_to_dominance_info.
* cfglayout.c (copy_bbs): Don't call add_to_dominance_info.
* cfgloopmanip.c (split_loop_bb): Don't update dominators.
(remove_bbs): Don't call remove_bbs.
(create_preheader): Use make_forwarder_block.
(mfb_keep_just, mfb_update_loops): New static functions.
2004-01-29 Kazu Hirata <kazu@cs.umass.edu>
* config/avr/avr.h: Remove target-independent comments about
......
......@@ -1686,7 +1686,7 @@ cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h insn-
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(GGC_H) $(TM_P_H) alloc-pool.h
cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
$(BASIC_BLOCK_H) cfglayout.h
$(BASIC_BLOCK_H) cfglayout.h $(TIMEVAR_H) toplev.h
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(GGC_H) $(TM_P_H) insn-config.h $(EXPR_H)
......
......@@ -363,8 +363,6 @@ extern edge redirect_edge_succ_nodup (edge, basic_block);
extern void redirect_edge_pred (edge, basic_block);
extern basic_block create_basic_block_structure (rtx, rtx, rtx, basic_block);
extern void clear_bb_flags (void);
extern void tidy_fallthru_edge (edge, basic_block, basic_block);
extern void tidy_fallthru_edges (void);
extern void flow_reverse_top_sort_order_compute (int *);
extern int flow_depth_first_order_compute (int *, int *);
extern void flow_preorder_transversal_compute (int *);
......@@ -537,7 +535,6 @@ extern bool probably_never_executed_bb_p (basic_block);
/* In flow.c */
extern void init_flow (void);
extern void dump_bb (basic_block, FILE *);
extern void debug_bb (basic_block);
extern basic_block debug_bb_n (int);
extern void dump_regset (regset, FILE *);
......@@ -570,11 +567,6 @@ extern void alloc_aux_for_edges (int);
extern void clear_aux_for_edges (void);
extern void free_aux_for_edges (void);
/* This function is always defined so it can be called from the
debugger, and it is declared extern so we don't get warnings about
it being unused. */
extern void verify_flow_info (void);
typedef struct conflict_graph_def *conflict_graph;
/* Callback function when enumerating conflicts. The arguments are
......
......@@ -810,185 +810,16 @@ free_aux_for_edges (void)
clear_aux_for_edges ();
}
/* Verify the CFG consistency.
Currently it does following checks edge and basic block list correctness
and calls into IL dependent checking then. */
void
verify_flow_info (void)
{
size_t *edge_checksum;
int num_bb_notes, err = 0;
basic_block bb, last_bb_seen;
basic_block *last_visited;
last_visited = xcalloc (last_basic_block + 2, sizeof (basic_block));
edge_checksum = xcalloc (last_basic_block + 2, sizeof (size_t));
/* Check bb chain & numbers. */
last_bb_seen = ENTRY_BLOCK_PTR;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
{
if (bb != EXIT_BLOCK_PTR
&& bb != BASIC_BLOCK (bb->index))
{
error ("bb %d on wrong place", bb->index);
err = 1;
}
if (bb->prev_bb != last_bb_seen)
{
error ("prev_bb of %d should be %d, not %d",
bb->index, last_bb_seen->index, bb->prev_bb->index);
err = 1;
}
last_bb_seen = bb;
}
/* Now check the basic blocks (boundaries etc.) */
FOR_EACH_BB_REVERSE (bb)
{
int n_fallthru = 0;
edge e;
if (bb->count < 0)
{
error ("verify_flow_info: Wrong count of block %i %i",
bb->index, (int)bb->count);
err = 1;
}
if (bb->frequency < 0)
{
error ("verify_flow_info: Wrong frequency of block %i %i",
bb->index, bb->frequency);
err = 1;
}
for (e = bb->succ; e; e = e->succ_next)
{
if (last_visited [e->dest->index + 2] == bb)
{
error ("verify_flow_info: Duplicate edge %i->%i",
e->src->index, e->dest->index);
err = 1;
}
if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
{
error ("verify_flow_info: Wrong probability of edge %i->%i %i",
e->src->index, e->dest->index, e->probability);
err = 1;
}
if (e->count < 0)
{
error ("verify_flow_info: Wrong count of edge %i->%i %i",
e->src->index, e->dest->index, (int)e->count);
err = 1;
}
last_visited [e->dest->index + 2] = bb;
if (e->flags & EDGE_FALLTHRU)
n_fallthru++;
if (e->src != bb)
{
error ("verify_flow_info: Basic block %d succ edge is corrupted",
bb->index);
fprintf (stderr, "Predecessor: ");
dump_edge_info (stderr, e, 0);
fprintf (stderr, "\nSuccessor: ");
dump_edge_info (stderr, e, 1);
fprintf (stderr, "\n");
err = 1;
}
edge_checksum[e->dest->index + 2] += (size_t) e;
}
if (n_fallthru > 1)
{
error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
err = 1;
}
for (e = bb->pred; e; e = e->pred_next)
{
if (e->dest != bb)
{
error ("basic block %d pred edge is corrupted", bb->index);
fputs ("Predecessor: ", stderr);
dump_edge_info (stderr, e, 0);
fputs ("\nSuccessor: ", stderr);
dump_edge_info (stderr, e, 1);
fputc ('\n', stderr);
err = 1;
}
edge_checksum[e->dest->index + 2] -= (size_t) e;
}
}
/* Complete edge checksumming for ENTRY and EXIT. */
{
edge e;
for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
edge_checksum[e->dest->index + 2] += (size_t) e;
for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
edge_checksum[e->dest->index + 2] -= (size_t) e;
}
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
if (edge_checksum[bb->index + 2])
{
error ("basic block %i edge lists are corrupted", bb->index);
err = 1;
}
num_bb_notes = 0;
last_bb_seen = ENTRY_BLOCK_PTR;
/* Clean up. */
free (last_visited);
free (edge_checksum);
err |= cfg_hooks->cfgh_verify_flow_info ();
if (err)
internal_error ("verify_flow_info failed");
}
/* Print out one basic block with live information at start and end. */
void
dump_bb (basic_block bb, FILE *outf)
{
edge e;
fprintf (outf, ";; Basic block %d, loop depth %d, count ",
bb->index, bb->loop_depth);
fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
putc ('\n', outf);
fputs (";; Predecessors: ", outf);
for (e = bb->pred; e; e = e->pred_next)
dump_edge_info (outf, e, 0);
putc ('\n', outf);
cfg_hooks->dump_bb (bb, outf);
fputs (";; Successors: ", outf);
for (e = bb->succ; e; e = e->succ_next)
dump_edge_info (outf, e, 1);
putc ('\n', outf);
}
void
debug_bb (basic_block bb)
{
dump_bb (bb, stderr);
dump_bb (bb, stderr, 0);
}
basic_block
debug_bb_n (int n)
{
basic_block bb = BASIC_BLOCK (n);
dump_bb (bb, stderr);
dump_bb (bb, stderr, 0);
return bb;
}
......@@ -194,8 +194,8 @@ try_simplify_condjump (basic_block cbranch_block)
}
}
/* Delete the block with the unconditional jump, and clean up the mess. */
delete_block (jump_block);
tidy_fallthru_edge (cbranch_jump_edge, cbranch_block, cbranch_dest_block);
delete_basic_block (jump_block);
tidy_fallthru_edge (cbranch_jump_edge);
return true;
}
......@@ -1530,7 +1530,7 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
to_remove = redirect_from->succ->dest;
redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
delete_block (to_remove);
delete_basic_block (to_remove);
update_forwarder_flag (redirect_from);
......@@ -1694,7 +1694,7 @@ try_optimize_cfg (int mode)
fprintf (rtl_dump_file, "Deleting block %i.\n",
b->index);
delete_block (b);
delete_basic_block (b);
if (!(mode & CLEANUP_CFGLAYOUT))
changed = true;
b = c;
......@@ -1755,7 +1755,7 @@ try_optimize_cfg (int mode)
c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
redirect_edge_succ_nodup (b->pred, b->succ->dest);
delete_block (b);
delete_basic_block (b);
changed = true;
b = c;
}
......@@ -1873,7 +1873,7 @@ delete_unreachable_blocks (void)
if (!(b->flags & BB_REACHABLE))
{
delete_block (b);
delete_basic_block (b);
changed = true;
}
}
......
......@@ -24,10 +24,12 @@ Boston, MA 02111-1307, USA. */
struct cfg_hooks
{
/* Debugging. Do not use macros to hook these so they can be called from
debugger! */
int (*cfgh_verify_flow_info) (void);
void (*dump_bb) (basic_block, FILE *);
/* Name of the corresponding ir. */
const char *name;
/* Debugging. */
int (*verify_flow_info) (void);
void (*dump_bb) (basic_block, FILE *, int);
/* Basic CFG manipulation. */
......@@ -44,11 +46,15 @@ struct cfg_hooks
on abnormal edge. */
basic_block (*redirect_edge_and_branch_force) (edge, basic_block);
/* Remove given basic block and all edges possibly pointing into it. */
void (*delete_block) (basic_block);
/* Remove statements corresponding to a given basic block. */
void (*delete_basic_block) (basic_block);
/* Creates a new basic block just after basic block B by splitting
everything after specified instruction I. */
basic_block (*split_block) (basic_block b, void * i);
/* Split basic block B after specified instruction I. */
edge (*split_block) (basic_block b, void * i);
/* Move block B immediately after block A. */
bool (*move_block_after) (basic_block b, basic_block a);
/* Return true when blocks A and B can be merged into single basic block. */
bool (*can_merge_blocks_p) (basic_block a, basic_block b);
......@@ -58,23 +64,34 @@ struct cfg_hooks
/* Higher level functions representable by primitive operations above if
we didn't have some oddities in RTL and Tree representations. */
basic_block (*cfgh_split_edge) (edge);
basic_block (*split_edge) (edge);
void (*make_forwarder_block) (edge);
/* Tries to make the edge fallthru. */
void (*tidy_fallthru_edge) (edge);
};
#define redirect_edge_and_branch(e,b) cfg_hooks->redirect_edge_and_branch (e,b)
#define redirect_edge_and_branch_force(e,b) cfg_hooks->redirect_edge_and_branch_force (e,b)
#define split_block(e,i) cfg_hooks->split_block (e,i)
#define delete_block(b) cfg_hooks->delete_block (b)
#define split_edge(e) cfg_hooks->cfgh_split_edge (e)
#define create_basic_block(h,e,a) cfg_hooks->create_basic_block (h,e,a)
#define can_merge_blocks_p(a,b) cfg_hooks->can_merge_blocks_p (a,b)
#define merge_blocks(a,b) cfg_hooks->merge_blocks (a,b)
extern void verify_flow_info (void);
extern void dump_bb (basic_block, FILE *, int);
extern bool redirect_edge_and_branch (edge, basic_block);
extern basic_block redirect_edge_and_branch_force (edge, basic_block);
extern edge split_block (basic_block, void *);
extern edge split_block_after_labels (basic_block);
extern bool move_block_after (basic_block, basic_block);
extern void delete_basic_block (basic_block);
extern basic_block split_edge (edge);
extern basic_block create_basic_block (void *, void *, basic_block);
extern basic_block create_empty_bb (basic_block);
extern bool can_merge_blocks_p (basic_block, basic_block);
extern void merge_blocks (basic_block, basic_block);
extern edge make_forwarder_block (basic_block, bool (*)(edge),
void (*) (basic_block));
extern void tidy_fallthru_edge (edge);
extern void tidy_fallthru_edges (void);
/* Hooks containers. */
extern struct cfg_hooks rtl_cfg_hooks;
/* A pointer to one of the hooks containers. */
extern struct cfg_hooks *cfg_hooks;
extern struct cfg_hooks cfg_layout_rtl_cfg_hooks;
/* Declarations. */
extern void rtl_register_cfg_hooks (void);
......
......@@ -1268,7 +1268,6 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
bb->rbi->duplicated = 1;
/* Add to loop. */
add_bb_to_loop (new_bb, bb->loop_father->copy);
add_to_dominance_info (CDI_DOMINATORS, new_bb);
/* Possibly set header. */
if (bb->loop_father->header == bb && bb->loop_father != base)
new_bb->loop_father->header = new_bb;
......
......@@ -33,6 +33,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
considered to belong to inner loop with same header. */
#define HEAVY_EDGE_RATIO 8
#define HEADER_BLOCK(B) (* (int *) (B)->aux)
#define LATCH_EDGE(E) (*(int *) (E)->aux)
static void flow_loops_cfg_dump (const struct loops *, FILE *);
static void flow_loop_entry_edges_find (struct loop *);
static void flow_loop_exit_edges_find (struct loop *);
......@@ -42,10 +45,8 @@ 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 *);
static basic_block make_forwarder_block (basic_block, int, int, edge, int);
static void canonicalize_loop_headers (void);
static bool glb_enum_p (basic_block, void *);
static void redirect_edge_with_latch_update (edge, basic_block);
/* Dump loop related CFG information. */
......@@ -547,78 +548,41 @@ flow_loop_scan (struct loop *loop, int flags)
return 1;
}
#define HEADER_BLOCK(B) (* (int *) (B)->aux)
#define LATCH_EDGE(E) (*(int *) (E)->aux)
/* A callback to update latch and header info for basic block JUMP created
by redirecting an edge. */
/* Redirect edge and update latch and header info. */
static void
redirect_edge_with_latch_update (edge e, basic_block to)
update_latch_info (basic_block jump)
{
basic_block jump;
jump = redirect_edge_and_branch_force (e, to);
if (jump)
{
alloc_aux_for_block (jump, sizeof (int));
HEADER_BLOCK (jump) = 0;
alloc_aux_for_edge (jump->pred, sizeof (int));
LATCH_EDGE (jump->succ) = LATCH_EDGE (e);
LATCH_EDGE (jump->pred) = 0;
}
alloc_aux_for_block (jump, sizeof (int));
HEADER_BLOCK (jump) = 0;
alloc_aux_for_edge (jump->pred, sizeof (int));
LATCH_EDGE (jump->pred) = 0;
}
/* Split BB into entry part and rest; if REDIRECT_LATCH, redirect edges
marked as latch into entry part, analogically for REDIRECT_NONLATCH.
In both of these cases, ignore edge EXCEPT. If CONN_LATCH, set edge
between created entry part and BB as latch one. Return created entry
part. */
/* A callback for make_forwarder block, to redirect all edges except for
MFB_KJ_EDGE to the entry part. E is the edge for that we should decide
whether to redirect it. */
static basic_block
make_forwarder_block (basic_block bb, int redirect_latch, int redirect_nonlatch, edge except, int conn_latch)
static edge mfb_kj_edge;
static bool
mfb_keep_just (edge e)
{
edge e, next_e, fallthru;
basic_block dummy;
rtx insn;
insn = PREV_INSN (first_insn_after_basic_block_note (bb));
/* For empty block split_block will return NULL. */
if (BB_END (bb) == insn)
emit_note_after (NOTE_INSN_DELETED, insn);
fallthru = split_block (bb, insn);
dummy = fallthru->src;
bb = fallthru->dest;
bb->aux = xmalloc (sizeof (int));
HEADER_BLOCK (dummy) = 0;
HEADER_BLOCK (bb) = 1;
/* Redirect back edges we want to keep. */
for (e = dummy->pred; e; e = next_e)
{
next_e = e->pred_next;
if (e == except
|| !((redirect_latch && LATCH_EDGE (e))
|| (redirect_nonlatch && !LATCH_EDGE (e))))
{
dummy->frequency -= EDGE_FREQUENCY (e);
dummy->count -= e->count;
if (dummy->frequency < 0)
dummy->frequency = 0;
if (dummy->count < 0)
dummy->count = 0;
redirect_edge_with_latch_update (e, bb);
}
}
return e != mfb_kj_edge;
}
alloc_aux_for_edge (fallthru, sizeof (int));
LATCH_EDGE (fallthru) = conn_latch;
/* A callback for make_forwarder block, to redirect the latch edges into an
entry part. E is the edge for that we should decide whether to redirect
it. */
return dummy;
static bool
mfb_keep_nonlatch (edge e)
{
return LATCH_EDGE (e);
}
/* Takes care of merging natural loops with shared headers. */
static void
canonicalize_loop_headers (void)
{
......@@ -675,19 +639,10 @@ canonicalize_loop_headers (void)
FOR_EACH_BB (header)
{
int num_latch;
int want_join_latch;
int max_freq, is_heavy;
edge heavy;
edge heavy, tmp_edge;
if (!HEADER_BLOCK (header))
continue;
num_latch = HEADER_BLOCK (header);
want_join_latch = (num_latch > 1);
if (!want_join_latch)
if (HEADER_BLOCK (header) <= 1)
continue;
/* Find a heavy edge. */
......@@ -713,13 +668,28 @@ canonicalize_loop_headers (void)
if (is_heavy)
{
basic_block new_header =
make_forwarder_block (header, true, true, heavy, 0);
if (num_latch > 2)
make_forwarder_block (new_header, true, false, NULL, 1);
/* Split out the heavy edge, and create inner loop for it. */
mfb_kj_edge = heavy;
tmp_edge = make_forwarder_block (header, mfb_keep_just,
update_latch_info);
alloc_aux_for_block (tmp_edge->dest, sizeof (int));
HEADER_BLOCK (tmp_edge->dest) = 1;
alloc_aux_for_edge (tmp_edge, sizeof (int));
LATCH_EDGE (tmp_edge) = 0;
HEADER_BLOCK (header)--;
}
if (HEADER_BLOCK (header) > 1)
{
/* Create a new latch block. */
tmp_edge = make_forwarder_block (header, mfb_keep_nonlatch,
update_latch_info);
alloc_aux_for_block (tmp_edge->dest, sizeof (int));
HEADER_BLOCK (tmp_edge->src) = 0;
HEADER_BLOCK (tmp_edge->dest) = 1;
alloc_aux_for_edge (tmp_edge, sizeof (int));
LATCH_EDGE (tmp_edge) = 1;
}
else
make_forwarder_block (header, true, false, NULL, 1);
}
free_aux_for_blocks ();
......
......@@ -63,11 +63,6 @@ split_loop_bb (basic_block bb, rtx insn)
/* Add dest to loop. */
add_bb_to_loop (e->dest, e->src->loop_father);
/* Fix dominators. */
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;
}
......@@ -88,8 +83,7 @@ remove_bbs (basic_block *bbs, int nbbs)
for (i = 0; i < nbbs; i++)
{
remove_bb_from_loops (bbs[i]);
delete_from_dominance_info (CDI_DOMINATORS, bbs[i]);
delete_block (bbs[i]);
delete_basic_block (bbs[i]);
}
}
......@@ -1070,19 +1064,45 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
return true;
}
/* A callback for make_forwarder block, to redirect all edges except for
MFB_KJ_EDGE to the entry part. E is the edge for that we should decide
whether to redirect it. */
static edge mfb_kj_edge;
static bool
mfb_keep_just (edge e)
{
return e != mfb_kj_edge;
}
/* A callback for make_forwarder block, to update data structures for a basic
block JUMP created by redirecting an edge (only the latch edge is being
redirected). */
static void
mfb_update_loops (basic_block jump)
{
struct loop *loop = jump->succ->dest->loop_father;
if (dom_computed[CDI_DOMINATORS])
set_immediate_dominator (CDI_DOMINATORS, jump, jump->pred->src);
add_bb_to_loop (jump, loop);
loop->latch = jump;
}
/* Creates a pre-header for a LOOP. Returns newly created block. Unless
CP_SIMPLE_PREHEADERS is set in FLAGS, we only force LOOP to have single
entry; otherwise we also force preheader block to have only one successor.
The function also updates dominators stored in DOM. */
The function also updates dominators. */
static basic_block
create_preheader (struct loop *loop, int flags)
{
edge e, fallthru;
basic_block dummy;
basic_block jump, src = 0;
struct loop *cloop, *ploop;
int nentry = 0;
rtx insn;
bool irred = false;
cloop = loop->outer;
......@@ -1090,6 +1110,7 @@ create_preheader (struct loop *loop, int flags)
{
if (e->src == loop->latch)
continue;
irred |= (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
nentry++;
}
if (!nentry)
......@@ -1102,17 +1123,9 @@ create_preheader (struct loop *loop, int flags)
return NULL;
}
insn = first_insn_after_basic_block_note (loop->header);
if (insn)
insn = PREV_INSN (insn);
else
insn = get_last_insn ();
if (insn == BB_END (loop->header))
{
/* Split_block would not split block after its end. */
emit_note_after (NOTE_INSN_DELETED, insn);
}
fallthru = split_block (loop->header, insn);
mfb_kj_edge = loop_latch_edge (loop);
fallthru = make_forwarder_block (loop->header, mfb_keep_just,
mfb_update_loops);
dummy = fallthru->src;
loop->header = fallthru->dest;
......@@ -1122,35 +1135,22 @@ create_preheader (struct loop *loop, int flags)
if (ploop->latch == dummy)
ploop->latch = fallthru->dest;
add_to_dominance_info (CDI_DOMINATORS, fallthru->dest);
/* Redirect edges. */
/* Reorganize blocks so that the preheader is not stuck in the middle of the
loop. */
for (e = dummy->pred; e; e = e->pred_next)
{
src = e->src;
if (src == loop->latch)
break;
}
if (!e)
abort ();
if (e->src != loop->latch)
break;
move_block_after (dummy, e->src);
loop->header->loop_father = loop;
add_bb_to_loop (dummy, cloop);
dummy->frequency -= EDGE_FREQUENCY (e);
dummy->count -= e->count;
fallthru->count -= e->count;
jump = redirect_edge_and_branch_force (e, loop->header);
if (jump)
if (irred)
{
add_to_dominance_info (CDI_DOMINATORS, jump);
set_immediate_dominator (CDI_DOMINATORS, jump, src);
add_bb_to_loop (jump, loop);
loop->latch = jump;
dummy->flags |= BB_IRREDUCIBLE_LOOP;
dummy->succ->flags |= EDGE_IRREDUCIBLE_LOOP;
}
/* Update structures. */
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)
fprintf (rtl_dump_file, "Created preheader block for loop %i\n",
loop->num);
......@@ -1212,7 +1212,6 @@ loop_split_edge_with (edge e, rtx insns)
/* Create basic block for it. */
new_bb = split_edge (e);
add_to_dominance_info (CDI_DOMINATORS, new_bb);
add_bb_to_loop (new_bb, loop_c);
new_bb->flags = insns ? BB_SUPERBLOCK : 0;
......@@ -1226,10 +1225,6 @@ loop_split_edge_with (edge e, rtx insns)
if (insns)
emit_insn_after (insns, BB_END (new_bb));
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;
......
......@@ -517,7 +517,7 @@ verify_wide_reg (int regno, basic_block bb)
if (rtl_dump_file)
{
fprintf (rtl_dump_file, "Register %d died unexpectedly.\n", regno);
dump_bb (bb, rtl_dump_file);
dump_bb (bb, rtl_dump_file, 0);
}
abort ();
}
......@@ -541,7 +541,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb)
bb->index);
debug_bitmap_file (rtl_dump_file, new_live_at_start);
fputs ("Old:\n", rtl_dump_file);
dump_bb (bb, rtl_dump_file);
dump_bb (bb, rtl_dump_file, 0);
}
abort ();
}
......@@ -562,7 +562,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb)
{
fprintf (rtl_dump_file,
"Register %d died unexpectedly.\n", i);
dump_bb (bb, rtl_dump_file);
dump_bb (bb, rtl_dump_file, 0);
}
abort ();
}
......
......@@ -2103,8 +2103,6 @@ merge_if_block (struct ce_if_block * ce_info)
{
bb = fallthru;
fallthru = block_fallthru (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++;
}
......@@ -2120,8 +2118,6 @@ merge_if_block (struct ce_if_block * ce_info)
if (combo_bb->global_live_at_end)
COPY_REG_SET (combo_bb->global_live_at_end,
then_bb->global_live_at_end);
if (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++;
}
......@@ -2131,8 +2127,6 @@ merge_if_block (struct ce_if_block * ce_info)
get their addresses taken. */
if (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++;
}
......@@ -2188,8 +2182,6 @@ merge_if_block (struct ce_if_block * ce_info)
COPY_REG_SET (combo_bb->global_live_at_end,
join_bb->global_live_at_end);
if (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++;
}
......@@ -2205,7 +2197,7 @@ merge_if_block (struct ce_if_block * ce_info)
/* Remove the jump and cruft from the end of the COMBO block. */
if (join_bb != EXIT_BLOCK_PTR)
tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
tidy_fallthru_edge (combo_bb->succ);
}
num_updated_if_blocks++;
......@@ -2643,11 +2635,7 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
/* Delete the trap block if possible. */
remove_edge (trap_bb == then_bb ? then_edge : else_edge);
if (trap_bb->pred == NULL)
{
if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
delete_from_dominance_info (CDI_POST_DOMINATORS, trap_bb);
delete_block (trap_bb);
}
delete_basic_block (trap_bb);
/* If the non-trap block and the test are now adjacent, merge them.
Otherwise we must insert a direct branch. */
......@@ -2829,9 +2817,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
then_bb_index = then_bb->index;
if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb);
delete_block (then_bb);
delete_basic_block (then_bb);
/* Make rest of code believe that the newly created block is the THEN_BB
block we removed. */
......@@ -2839,8 +2825,6 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
{
new_bb->index = then_bb_index;
BASIC_BLOCK (then_bb_index) = new_bb;
if (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. */
......@@ -2909,9 +2893,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
then_bb->global_live_at_start,
else_bb->global_live_at_end, BITMAP_IOR);
if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb);
delete_block (else_bb);
delete_basic_block (else_bb);
num_true_changes++;
num_updated_if_blocks++;
......
......@@ -381,7 +381,6 @@ unswitch_loop (struct loops *loops, struct loop *loop, basic_block unswitch_on)
switch_bb->succ->flags &= ~EDGE_IRREDUCIBLE_LOOP;
switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP;
}
add_to_dominance_info (CDI_DOMINATORS, switch_bb);
unswitch_on->rbi->copy = unswitch_on_alt;
/* Loopify from the copy of LOOP body, constructing the new loop. */
......
......@@ -45,6 +45,7 @@ DEFTIMEVAR (TV_CGRAPHOPT , "callgraph optimization")
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */
DEFTIMEVAR (TV_CLEANUP_CFG , "cfg cleanup")
DEFTIMEVAR (TV_CFG_VERIFY , "CFG verifier")
DEFTIMEVAR (TV_DELETE_TRIVIALLY_DEAD , "trivially dead code")
/* Time spent by life analysis. */
DEFTIMEVAR (TV_LIFE , "life analysis")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment