aboutsummaryrefslogtreecommitdiff
path: root/gcc/flow.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-05-12 09:26:15 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-05-12 09:26:15 -0700
commitbe1bb652637d5d8785993a4cd197d989dc4b5260 (patch)
treed0c01aedfa0c100dbc8cf6e908311acdea960127 /gcc/flow.c
parentfb0f12c9326308579f89b0961681ffdb85288228 (diff)
downloadgcc-be1bb652637d5d8785993a4cd197d989dc4b5260.zip
gcc-be1bb652637d5d8785993a4cd197d989dc4b5260.tar.gz
gcc-be1bb652637d5d8785993a4cd197d989dc4b5260.tar.bz2
Makefile.in (final.o): Depend on BASIC_BLOCK_H.
* Makefile.in (final.o): Depend on BASIC_BLOCK_H. * final.c (final_end_function): Use app_disable. Rearrange note handling into a switch. Emit deleted labels. (output_asm_label): Generate label strings for deleted labels. * flow.c (tail_recursion_label_list): New. (find_basic_blocks_1): Set label_value_list directly. Collect list of tail recursion labels from call_placeholders. Don't add deleted labels to the label value list. (cleanup_cfg): Use free_EXPR_LIST_list. (flow_delete_insn_chain): Turn non-removable labels into notes. (flow_delete_block): Don't disable deleting the block because of a non-removable label. (tail_recursion_label_p): New. (merge_blocks_move_predecessor_nojumps): Don't disable the merge because of a label. (merge_blocks_move_successor_nojumps): Likewise. Also move a jump table. (merge_blocks): Disable a merge because of tail recursion labels. * ifcvt.c (merge_if_block): Don't disable a merge because of a label. Use a more accurate measure of not merging the join block. (find_if_block): Don't disable conversion because of a label. (find_if_case_1, find_if_case_2): Likewise. * jump.c (duplicate_loop_exit_test): Preserve the kind of list element when copying. (squeeze_notes): Also leave EH notes. (mark_jump_label): Ignore deleted labels. Use an INSN_LIST for REG_LABEL notes. (delete_insn): Preserve LABEL_NAME in NOTE_SOURCE_FILE when deleting a label. * print-rtl.c (print_rtx): Print NOTE_SOURCE_FILE for NOTE_INSN_DELETED_LABEL. Print `[# deleted]' for a label_ref referring to a deleted label. Convert tail handling to a switch. * rtl.def (CODE_LABEL): Rearrange elements to be compatible with NOTE for NOTE_INSN_DELETED_LABEL. (NOTE): Fix commentary. * rtl.h (REG_LABEL): Update commentary wrt INSN_LIST. (REG_CC_SETTER, REG_CC_USER, REG_LIBCALL): Likewise. (CODE_LABEL_NUMBER, LABEL_NAME): Update index. (LABEL_NUSES, LABEL_REFS): Likewise. * unroll.c (copy_loop_body): Don't copy NOTE_INSN_DELETED_LABEL. From-SVN: r33876
Diffstat (limited to 'gcc/flow.c')
-rw-r--r--gcc/flow.c127
1 files changed, 68 insertions, 59 deletions
diff --git a/gcc/flow.c b/gcc/flow.c
index 1bea9c2..a8573e1 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -253,6 +253,7 @@ varray_type basic_block_for_insn;
bit of surgery to be able to use or co-opt the routines in jump. */
static rtx label_value_list;
+static rtx tail_recursion_label_list;
/* Holds information for tracking conditional register life information. */
struct reg_cond_life_info
@@ -307,7 +308,7 @@ struct propagate_block_info
/* Forward declarations */
static int count_basic_blocks PARAMS ((rtx));
-static rtx find_basic_blocks_1 PARAMS ((rtx));
+static void find_basic_blocks_1 PARAMS ((rtx));
static void clear_edges PARAMS ((void));
static void make_edges PARAMS ((rtx));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
@@ -325,6 +326,7 @@ static void delete_eh_regions PARAMS ((void));
static int can_delete_note_p PARAMS ((rtx));
static void expunge_block PARAMS ((basic_block));
static int can_delete_label_p PARAMS ((rtx));
+static int tail_recursion_label_p PARAMS ((rtx));
static int merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
basic_block));
static int merge_blocks_move_successor_nojumps PARAMS ((basic_block,
@@ -437,7 +439,7 @@ find_basic_blocks (f, nregs, file)
VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
- label_value_list = find_basic_blocks_1 (f);
+ find_basic_blocks_1 (f);
/* Record the block to which an insn belongs. */
/* ??? This should be done another way, by which (perhaps) a label is
@@ -535,7 +537,7 @@ count_basic_blocks (f)
Collect and return a list of labels whose addresses are taken. This
will be used in make_edges for use with computed gotos. */
-static rtx
+static void
find_basic_blocks_1 (f)
rtx f;
{
@@ -543,7 +545,8 @@ find_basic_blocks_1 (f)
int i = 0;
rtx bb_note = NULL_RTX;
rtx eh_list = NULL_RTX;
- rtx label_value_list = NULL_RTX;
+ rtx lvl = NULL_RTX;
+ rtx trll = NULL_RTX;
rtx head = NULL_RTX;
rtx end = NULL_RTX;
@@ -667,6 +670,12 @@ find_basic_blocks_1 (f)
int region = (note ? INTVAL (XEXP (note, 0)) : 1);
int call_has_abnormal_edge = 0;
+ /* If this is a call placeholder, record its tail recursion
+ label, if any. */
+ if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER
+ && XEXP (PATTERN (insn), 3) != NULL_RTX)
+ trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
+
/* If there is an EH region or rethrow, we have an edge. */
if ((eh_list && region > 0)
|| find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
@@ -724,15 +733,16 @@ find_basic_blocks_1 (f)
rtx lab = XEXP (note, 0), next;
if (lab == eh_return_stub_label)
- ;
+ ;
else if ((next = next_nonnote_insn (lab)) != NULL
&& GET_CODE (next) == JUMP_INSN
&& (GET_CODE (PATTERN (next)) == ADDR_VEC
|| GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
;
+ else if (GET_CODE (lab) == NOTE)
+ ;
else
- label_value_list
- = alloc_EXPR_LIST (0, XEXP (note, 0), label_value_list);
+ lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
}
}
}
@@ -745,7 +755,8 @@ find_basic_blocks_1 (f)
if (i != n_basic_blocks)
abort ();
- return label_value_list;
+ label_value_list = lvl;
+ tail_recursion_label_list = trll;
}
/* Tidy the CFG by deleting unreachable code and whatnot. */
@@ -761,7 +772,8 @@ cleanup_cfg (f)
mark_critical_edges ();
/* Kill the data we won't maintain. */
- label_value_list = NULL_RTX;
+ free_EXPR_LIST_list (&label_value_list);
+ free_EXPR_LIST_list (&tail_recursion_label_list);
}
/* Create a new basic block consisting of the instructions between
@@ -1853,8 +1865,14 @@ flow_delete_insn_chain (start, finish)
next = NEXT_INSN (start);
if (GET_CODE (start) == NOTE && !can_delete_note_p (start))
;
- else if (GET_CODE (start) == CODE_LABEL && !can_delete_label_p (start))
- ;
+ else if (GET_CODE (start) == CODE_LABEL
+ && ! can_delete_label_p (start))
+ {
+ const char *name = LABEL_NAME (start);
+ PUT_CODE (start, NOTE);
+ NOTE_LINE_NUMBER (start) = NOTE_INSN_DELETED_LABEL;
+ NOTE_SOURCE_FILE (start) = name;
+ }
else
next = flow_delete_insn (start);
@@ -1910,20 +1928,6 @@ flow_delete_block (b)
}
prev = &XEXP (x, 1);
}
-
- /* This label may be referenced by code solely for its value, or
- referenced by static data, or something. We have determined
- that it is not reachable, but cannot delete the label itself.
- Save code space and continue to delete the balance of the block,
- along with properly updating the cfg. */
- if (!can_delete_label_p (insn))
- {
- /* If we've only got one of these, skip the whole deleting
- insns thing. */
- if (insn == b->end)
- goto no_delete_insns;
- insn = NEXT_INSN (insn);
- }
}
/* Include any jump table following the basic block. */
@@ -1944,8 +1948,6 @@ flow_delete_block (b)
/* Selectively delete the entire chain. */
flow_delete_insn_chain (insn, end);
- no_delete_insns:
-
/* Remove the edges into and out of this block. Note that there may
indeed be edges in, if we are removing an unreachable loop. */
{
@@ -2063,6 +2065,19 @@ can_delete_label_p (label)
return 1;
}
+static int
+tail_recursion_label_p (label)
+ rtx label;
+{
+ rtx x;
+
+ for (x = tail_recursion_label_list; x ; x = XEXP (x, 1))
+ if (label == XEXP (x, 0))
+ return 1;
+
+ return 0;
+}
+
/* Blocks A and B are to be merged into a single block A. The insns
are already contiguous, hence `nomove'. */
@@ -2180,19 +2195,10 @@ merge_blocks_move_predecessor_nojumps (a, b)
start = a->head;
end = a->end;
- /* We want to delete the BARRIER after the end of the insns we are
- going to move. If we don't find a BARRIER, then do nothing. This
- can happen in some cases if we have labels we can not delete.
-
- Similarly, do nothing if we can not delete the label at the start
- of the target block. */
barrier = next_nonnote_insn (end);
- if (GET_CODE (barrier) != BARRIER
- || (GET_CODE (b->head) == CODE_LABEL
- && ! can_delete_label_p (b->head)))
- return 0;
- else
- flow_delete_insn (barrier);
+ if (GET_CODE (barrier) != BARRIER)
+ abort ();
+ flow_delete_insn (barrier);
/* Move block and loop notes out of the chain so that we do not
disturb their order.
@@ -2240,20 +2246,23 @@ merge_blocks_move_successor_nojumps (a, b)
start = b->head;
end = b->end;
+ barrier = NEXT_INSN (end);
- /* We want to delete the BARRIER after the end of the insns we are
- going to move. If we don't find a BARRIER, then do nothing. This
- can happen in some cases if we have labels we can not delete.
+ /* Recognize a jump table following block B. */
+ if (GET_CODE (barrier) == CODE_LABEL
+ && NEXT_INSN (barrier)
+ && GET_CODE (NEXT_INSN (barrier)) == JUMP_INSN
+ && (GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_VEC
+ || GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_DIFF_VEC))
+ {
+ end = NEXT_INSN (barrier);
+ barrier = NEXT_INSN (end);
+ }
- Similarly, do nothing if we can not delete the label at the start
- of the target block. */
- barrier = next_nonnote_insn (end);
- if (GET_CODE (barrier) != BARRIER
- || (GET_CODE (b->head) == CODE_LABEL
- && ! can_delete_label_p (b->head)))
- return 0;
- else
- flow_delete_insn (barrier);
+ /* There had better have been a barrier there. Delete it. */
+ if (GET_CODE (barrier) != BARRIER)
+ abort ();
+ flow_delete_insn (barrier);
/* Move block and loop notes out of the chain so that we do not
disturb their order.
@@ -2287,17 +2296,17 @@ merge_blocks (e, b, c)
edge e;
basic_block b, c;
{
+ /* If C has a tail recursion label, do not merge. There is no
+ 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
+ && tail_recursion_label_p (c->head))
+ return 0;
+
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
{
- /* If a label still appears somewhere and we cannot delete the label,
- then we cannot merge the blocks. The edge was tidied already. */
-
- rtx insn, stop = NEXT_INSN (c->head);
- for (insn = NEXT_INSN (b->end); insn != stop; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == CODE_LABEL && !can_delete_label_p (insn))
- return 0;
-
merge_blocks_nomove (b, c);
if (rtl_dump_file)