Commit 4262e623 by Jan Hubicka Committed by Jan Hubicka

basic-block.h (EDGE_CRITICAL): Remove; renumber other flags.

	* basic-block.h (EDGE_CRITICAL): Remove; renumber other flags.
	(EDGE_CRITICAL_P): New predicate.
	* cfg.c (force_nonfallthru_and_redirect, split_edge): Kill EDGE_CRITICAL
	handling.
	(insert_insn_on_edge): Use EDGE_CRITICAL_P.
	(dump_edge_info): Remove "crit".
	* cfganal.c (mark_critical_edges): Kill.
	* cfgbuild.c (find_basic_blocks): Remove mark_critical_edges call.
	* cfgcleanup.c (cleanup_cfg): Likewise.
	* profile.c (instrument_edges): Use EDGE_CRITICAL_P.
	(find_spanning_tree): Likewise.
	* reg-stack.c (convert_regs_1): Likewise.
	* ssa.c (mark_regs_equivalent_over_bad_edges): Likewise.

	* basic-block.h (create_basic_block_structure): New.
	(create_basic_block): Update prototype.
	(force_nonfallthru): New.
	* bb-reorder.c (fixup_reorder_chain): Fixup use force_nonfallthru.
	* cfg.c (create_basic_block_structure): Rename from create_basic_block;
	handle updating of block_for_insn, creating of empty BBs and BBs at
	the end of INSN chain.
	(create_basic_block): New function.
	(split_block): Use create_basic_block.
	(force_nonfallthru_and_redirect): Break out from ...; cleanup
	(redirect_edge_and_branch_force): ... here.
	(force_nonfallthru): New.
	(split_edge): Rewrite to use force_nonfallthru and create_block.
	* cfgbuild.c (find_basic_blocks_1): Use create_basic_block_structure.
	(find_basic_blocks): Free basic_block_for_insn.
	* cfgcleanup.c (merge_blocks): Use force_nonfallthru.

	* cfg.c: Fix formating.
	* cfgcleanup.c: Fix formating.
	(merge_blocks, tail_recursion_label_p): Return bool.
	(merge_blocks_move_predecessor_nojumps,
	 merge_blocks_move_successor_nojumps): Return void.

From-SVN: r45549
parent 201556f0
Tue Sep 11 18:57:47 CEST 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (EDGE_CRITICAL): Remove; renumber other flags.
(EDGE_CRITICAL_P): New predicate.
* cfg.c (force_nonfallthru_and_redirect, split_edge): Kill EDGE_CRITICAL
handling.
(insert_insn_on_edge): Use EDGE_CRITICAL_P.
(dump_edge_info): Remove "crit".
* cfganal.c (mark_critical_edges): Kill.
* cfgbuild.c (find_basic_blocks): Remove mark_critical_edges call.
* cfgcleanup.c (cleanup_cfg): Likewise.
* profile.c (instrument_edges): Use EDGE_CRITICAL_P.
(find_spanning_tree): Likewise.
* reg-stack.c (convert_regs_1): Likewise.
* ssa.c (mark_regs_equivalent_over_bad_edges): Likewise.
* basic-block.h (create_basic_block_structure): New.
(create_basic_block): Update prototype.
(force_nonfallthru): New.
* bb-reorder.c (fixup_reorder_chain): Fixup use force_nonfallthru.
* cfg.c (create_basic_block_structure): Rename from create_basic_block;
handle updating of block_for_insn, creating of empty BBs and BBs at
the end of INSN chain.
(create_basic_block): New function.
(split_block): Use create_basic_block.
(force_nonfallthru_and_redirect): Break out from ...; cleanup
(redirect_edge_and_branch_force): ... here.
(force_nonfallthru): New.
(split_edge): Rewrite to use force_nonfallthru and create_block.
* cfgbuild.c (find_basic_blocks_1): Use create_basic_block_structure.
(find_basic_blocks): Free basic_block_for_insn.
* cfgcleanup.c (merge_blocks): Use force_nonfallthru.
* cfg.c: Fix formating.
* cfgcleanup.c: Fix formating.
(merge_blocks, tail_recursion_label_p): Return bool.
(merge_blocks_move_predecessor_nojumps,
merge_blocks_move_successor_nojumps): Return void.
2001-09-11 Jakub Jelinek <jakub@redhat.com>
* configure.in: Check whether assembler supports section merging.
......
......@@ -140,12 +140,11 @@ typedef struct edge_def {
} *edge;
#define EDGE_FALLTHRU 1
#define EDGE_CRITICAL 2
#define EDGE_ABNORMAL 4
#define EDGE_ABNORMAL_CALL 8
#define EDGE_EH 16
#define EDGE_FAKE 32
#define EDGE_DFS_BACK 64
#define EDGE_ABNORMAL 2
#define EDGE_ABNORMAL_CALL 4
#define EDGE_EH 8
#define EDGE_FAKE 16
#define EDGE_DFS_BACK 32
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
......@@ -315,7 +314,8 @@ extern void remove_edge PARAMS ((edge));
extern void redirect_edge_succ PARAMS ((edge, basic_block));
extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block));
extern void redirect_edge_pred PARAMS ((edge, basic_block));
extern void create_basic_block PARAMS ((int, rtx, rtx, rtx));
extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
extern basic_block create_basic_block PARAMS ((int, rtx, rtx));
extern int flow_delete_block PARAMS ((basic_block));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
......@@ -536,6 +536,10 @@ struct edge_list
+ REG_BR_PROB_BASE / 2) \
/ REG_BR_PROB_BASE)
/* Return nonzero if edge is critical. */
#define EDGE_CRITICAL_P(e) ((e)->src->succ->succ_next \
&& (e)->dest->pred->pred_next)
struct edge_list * create_edge_list PARAMS ((void));
void free_edge_list PARAMS ((struct edge_list *));
void print_edge_list PARAMS ((FILE *, struct edge_list *));
......@@ -629,6 +633,7 @@ extern void allocate_bb_life_data PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void));
extern void delete_noop_moves PARAMS ((rtx));
extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
extern basic_block force_nonfallthru PARAMS ((edge));
extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
extern rtx block_label PARAMS ((basic_block));
extern bool forwarder_block_p PARAMS ((basic_block));
......
......@@ -610,7 +610,7 @@ fixup_reorder_chain ()
for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
{
edge e_fall, e_taken, e;
rtx jump_insn, barrier_insn, bb_end_insn;
rtx bb_end_insn;
basic_block nb;
if (bb->succ == NULL)
......@@ -698,54 +698,24 @@ fixup_reorder_chain ()
/* An fallthru to exit block. */
if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR)
continue;
/* We need a new jump insn. If the block has only one outgoing
edge, then we can stuff the new jump insn in directly. */
if (bb->succ->succ_next == NULL)
{
e_fall->flags &= ~EDGE_FALLTHRU;
jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
bb->end = jump_insn;
barrier_insn = emit_barrier_after (jump_insn);
RBI (bb)->eff_end = barrier_insn;
continue;
}
}
/* We got here if we need to add a new jump insn in a new block
across the edge e_fall. */
jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
barrier_insn = emit_barrier_after (jump_insn);
/* We got here if we need to add a new jump insn. */
VARRAY_GROW (basic_block_info, ++n_basic_blocks);
create_basic_block (n_basic_blocks - 1, jump_insn, jump_insn, NULL);
nb = force_nonfallthru (e_fall);
nb = BASIC_BLOCK (n_basic_blocks - 1);
nb->local_set = 0;
nb->count = e_fall->count;
nb->frequency = EDGE_FREQUENCY (e_fall);
nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
nb->aux = xmalloc (sizeof (struct reorder_block_def));
RBI (nb)->eff_head = nb->head;
RBI (nb)->eff_end = barrier_insn;
RBI (nb)->scope = RBI (bb)->scope;
RBI (nb)->visited = 1;
RBI (nb)->next = RBI (bb)->next;
RBI (bb)->next = nb;
/* Link to new block. */
make_single_succ_edge (nb, e_fall->dest, 0);
redirect_edge_succ (e_fall, nb);
/* Don't process this new block. */
bb = nb;
if (nb)
{
nb->aux = xmalloc (sizeof (struct reorder_block_def));
RBI (nb)->eff_head = nb->head;
RBI (nb)->eff_end = NEXT_INSN (nb->end);
RBI (nb)->scope = RBI (bb)->scope;
RBI (nb)->visited = 1;
RBI (nb)->next = RBI (bb)->next;
RBI (bb)->next = nb;
/* Don't process this new block. */
bb = nb;
}
}
/* Put basic_block_info in the new order. */
......
......@@ -89,50 +89,6 @@ can_fallthru (src, target)
return next_active_insn (insn) == insn2;
}
/* Identify critical edges and set the bits appropriately. */
void
mark_critical_edges ()
{
int i, n = n_basic_blocks;
basic_block bb;
/* We begin with the entry block. This is not terribly important now,
but could be if a front end (Fortran) implemented alternate entry
points. */
bb = ENTRY_BLOCK_PTR;
i = -1;
while (1)
{
edge e;
/* (1) Critical edges must have a source with multiple successors. */
if (bb->succ && bb->succ->succ_next)
{
for (e = bb->succ; e; e = e->succ_next)
{
/* (2) Critical edges must have a destination with multiple
predecessors. Note that we know there is at least one
predecessor -- the edge we followed to get here. */
if (e->dest->pred->pred_next)
e->flags |= EDGE_CRITICAL;
else
e->flags &= ~EDGE_CRITICAL;
}
}
else
{
for (e = bb->succ; e; e = e->succ_next)
e->flags &= ~EDGE_CRITICAL;
}
if (++i >= n)
break;
bb = BASIC_BLOCK (i);
}
}
/* Mark the back edges in DFS traversal.
Return non-zero if a loop (natural or otherwise) is present.
Inspired by Depth_First_Search_PP described in:
......
......@@ -452,7 +452,7 @@ find_basic_blocks_1 (f)
to a barrier or some such, no need to do it again. */
if (head != NULL_RTX)
{
create_basic_block (i++, head, end, bb_note);
create_basic_block_structure (i++, head, end, bb_note);
bb_note = NULL_RTX;
}
......@@ -523,7 +523,7 @@ find_basic_blocks_1 (f)
end = insn;
new_bb_exclusive:
create_basic_block (i++, head, end, bb_note);
create_basic_block_structure (i++, head, end, bb_note);
head = end = NULL_RTX;
bb_note = NULL_RTX;
break;
......@@ -579,7 +579,7 @@ find_basic_blocks_1 (f)
}
if (head != NULL_RTX)
create_basic_block (i++, head, end, bb_note);
create_basic_block_structure (i++, head, end, bb_note);
else if (bb_note)
flow_delete_insn (bb_note);
......@@ -604,6 +604,10 @@ find_basic_blocks (f, nregs, file)
int max_uid;
timevar_push (TV_CFG);
if (basic_block_for_insn)
VARRAY_FREE (basic_block_for_insn);
basic_block_for_insn = 0;
/* Flush out existing data. */
if (basic_block_info != NULL)
{
......@@ -655,8 +659,6 @@ find_basic_blocks (f, nregs, file)
here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns. */
tidy_fallthru_edges ();
mark_critical_edges ();
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
......
......@@ -52,12 +52,12 @@ static int flow_find_cross_jump PARAMS ((int, basic_block, basic_block,
rtx *, rtx *));
static bool delete_unreachable_blocks PARAMS ((void));
static int tail_recursion_label_p PARAMS ((rtx));
static int merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
static bool tail_recursion_label_p PARAMS ((rtx));
static void merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
basic_block));
static int merge_blocks_move_successor_nojumps PARAMS ((basic_block,
static void merge_blocks_move_successor_nojumps PARAMS ((basic_block,
basic_block));
static int merge_blocks PARAMS ((edge,basic_block,basic_block,
static bool merge_blocks PARAMS ((edge,basic_block,basic_block,
int));
static bool try_optimize_cfg PARAMS ((int));
static bool try_simplify_condjump PARAMS ((basic_block));
......@@ -248,7 +248,9 @@ try_forward_edges (mode, b)
return changed;
}
static int
/* Return true if LABEL is used for tail recursion. */
static bool
tail_recursion_label_p (label)
rtx label;
{
......@@ -256,16 +258,16 @@ tail_recursion_label_p (label)
for (x = tail_recursion_label_list; x; x = XEXP (x, 1))
if (label == XEXP (x, 0))
return 1;
return true;
return 0;
return false;
}
/* Blocks A and B are to be merged into a single block. A has no incoming
fallthru edge, so it can be moved before B without adding or modifying
any jumps (aside from the jump from A to B). */
static int
static void
merge_blocks_move_predecessor_nojumps (a, b)
basic_block a, b;
{
......@@ -307,15 +309,13 @@ merge_blocks_move_predecessor_nojumps (a, b)
/* Now blocks A and B are contiguous. Merge them. */
merge_blocks_nomove (a, b);
return 1;
}
/* Blocks A and B are to be merged into a single block. B has no outgoing
fallthru edge, so it can be moved after A without adding or modifying
any jumps (aside from the jump from A to B). */
static int
static void
merge_blocks_move_successor_nojumps (a, b)
basic_block a, b;
{
......@@ -359,14 +359,12 @@ merge_blocks_move_successor_nojumps (a, b)
fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
b->index, a->index);
}
return 1;
}
/* Attempt to merge basic blocks that are potentially non-adjacent.
Return true iff the attempt succeeded. */
static int
static bool
merge_blocks (e, b, c, mode)
edge e;
basic_block b, c;
......@@ -376,9 +374,10 @@ merge_blocks (e, b, c, mode)
edge recorded from the call_placeholder back to this label, as
that would make optimize_sibling_and_tail_recursive_calls more
complex for no gain. */
if (GET_CODE (c->head) == CODE_LABEL
if ((mode & CLEANUP_PRE_SIBCALL)
&& GET_CODE (c->head) == CODE_LABEL
&& tail_recursion_label_p (c->head))
return 0;
return false;
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
......@@ -391,22 +390,22 @@ merge_blocks (e, b, c, mode)
b->index, c->index);
}
return 1;
return true;
}
/* Otherwise we will need to move code around. Do that only if expensive
transformations are allowed. */
else if (mode & CLEANUP_EXPENSIVE)
{
edge tmp_edge, c_fallthru_edge;
int c_has_outgoing_fallthru;
int b_has_incoming_fallthru;
edge tmp_edge, b_fallthru_edge;
bool c_has_outgoing_fallthru;
bool b_has_incoming_fallthru;
/* Avoid overactive code motion, as the forwarder blocks should be
eliminated by edge redirection instead. One exception might have
been if B is a forwarder block and C has no fallthru edge, but
that should be cleaned up by bb-reorder instead. */
if (forwarder_block_p (b) || forwarder_block_p (c))
return 0;
return false;
/* We must make sure to not munge nesting of lexical blocks,
and loop notes. This is done by squeezing out all the notes
......@@ -416,59 +415,37 @@ merge_blocks (e, b, c, mode)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
c_has_outgoing_fallthru = (tmp_edge != NULL);
c_fallthru_edge = tmp_edge;
for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
b_has_incoming_fallthru = (tmp_edge != NULL);
b_fallthru_edge = tmp_edge;
/* Otherwise, we're going to try to move C after B. If C does
not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
{
merge_blocks_move_successor_nojumps (b, c);
return true;
}
/* If B does not have an incoming fallthru, then it can be moved
immediately before C without introducing or modifying jumps.
C cannot be the first block, so we do not have to worry about
accessing a non-existent block. */
if (! b_has_incoming_fallthru)
return merge_blocks_move_predecessor_nojumps (b, c);
/* Otherwise, we're going to try to move C after B. If C does
not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
return merge_blocks_move_successor_nojumps (b, c);
/* Otherwise, we'll need to insert an extra jump, and possibly
a new block to contain it. We can't redirect to EXIT_BLOCK_PTR,
as we don't have explicit return instructions before epilogues
are generated, so give up on that case. */
if (c_fallthru_edge->dest != EXIT_BLOCK_PTR
&& merge_blocks_move_successor_nojumps (b, c))
{
basic_block target = c_fallthru_edge->dest;
rtx barrier;
basic_block new;
/* This is a dirty hack to avoid code duplication.
Set edge to point to wrong basic block, so
redirect_edge_and_branch_force will do the trick
and rewire edge back to the original location. */
redirect_edge_succ (c_fallthru_edge, ENTRY_BLOCK_PTR);
new = redirect_edge_and_branch_force (c_fallthru_edge, target);
/* We've just created barrier, but another barrier is
already present in the stream. Avoid the duplicate. */
barrier = next_nonnote_insn (new ? new->end : b->end);
if (GET_CODE (barrier) != BARRIER)
abort ();
flow_delete_insn (barrier);
return 1;
}
return 0;
if (b_has_incoming_fallthru)
{
if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
return false;
force_nonfallthru (b_fallthru_edge);
}
merge_blocks_move_predecessor_nojumps (b, c);
return true;
}
return 0;
return false;
}
/* Look through the insns at the end of BB1 and BB2 and find the longest
......@@ -1191,6 +1168,7 @@ try_optimize_cfg (mode)
}
/* Delete all unreachable basic blocks. */
static bool
delete_unreachable_blocks ()
{
......@@ -1215,7 +1193,6 @@ delete_unreachable_blocks ()
tidy_fallthru_edges ();
return changed;
}
/* Tidy the CFG by deleting unreachable code and whatnot. */
......@@ -1231,9 +1208,6 @@ cleanup_cfg (mode)
if (try_optimize_cfg (mode))
delete_unreachable_blocks (), changed = true;
if (changed)
mark_critical_edges ();
/* Kill the data we won't maintain. */
free_EXPR_LIST_list (&label_value_list);
free_EXPR_LIST_list (&tail_recursion_label_list);
......
......@@ -152,7 +152,7 @@ instrument_edges (el)
if (rtl_dump_file)
fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
e->src->index, e->dest->index,
e->flags & EDGE_CRITICAL ? " (and split)" : "");
EDGE_CRITICAL_P (e) ? " (and split)" : "");
need_func_profiler = 1;
insert_insn_on_edge (
gen_edge_profiler (total_num_edges_instrumented
......@@ -884,7 +884,7 @@ find_spanning_tree (el)
for (i = 0; i < num_edges; i++)
{
edge e = INDEX_EDGE (el, i);
if ((e->flags & EDGE_CRITICAL)
if ((EDGE_CRITICAL_P (e))
&& !EDGE_INFO (e)->ignore
&& (find_group (e->src) != find_group (e->dest)))
{
......
......@@ -2660,9 +2660,10 @@ convert_regs_1 (file, block)
beste = e;
else if (beste->count > e->count)
;
else if ((e->flags & EDGE_CRITICAL) != (beste->flags & EDGE_CRITICAL))
else if ((EDGE_CRITICAL_P (e) != 0)
!= (EDGE_CRITICAL_P (beste) != 0))
{
if (e->flags & EDGE_CRITICAL)
if (EDGE_CRITICAL_P (e))
beste = e;
}
else if (e->src->index < beste->src->index)
......
......@@ -1498,8 +1498,7 @@ make_regs_equivalent_over_bad_edges (bb, reg_partition)
/* Scan incoming abnormal critical edges. */
for (e = b->pred; e; e = e->pred_next)
if ((e->flags & (EDGE_ABNORMAL | EDGE_CRITICAL))
== (EDGE_ABNORMAL | EDGE_CRITICAL))
if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
{
rtx *alt = phi_alternative (set, e->src->index);
int alt_regno;
......
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