summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2000-05-12 16:26:15 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2000-05-12 16:26:15 +0000
commit74b0991dfaf52eb1f152e64b4afc0d1cb05ddc28 (patch)
treed0c01aedfa0c100dbc8cf6e908311acdea960127 /gcc
parent27d1c59cbab6ccce71a1a15d1e0471c6850dc50b (diff)
downloadgcc-74b0991dfaf52eb1f152e64b4afc0d1cb05ddc28.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33876 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog43
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/final.c316
-rw-r--r--gcc/flow.c127
-rw-r--r--gcc/ifcvt.c59
-rw-r--r--gcc/jump.c36
-rw-r--r--gcc/print-rtl.c74
-rw-r--r--gcc/rtl.def19
-rw-r--r--gcc/rtl.h21
-rw-r--r--gcc/unroll.c1
10 files changed, 388 insertions, 310 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 456338e8ae2..d5ff1679f75 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0ad11fb118d..3da7dee8447 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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
diff --git a/gcc/final.c b/gcc/final.c
index c207cfb1d5d..02dc418a35f 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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. */
+ switch (NOTE_LINE_NUMBER (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;
- 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;
+ 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;
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
- && ! 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));
+ 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)
- abort ();
+ 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);
+ 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);
+ 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);
+ 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);
+ if (write_symbols == DWARF_DEBUG)
+ dwarfout_end_block (n);
#endif
#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_end_block (n);
+ 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))
- {
+ }
+ 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);
+ if (write_symbols == DWARF_DEBUG)
+ dwarfout_label (insn);
#endif
#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_label (insn);
+ 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;
+ }
+ break;
-#if 0 /* This is what we used to do. */
- output_source_line (file, insn);
-#endif
- int note_after = 0;
+ default:
+ if (NOTE_LINE_NUMBER (insn) <= 0)
+ abort ();
- /* 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;
+ /* This note is a line-number. */
+ {
+ register rtx note;
+ 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;
- }
- }
- /* 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");
diff --git a/gcc/flow.c b/gcc/flow.c
index 1bea9c2959f..a8573e1642a 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)
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 8c2ddee0fbf..aa54390e73a 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -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)
diff --git a/gcc/jump.c b/gcc/jump.c
index baffdf03b7b..4296759545f 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -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;
}
}
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 140ac36bdb7..d8008380215 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -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
diff --git a/gcc/rtl.def b/gcc/rtl.def
index cbfd892bc67..97df5373e3e 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -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')
/* ----------------------------------------------------------------------
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 815cb0dc041..ccd143ecf02 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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.
diff --git a/gcc/unroll.c b/gcc/unroll.c
index 6ecef324612..82d2d69d836 100644
--- a/gcc/unroll.c
+++ b/gcc/unroll.c
@@ -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)