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
This commit is contained in:
Richard Henderson 2000-05-12 09:26:15 -07:00 committed by Richard Henderson
parent fb0f12c932
commit be1bb65263
10 changed files with 403 additions and 325 deletions

View File

@ -1,3 +1,46 @@
2000-05-12 Richard Henderson <rth@cygnus.com>
* 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.
2000-05-12 Zack Weinberg <zack@wolery.cumb.org>
* fixinc/fixfixes.c (IO_use_fix, IO_defn_fix, CTRL_use_fix,

View File

@ -1374,7 +1374,7 @@ final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
$(REGS_H) $(RECOG_H) conditions.h insn-config.h insn-attr.h function.h \
real.h output.h hard-reg-set.h insn-flags.h insn-codes.h gstab.h except.h \
xcoffout.h defaults.h toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h \
dbxout.h
dbxout.h $(BASIC_BLOCK_H)
recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) function.h $(BASIC_BLOCK_H) \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
insn-flags.h insn-codes.h real.h toplev.h output.h resource.h

View File

@ -68,6 +68,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "reload.h"
#include "intl.h"
#include "basic-block.h"
/* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
@ -1782,11 +1783,7 @@ final_end_function (first, file, optimize)
FILE *file;
int optimize ATTRIBUTE_UNUSED;
{
if (app_on)
{
fputs (ASM_APP_OFF, file);
app_on = 0;
}
app_disable ();
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
@ -2082,218 +2079,243 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (prescan > 0)
break;
/* Align the beginning of a loop, for higher speed
on certain machines. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
break; /* This used to depend on optimize, but that was bogus. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
break;
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
&& ! exceptions_via_longjmp)
switch (NOTE_LINE_NUMBER (insn))
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
if (! flag_new_exceptions)
add_eh_table_entry (NOTE_EH_HANDLER (insn));
case NOTE_INSN_DELETED:
case NOTE_INSN_LOOP_BEG:
case NOTE_INSN_LOOP_END:
case NOTE_INSN_LOOP_CONT:
case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_SETJMP:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_RANGE_BEG:
case NOTE_INSN_RANGE_END:
case NOTE_INSN_LIVE:
case NOTE_INSN_EXPECTED_VALUE:
break;
case NOTE_INSN_BASIC_BLOCK:
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s basic block %d\n",
ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
break;
case NOTE_INSN_EH_REGION_BEG:
if (! exceptions_via_longjmp)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
if (! flag_new_exceptions)
add_eh_table_entry (NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_BEG
ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
#endif
}
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
&& ! exceptions_via_longjmp)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
if (flag_new_exceptions)
add_eh_table_entry (NOTE_EH_HANDLER (insn));
case NOTE_INSN_EH_REGION_END:
if (! exceptions_via_longjmp)
{
ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
if (flag_new_exceptions)
add_eh_table_entry (NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_END
ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
#endif
}
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
{
case NOTE_INSN_PROLOGUE_END:
#ifdef FUNCTION_END_PROLOGUE
FUNCTION_END_PROLOGUE (file);
#endif
profile_after_prologue (file);
break;
}
case NOTE_INSN_EPILOGUE_BEG:
#ifdef FUNCTION_BEGIN_EPILOGUE
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
{
FUNCTION_BEGIN_EPILOGUE (file);
break;
}
#endif
break;
if (write_symbols == NO_DEBUG)
break;
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
{
case NOTE_INSN_FUNCTION_BEG:
if (write_symbols == NO_DEBUG)
break;
#if defined(SDB_DEBUGGING_INFO) && defined(MIPS_DEBUGGING_INFO)
/* MIPS stabs require the parameter descriptions to be after the
function entry point rather than before. */
if (write_symbols == SDB_DEBUG)
sdbout_begin_function (last_linenum);
{
app_disable ();
sdbout_begin_function (last_linenum);
}
else
#endif
#ifdef DWARF_DEBUGGING_INFO
/* This outputs a marker where the function body starts, so it
must be after the prologue. */
if (write_symbols == DWARF_DEBUG)
dwarfout_begin_function ();
{
app_disable ();
dwarfout_begin_function ();
}
#endif
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
break; /* An insn that was "deleted" */
if (app_on)
{
fputs (ASM_APP_OFF, file);
app_on = 0;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
&& (debug_info_level == DINFO_LEVEL_NORMAL
case NOTE_INSN_BLOCK_BEG:
if (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
|| write_symbols == DWARF_DEBUG
|| write_symbols == DWARF2_DEBUG))
{
int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
|| write_symbols == DWARF2_DEBUG)
{
int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
++block_depth;
high_block_linenum = last_linenum;
app_disable ();
++block_depth;
high_block_linenum = last_linenum;
/* Output debugging info about the symbol-block beginning. */
/* Output debugging info about the symbol-block beginning. */
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
sdbout_begin_block (file, last_linenum, n);
if (write_symbols == SDB_DEBUG)
sdbout_begin_block (file, last_linenum, n);
#endif
#ifdef XCOFF_DEBUGGING_INFO
if (write_symbols == XCOFF_DEBUG)
xcoffout_begin_block (file, last_linenum, n);
if (write_symbols == XCOFF_DEBUG)
xcoffout_begin_block (file, last_linenum, n);
#endif
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", n);
if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", n);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
dwarfout_begin_block (n);
if (write_symbols == DWARF_DEBUG)
dwarfout_begin_block (n);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_begin_block (n);
if (write_symbols == DWARF2_DEBUG)
dwarf2out_begin_block (n);
#endif
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
&& (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
|| write_symbols == DWARF_DEBUG
|| write_symbols == DWARF2_DEBUG))
{
int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
}
break;
/* End of a symbol-block. */
case NOTE_INSN_BLOCK_END:
if (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
|| write_symbols == DWARF_DEBUG
|| write_symbols == DWARF2_DEBUG)
{
int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
--block_depth;
if (block_depth < 0)
app_disable ();
/* End of a symbol-block. */
--block_depth;
if (block_depth < 0)
abort ();
#ifdef XCOFF_DEBUGGING_INFO
if (write_symbols == XCOFF_DEBUG)
xcoffout_end_block (file, high_block_linenum, n);
#endif
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", n);
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
sdbout_end_block (file, high_block_linenum, n);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
dwarfout_end_block (n);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_end_block (n);
#endif
}
break;
case NOTE_INSN_DELETED_LABEL:
/* Emit the label. We may have deleted the CODE_LABEL because
the label could be proved to be unreachable, though still
referenced (in the form of having its address taken. */
/* ??? Figure out how not to do this unconditionally. This
interferes with bundling on LIW targets. */
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
if (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE)
{
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
dwarfout_label (insn);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_label (insn);
#endif
}
break;
default:
if (NOTE_LINE_NUMBER (insn) <= 0)
abort ();
#ifdef XCOFF_DEBUGGING_INFO
if (write_symbols == XCOFF_DEBUG)
xcoffout_end_block (file, high_block_linenum, n);
#endif
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", n);
#endif
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG)
sdbout_end_block (file, high_block_linenum, n);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
dwarfout_end_block (n);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_end_block (n);
#endif
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL
&& (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE))
{
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
dwarfout_label (insn);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_label (insn);
#endif
}
else if (NOTE_LINE_NUMBER (insn) > 0)
/* This note is a line-number. */
{
register rtx note;
/* This note is a line-number. */
{
register rtx note;
int note_after = 0;
#if 0 /* This is what we used to do. */
output_source_line (file, insn);
#endif
int note_after = 0;
/* If there is anything real after this note,
output it. If another line note follows, omit this one. */
for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))
{
if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)
break;
/* These types of notes can be significant
so make sure the preceding line number stays. */
else if (GET_CODE (note) == NOTE
&& (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG))
break;
else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)
{
/* Another line note follows; we can delete this note
if no intervening line numbers have notes elsewhere. */
int num;
for (num = NOTE_LINE_NUMBER (insn) + 1;
num < NOTE_LINE_NUMBER (note);
num++)
if (line_note_exists[num])
break;
if (num >= NOTE_LINE_NUMBER (note))
note_after = 1;
/* If there is anything real after this note, output it.
If another line note follows, omit this one. */
for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))
{
if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)
break;
}
}
/* Output this line note
if it is the first or the last line note in a row. */
if (!note_after)
output_source_line (file, insn);
/* These types of notes can be significant
so make sure the preceding line number stays. */
else if (GET_CODE (note) == NOTE
&& (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_END
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_FUNCTION_BEG))
break;
else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)
{
/* Another line note follows; we can delete this note
if no intervening line numbers have notes elsewhere. */
int num;
for (num = NOTE_LINE_NUMBER (insn) + 1;
num < NOTE_LINE_NUMBER (note);
num++)
if (line_note_exists[num])
break;
if (num >= NOTE_LINE_NUMBER (note))
note_after = 1;
break;
}
}
/* Output this line note if it is the first or the last line
note in a row. */
if (!note_after)
output_source_line (file, insn);
}
break;
}
break;
case BARRIER:
#if defined (DWARF2_UNWIND_INFO)
/* If we push arguments, we need to check all insns for stack
adjustments. */
if (!ACCUMULATE_OUTGOING_ARGS && dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
/* If we push arguments, we need to check all insns for stack
adjustments. */
if (!ACCUMULATE_OUTGOING_ARGS && dwarf2out_do_frame ())
dwarf2out_frame_debug (insn);
#endif
break;
@ -3544,8 +3566,10 @@ output_asm_label (x)
char buf[256];
if (GET_CODE (x) == LABEL_REF)
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
else if (GET_CODE (x) == CODE_LABEL)
x = XEXP (x, 0);
if (GET_CODE (x) == CODE_LABEL
|| (GET_CODE (x) == NOTE
&& NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
else
output_operand_lossage ("`%l' operand isn't a label");

View File

@ -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)

View File

@ -1275,37 +1275,8 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
get their addresses taken. */
if (else_bb)
{
if (LABEL_NUSES (else_bb->head) == 0
&& ! LABEL_PRESERVE_P (else_bb->head)
&& ! LABEL_NAME (else_bb->head))
{
/* We can merge the ELSE. */
merge_blocks_nomove (combo_bb, else_bb);
num_removed_blocks++;
}
else
{
/* We cannot merge the ELSE. */
/* Properly rewire the edge out of the now combined
TEST-THEN block to point here. */
remove_edge (combo_bb->succ);
if (combo_bb->succ || else_bb->pred)
abort ();
make_edge (NULL, combo_bb, else_bb, EDGE_FALLTHRU);
/* Remove the jump and cruft from the end of the TEST-THEN block. */
tidy_fallthru_edge (combo_bb->succ, combo_bb, else_bb);
/* Make sure we update life info properly. */
SET_UPDATE_LIFE(combo_bb);
if (else_bb->global_live_at_end)
COPY_REG_SET (else_bb->global_live_at_start,
else_bb->global_live_at_end);
/* The ELSE is the new combo block. */
combo_bb = else_bb;
}
merge_blocks_nomove (combo_bb, else_bb);
num_removed_blocks++;
}
/* If there was no join block reported, that means it was not adjacent
@ -1325,12 +1296,11 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
abort ();
}
/* The JOIN block had a label. It may have had quite a number
of other predecessors too, but probably not. See if we can
merge this with the others. */
else if (LABEL_NUSES (join_bb->head) == 0
&& ! LABEL_PRESERVE_P (join_bb->head)
&& ! LABEL_NAME (join_bb->head))
/* The JOIN block may have had quite a number of other predecessors too.
Since we've already merged the TEST, THEN and ELSE blocks, we should
have only one remaining edge from our if-then-else diamond. If there
is more than one remaining edge, it must come from elsewhere. */
else if (join_bb->pred->pred_next == NULL)
{
/* We can merge the JOIN. */
if (combo_bb->global_live_at_end)
@ -1438,11 +1408,6 @@ find_if_block (test_bb, then_edge, else_edge)
|| (then_succ->flags & EDGE_COMPLEX))
return FALSE;
/* The THEN block may not start with a label, as might happen with an
unused user label that has had its address taken. */
if (GET_CODE (then_bb->head) == CODE_LABEL)
return FALSE;
/* If the THEN block's successor is the other edge out of the TEST block,
then we have an IF-THEN combo without an ELSE. */
if (then_succ->dest == else_bb)
@ -1600,10 +1565,6 @@ find_if_case_1 (test_bb, then_edge, else_edge)
if (then_bb->pred->pred_next != NULL)
return FALSE;
/* THEN has no label. */
if (GET_CODE (then_bb->head) == CODE_LABEL)
return FALSE;
/* ELSE follows THEN. (??? could be moved) */
if (else_bb->index != then_bb->index + 1)
return FALSE;
@ -1674,12 +1635,6 @@ find_if_case_2 (test_bb, then_edge, else_edge)
if (else_bb->pred->pred_next != NULL)
return FALSE;
/* ELSE has a label we can delete. */
if (LABEL_NUSES (else_bb->head) > 1
|| LABEL_PRESERVE_P (else_bb->head)
|| LABEL_NAME (else_bb->head))
return FALSE;
/* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)

View File

@ -1262,10 +1262,19 @@ duplicate_loop_exit_test (loop_start)
make them. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) != REG_LABEL)
REG_NOTES (copy)
= copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
XEXP (link, 0),
REG_NOTES (copy)));
{
if (GET_CODE (link) == EXPR_LIST)
REG_NOTES (copy)
= copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
XEXP (link, 0),
REG_NOTES (copy)));
else
REG_NOTES (copy)
= copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
XEXP (link, 0),
REG_NOTES (copy)));
}
if (reg_map && REG_NOTES (copy))
replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
break;
@ -1345,8 +1354,8 @@ duplicate_loop_exit_test (loop_start)
return 1;
}
/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, and
loop-end notes between START and END out before START. Assume that
/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
eh-beg, eh-end notes between START and END out before START. Assume that
END is not such a note. START may be such a note. Returns the value
of the new starting insn, which may be different if the original start
was such a note. */
@ -1367,7 +1376,9 @@ squeeze_notes (start, end)
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP))
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
{
if (insn == start)
start = next;
@ -2389,6 +2400,12 @@ mark_jump_label (x, insn, cross_jump, in_mem)
rtx note;
rtx next;
/* Ignore remaining references to unreachable labels that
have been deleted. */
if (GET_CODE (label) == NOTE
&& NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
break;
if (GET_CODE (label) != CODE_LABEL)
abort ();
@ -2449,7 +2466,7 @@ mark_jump_label (x, insn, cross_jump, in_mem)
is no longer valid because of the more accurate cfg
we build in find_basic_blocks -- it no longer pessimizes
code when it finds a REG_LABEL note. */
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL, label,
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
REG_NOTES (insn));
}
}
@ -2755,9 +2772,10 @@ delete_insn (insn)
dont_really_delete = 1;
else if (! dont_really_delete)
{
const char *name = LABEL_NAME (insn);
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
NOTE_SOURCE_FILE (insn) = 0;
NOTE_SOURCE_FILE (insn) = name;
dont_really_delete = 1;
}
}

View File

@ -210,6 +210,13 @@ print_rtx (in_rtx)
indent -= 2;
break;
case NOTE_INSN_DELETED_LABEL:
if (NOTE_SOURCE_FILE (in_rtx))
fprintf (outfile, " (\"%s\")", NOTE_SOURCE_FILE (in_rtx));
else
fprintf (outfile, " \"\"");
break;
default:
{
const char * const str = X0STR (in_rtx, i);
@ -334,11 +341,25 @@ print_rtx (in_rtx)
rtx sub = XEXP (in_rtx, i);
enum rtx_code subc = GET_CODE (sub);
if (GET_CODE (in_rtx) == LABEL_REF && subc != CODE_LABEL)
goto do_e;
if (GET_CODE (in_rtx) == LABEL_REF)
{
if (subc == NOTE
&& NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
{
if (flag_dump_unnumbered)
fprintf (outfile, " [# deleted]");
else
fprintf (outfile, " [%d deleted]", INSN_UID (sub));
sawclose = 0;
break;
}
if (subc != CODE_LABEL)
goto do_e;
}
if (flag_dump_unnumbered)
fputc ('#', outfile);
fputs (" #", outfile);
else
fprintf (outfile, " %d", INSN_UID (sub));
}
@ -372,34 +393,43 @@ print_rtx (in_rtx)
abort ();
}
if (GET_CODE (in_rtx) == MEM)
fprintf (outfile, " %d", MEM_ALIAS_SET (in_rtx));
switch (GET_CODE (in_rtx))
{
case MEM:
fprintf (outfile, " %d", MEM_ALIAS_SET (in_rtx));
break;
#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64
if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
{
double val;
REAL_VALUE_FROM_CONST_DOUBLE (val, in_rtx);
fprintf (outfile, " [%.16g]", val);
}
case CONST_DOUBLE:
if (FLOAT_MODE_P (GET_MODE (in_rtx)))
{
double val;
REAL_VALUE_FROM_CONST_DOUBLE (val, in_rtx);
fprintf (outfile, " [%.16g]", val);
}
break;
#endif
if (GET_CODE (in_rtx) == CODE_LABEL)
{
case CODE_LABEL:
fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
if (LABEL_ALTERNATE_NAME (in_rtx))
fprintf (outfile, " [alternate name: %s]",
LABEL_ALTERNATE_NAME (in_rtx));
break;
case CALL_PLACEHOLDER:
for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
if (GET_CODE (tem) == CALL_INSN)
{
fprintf (outfile, " ");
print_rtx (tem);
break;
}
break;
default:
break;
}
if (GET_CODE (in_rtx) == CALL_PLACEHOLDER)
for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
if (GET_CODE (tem) == CALL_INSN)
{
fprintf (outfile, " ");
print_rtx (tem);
break;
}
if (dump_for_graph
&& (is_insn || GET_CODE (in_rtx) == NOTE

View File

@ -413,21 +413,16 @@ DEF_RTL_EXPR(BARRIER, "barrier", "iuu", 'x')
/* Holds a label that is followed by instructions.
Operand:
3: is a number that is unique in the entire compilation.
4: is the user-given name of the label, if any.
5: is used in jump.c for the use-count of the label.
6: is used in flow.c to point to the chain of label_ref's to this label.
3: is used in jump.c for the use-count of the label.
4: is used in flow.c to point to the chain of label_ref's to this label.
5: is a number that is unique in the entire compilation.
6: is the user-given name of the label, if any.
7: is the alternate label name. */
DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuuis00s", 'x')
DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuu00iss", 'x')
/* Say where in the code a source line starts, for symbol table's sake.
Contains a filename and a line number. Line numbers <= 0 are special:
0 is used in a dummy placed at the front of every function
just so there will never be a need to delete the first insn;
-1 indicates a dummy; insns to be deleted by flow analysis and combining
are really changed to NOTEs with a number of -1.
-2 means beginning of a name binding contour; output N_LBRAC.
-3 means end of a contour; output N_RBRAC. */
Contains a filename and a line number. Line numbers <= 0 are special;
See enum note_insn in rtl.h. */
DEF_RTL_EXPR(NOTE, "note", "iuu0n", 'x')
/* ----------------------------------------------------------------------

View File

@ -417,7 +417,7 @@ enum reg_note
appear on an insn which copies a register parameter to a pseudo-register,
if there is a memory address which could be used to hold that
pseudo-register throughout the function. */
REG_EQUIV,
REG_EQUIV,
/* Like REG_EQUIV except that the destination is only momentarily equal
to the specified rtx. Therefore, it cannot be used for substitution;
@ -437,7 +437,8 @@ enum reg_note
REG_RETVAL,
/* The inverse of REG_RETVAL: it goes on the first insn of the library call
and points at the one that has the REG_RETVAL. */
and points at the one that has the REG_RETVAL. This note is also an
INSN_LIST. */
REG_LIBCALL,
/* The register is always nonnegative during the containing loop. This is
@ -459,11 +460,13 @@ enum reg_note
we permit putting a cc0-setting insn in the delay slot of a branch as
long as only one copy of the insn exists. In that case, these notes
point from one to the other to allow code generation to determine what
any require information and to properly update CC_STATUS. */
any require information and to properly update CC_STATUS. These notes
are INSN_LISTs. */
REG_CC_SETTER, REG_CC_USER,
/* Points to a CODE_LABEL. Used by non-JUMP_INSNs to say that the
CODE_LABEL contained in the REG_LABEL note is used by the insn. */
CODE_LABEL contained in the REG_LABEL note is used by the insn.
This note is an INSN_LIST. */
REG_LABEL,
/* REG_DEP_ANTI and REG_DEP_OUTPUT are used in LOG_LINKS to represent
@ -544,7 +547,7 @@ extern const char * const reg_note_name[];
/* The label-number of a code-label. The assembler label
is made from `L' and the label-number printed in decimal.
Label numbers are unique in a compilation. */
#define CODE_LABEL_NUMBER(INSN) XINT(INSN, 3)
#define CODE_LABEL_NUMBER(INSN) XINT(INSN, 5)
#define LINE_NUMBER NOTE
@ -664,11 +667,11 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* The name of a label, in case it corresponds to an explicit label
in the input source code. */
#define LABEL_NAME(RTX) XCSTR(RTX, 4, CODE_LABEL)
#define LABEL_NAME(RTX) XCSTR(RTX, 6, CODE_LABEL)
/* In jump.c, each label contains a count of the number
of LABEL_REFs that point at it, so unused labels can be deleted. */
#define LABEL_NUSES(RTX) XCINT(RTX, 5, CODE_LABEL)
#define LABEL_NUSES(RTX) XCINT(RTX, 3, CODE_LABEL)
/* Associate a name with a CODE_LABEL. */
#define LABEL_ALTERNATE_NAME(RTX) XCSTR(RTX, 7, CODE_LABEL)
@ -687,8 +690,8 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* Once basic blocks are found in flow.c,
each CODE_LABEL starts a chain that goes through
all the LABEL_REFs that jump to that label.
The chain eventually winds up at the CODE_LABEL; it is circular. */
#define LABEL_REFS(LABEL) XCEXP(LABEL, 6, CODE_LABEL)
The chain eventually winds up at the CODE_LABEL: it is circular. */
#define LABEL_REFS(LABEL) XCEXP(LABEL, 4, CODE_LABEL)
/* This is the field in the LABEL_REF through which the circular chain
of references to a particular label is linked.

View File

@ -2207,6 +2207,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
this new block. */
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
&& ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)