summaryrefslogtreecommitdiff
path: root/gcc/final.c
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/final.c
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/final.c')
-rw-r--r--gcc/final.c316
1 files changed, 170 insertions, 146 deletions
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");