aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/cfgcleanup.c43
2 files changed, 46 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 73f05ef..9c3dcda 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2001-12-09 Richard Henderson <rth@redhat.com>
+
+ * cfgcleanup.c (label_is_jump_target_p): New function.
+ (try_optimize_cfg): Use label_is_jump_target_p to check if label is
+ target of a JUMP_INSN from the preceding block.
+
Sun Dec 9 18:40:07 2001 Douglas B. Rupp <rupp@gnat.com>
* vmsdbgout.c (lookup_filename): Assign null string instead
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 28f3a1f..526202a 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -69,6 +69,7 @@ static int flow_find_cross_jump PARAMS ((int, basic_block, basic_block,
rtx *, rtx *));
static bool delete_unreachable_blocks PARAMS ((void));
+static bool label_is_jump_target_p PARAMS ((rtx, rtx));
static bool tail_recursion_label_p PARAMS ((rtx));
static void merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
basic_block));
@@ -291,6 +292,38 @@ try_forward_edges (mode, b)
return changed;
}
+/* Return true if LABEL is a target of JUMP_INSN. This applies only
+ to non-complex jumps. That is, direct unconditional, conditional,
+ and tablejumps, but not computed jumps or returns. It also does
+ not apply to the fallthru case of a conditional jump. */
+
+static bool
+label_is_jump_target_p (label, jump_insn)
+ rtx label, jump_insn;
+{
+ rtx tmp = JUMP_LABEL (jump_insn);
+
+ if (label == tmp)
+ return true;
+
+ if (tmp != NULL_RTX
+ && (tmp = NEXT_INSN (tmp)) != NULL_RTX
+ && GET_CODE (tmp) == JUMP_INSN
+ && (tmp = PATTERN (tmp),
+ GET_CODE (tmp) == ADDR_VEC
+ || GET_CODE (tmp) == ADDR_DIFF_VEC))
+ {
+ rtvec vec = XVEC (tmp, GET_CODE (tmp) == ADDR_DIFF_VEC);
+ int i, veclen = GET_NUM_ELEM (vec);
+
+ for (i = 0; i < veclen; ++i)
+ if (XEXP (RTVEC_ELT (vec, i), 0) == label)
+ return true;
+ }
+
+ return false;
+}
+
/* Return true if LABEL is used for tail recursion. */
static bool
@@ -1162,10 +1195,14 @@ try_optimize_cfg (mode)
&& GET_CODE (b->head) == CODE_LABEL
&& (!(mode & CLEANUP_PRE_SIBCALL)
|| !tail_recursion_label_p (b->head))
- /* If previous block ends with condjump jumping to next BB,
- we can't delete the label. */
+ /* If the previous block ends with a branch to this block,
+ we can't delete the label. Normally this is a condjump
+ that is yet to be simplified, but if CASE_DROPS_THRU,
+ this can be a tablejump with some element going to the
+ same place as the default (fallthru). */
&& (b->pred->src == ENTRY_BLOCK_PTR
- || !reg_mentioned_p (b->head, b->pred->src->end)))
+ || GET_CODE (b->pred->src->end) != JUMP_INSN
+ || ! label_is_jump_target_p (b->head, b->pred->src->end)))
{
rtx label = b->head;
b->head = NEXT_INSN (b->head);