Commit b62c8881 by Jeffrey A Law Committed by Jeff Law

basic-block.h (first_insn_after_basic_block_note): Declare.

        * basic-block.h (first_insn_after_basic_block_note): Declare.
        * flow.c (first_insn_after_basic_block_note): Define.  Moved
        from...
        * ssa.c (first_insn_after_basic_block_note): Remove.
        * ssa-dce.c (find_inherently_necessary): Consider BARRIERs
        necessary.
        (ssa_eliminate_dead_code): Properly update the CFG and PHI
        nodes when we find a dead conditional branch.  Insert BARRIERs
        after any blocks with no successors, but which do not have
        any BARRIERs.

From-SVN: r43816
parent 9d99ca5b
Fri Jul 6 11:47:59 2001 Jeffrey A Law (law@cygnus.com)
* basic-block.h (first_insn_after_basic_block_note): Declare.
* flow.c (first_insn_after_basic_block_note): Define. Moved
from...
* ssa.c (first_insn_after_basic_block_note): Remove.
* ssa-dce.c (find_inherently_necessary): Consider BARRIERs
necessary.
(ssa_eliminate_dead_code): Properly update the CFG and PHI
nodes when we find a dead conditional branch. Insert BARRIERs
after any blocks with no successors, but which do not have
any BARRIERs.
2001-07-06 Zack Weinberg <zackw@stanford.edu> 2001-07-06 Zack Weinberg <zackw@stanford.edu>
* varray.c (varray_check_failed): Use internal_error. * varray.c (varray_check_failed): Use internal_error.
......
...@@ -294,7 +294,7 @@ extern int flow_depth_first_order_compute PARAMS ((int *, int *)); ...@@ -294,7 +294,7 @@ extern int flow_depth_first_order_compute PARAMS ((int *, int *));
extern void dump_edge_info PARAMS ((FILE *, edge, int)); extern void dump_edge_info PARAMS ((FILE *, edge, int));
extern void clear_edges PARAMS ((void)); extern void clear_edges PARAMS ((void));
extern void mark_critical_edges PARAMS ((void)); extern void mark_critical_edges PARAMS ((void));
extern rtx first_insn_after_basic_block_note PARAMS ((basic_block));
/* Structure to hold information for each natural loop. */ /* Structure to hold information for each natural loop. */
struct loop struct loop
......
...@@ -1088,6 +1088,28 @@ create_basic_block (index, head, end, bb_note) ...@@ -1088,6 +1088,28 @@ create_basic_block (index, head, end, bb_note)
bb->aux = bb; bb->aux = bb;
} }
/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
note associated with the BLOCK. */
rtx
first_insn_after_basic_block_note (block)
basic_block block;
{
rtx insn;
/* Get the first instruction in the block. */
insn = block->head;
if (insn == NULL_RTX)
return NULL_RTX;
if (GET_CODE (insn) == CODE_LABEL)
insn = NEXT_INSN (insn);
if (!NOTE_INSN_BASIC_BLOCK_P (insn))
abort ();
return NEXT_INSN (insn);
}
/* Records the basic block struct in BB_FOR_INSN, for every instruction /* Records the basic block struct in BB_FOR_INSN, for every instruction
indexed by INSN_UID. MAX is the size of the array. */ indexed by INSN_UID. MAX is the size of the array. */
......
...@@ -372,15 +372,13 @@ find_inherently_necessary (x) ...@@ -372,15 +372,13 @@ find_inherently_necessary (x)
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case CALL_INSN: case CALL_INSN:
case BARRIER:
return !0; return !0;
case CODE_LABEL: case CODE_LABEL:
case NOTE: case NOTE:
case BARRIER:
return 0; return 0;
break;
case JUMP_INSN: case JUMP_INSN:
return JUMP_TABLE_DATA_P (x) || computed_jump_p (x) != 0; return JUMP_TABLE_DATA_P (x) || computed_jump_p (x) != 0;
break;
case INSN: case INSN:
{ {
int inherently_necessary_set = 0; int inherently_necessary_set = 0;
...@@ -626,42 +624,103 @@ ssa_eliminate_dead_code () ...@@ -626,42 +624,103 @@ ssa_eliminate_dead_code ()
{ {
if (any_condjump_p (insn)) if (any_condjump_p (insn))
{ {
/* Convert unnecessary conditional insn to an unconditional basic_block bb = BLOCK_FOR_INSN (insn);
jump to immediate postdominator block. */ basic_block pdom_bb = find_pdom (pdom, bb);
rtx old_label = JUMP_LABEL (insn); rtx lbl;
int pdom_block_number = edge e;
find_pdom (pdom, BLOCK_FOR_INSN (insn))->index;
/* Egad. The immediate post dominator is the exit block. We
/* Prevent the conditional jump's label from being deleted so would like to optimize this conditional jump to jump directly
we do not have to modify the basic block structure. */ to the exit block. That can be difficult as we may not have
++LABEL_NUSES (old_label); a suitable CODE_LABEL that allows us to fall unmolested into
the exit block.
if (pdom_block_number != EXIT_BLOCK
&& pdom_block_number != INVALID_BLOCK) So, we just delete the conditional branch by turning it into
a deleted note. That is safe, but just not as optimal as
it could be. */
if (pdom_bb == EXIT_BLOCK_PTR)
{
/* Since we're going to just delete the branch, we need
look at all the edges and remove all those which are not
a fallthru edge. */
e = bb->succ;
while (e)
{ {
rtx lbl = find_block_label (BASIC_BLOCK (pdom_block_number)); edge temp = e;
rtx new_jump = emit_jump_insn_before (gen_jump (lbl), insn);
/* Let jump know that label is in use. */ e = e->succ_next;
JUMP_LABEL (new_jump) = lbl; if ((temp->flags & EDGE_FALLTHRU) == 0)
++LABEL_NUSES (lbl); {
/* We've found a non-fallthru edge, find any PHI nodes
at the target and clean them up. */
if (temp->dest != EXIT_BLOCK_PTR)
{
rtx insn
= first_insn_after_basic_block_note (temp->dest);
delete_insn_bb (insn); while (PHI_NODE_P (insn))
{
remove_phi_alternative (PATTERN (insn), temp->src);
insn = NEXT_INSN (insn);
}
}
remove_edge (temp);
}
}
/* Now "delete" the conditional jump. */
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
continue;
}
/* We've found a conditional branch that is unnecessary.
First, remove all outgoing edges from this block, updating
PHI nodes as appropriate. */
e = bb->succ;
while (e)
{
edge temp = e;
/* A conditional branch is unnecessary if and only if any e = e->succ_next;
block control-dependent on it is unnecessary. Thus,
any phi nodes in these unnecessary blocks are also if (temp->flags & EDGE_ABNORMAL)
removed and these nodes need not be updated. */ continue;
/* We found an edge that is not executable. First simplify
the PHI nodes in the target block. */
if (temp->dest != EXIT_BLOCK_PTR)
{
rtx insn = first_insn_after_basic_block_note (temp->dest);
while (PHI_NODE_P (insn))
{
remove_phi_alternative (PATTERN (insn), temp->src);
insn = NEXT_INSN (insn);
}
}
remove_edge (temp);
}
/* Create an edge from this block to the post dominator.
What about the PHI nodes at the target? */
make_edge (NULL, bb, pdom_bb, 0);
/* Third, transform this insn into an unconditional
jump to the label for the immediate postdominator. */
lbl = find_block_label (pdom_bb);
SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (VOIDmode, lbl);
INSN_CODE (insn) = -1;
JUMP_LABEL (insn) = lbl;
LABEL_NUSES (lbl)++;
/* A barrier must follow any unconditional jump. Barriers /* A barrier must follow any unconditional jump. Barriers
are not in basic blocks so this must occur after are not in basic blocks so this must occur after
deleting the conditional jump. */ deleting the conditional jump. */
emit_barrier_after (new_jump); emit_barrier_after (insn);
}
else
/* The block drops off the end of the function and the
ending conditional jump is not needed. */
delete_insn_bb (insn);
} }
else if (!JUMP_P (insn)) else if (!JUMP_P (insn))
delete_insn_bb (insn); delete_insn_bb (insn);
...@@ -670,6 +729,21 @@ ssa_eliminate_dead_code () ...@@ -670,6 +729,21 @@ ssa_eliminate_dead_code ()
/* Remove fake edges from the CFG. */ /* Remove fake edges from the CFG. */
remove_fake_edges (); remove_fake_edges ();
/* Find any blocks with no successors and ensure they are followed
by a BARRIER. delete_insn has the nasty habit of deleting barriers
when deleting insns. */
for (i = 0; i < n_basic_blocks; i++)
{
basic_block bb = BASIC_BLOCK (i);
if (bb->succ == NULL)
{
rtx next = NEXT_INSN (bb->end);
if (!next || GET_CODE (next) != BARRIER)
emit_barrier_after (bb->end);
}
}
/* Release allocated memory. */ /* Release allocated memory. */
for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
RESURRECT_INSN (insn); RESURRECT_INSN (insn);
......
...@@ -162,8 +162,6 @@ struct rename_context; ...@@ -162,8 +162,6 @@ struct rename_context;
static inline rtx * phi_alternative static inline rtx * phi_alternative
PARAMS ((rtx, int)); PARAMS ((rtx, int));
static rtx first_insn_after_basic_block_note
PARAMS ((basic_block));
static void compute_dominance_frontiers_1 static void compute_dominance_frontiers_1
PARAMS ((sbitmap *frontiers, int *idom, int bb, sbitmap done)); PARAMS ((sbitmap *frontiers, int *idom, int bb, sbitmap done));
static void find_evaluations_1 static void find_evaluations_1
...@@ -633,28 +631,6 @@ compute_iterated_dominance_frontiers (idfs, frontiers, evals, nregs) ...@@ -633,28 +631,6 @@ compute_iterated_dominance_frontiers (idfs, frontiers, evals, nregs)
} }
} }
/* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
note associated with the BLOCK. */
static rtx
first_insn_after_basic_block_note (block)
basic_block block;
{
rtx insn;
/* Get the first instruction in the block. */
insn = block->head;
if (insn == NULL_RTX)
return NULL_RTX;
if (GET_CODE (insn) == CODE_LABEL)
insn = NEXT_INSN (insn);
if (!NOTE_INSN_BASIC_BLOCK_P (insn))
abort ();
return NEXT_INSN (insn);
}
/* Insert the phi nodes. */ /* Insert the phi nodes. */
static void static void
......
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