Index: gcc/gcc/final.c |
diff --git a/gcc/gcc/final.c b/gcc/gcc/final.c |
index 1735a73207dcb53241a1fe96c4adfb181dd230f8..e2b7461bbbea18a3f3a66b460381ff753c43d0e1 100644 |
--- a/gcc/gcc/final.c |
+++ b/gcc/gcc/final.c |
@@ -1,6 +1,6 @@ |
/* Convert RTL to assembler code and output it, for GNU compiler. |
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, |
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
Free Software Foundation, Inc. |
This file is part of GCC. |
@@ -72,6 +72,7 @@ along with GCC; see the file COPYING3. If not see |
#include "expr.h" |
#include "cfglayout.h" |
#include "tree-pass.h" |
+#include "tree-flow.h" |
#include "timevar.h" |
#include "cgraph.h" |
#include "coverage.h" |
@@ -130,6 +131,12 @@ rtx current_output_insn; |
/* Line number of last NOTE. */ |
static int last_linenum; |
+/* Last discriminator written to assembly. */ |
+static int last_discriminator; |
+ |
+/* Discriminator of current block. */ |
+static int discriminator; |
+ |
/* Highest line number in current block. */ |
static int high_block_linenum; |
@@ -197,17 +204,18 @@ rtx final_sequence; |
static int dialect_number; |
#endif |
-#ifdef HAVE_conditional_execution |
/* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */ |
rtx current_insn_predicate; |
-#endif |
+ |
+/* True if printing into -fdump-final-insns= dump. */ |
+bool final_insns_dump_p; |
#ifdef HAVE_ATTR_length |
static int asm_insn_count (rtx); |
#endif |
static void profile_function (FILE *); |
static void profile_after_prologue (FILE *); |
-static bool notice_source_line (rtx); |
+static bool notice_source_line (rtx, bool *); |
static rtx walk_alter_subreg (rtx *, bool *); |
static void output_asm_name (void); |
static void output_alternate_entry_point (FILE *, rtx); |
@@ -384,6 +392,7 @@ get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED, |
case NOTE: |
case BARRIER: |
case CODE_LABEL: |
+ case DEBUG_INSN: |
return 0; |
case CALL_INSN: |
@@ -553,7 +562,17 @@ static int min_labelno, max_labelno; |
int |
label_to_alignment (rtx label) |
{ |
- return LABEL_TO_ALIGNMENT (label); |
+ if (CODE_LABEL_NUMBER (label) <= max_labelno) |
+ return LABEL_TO_ALIGNMENT (label); |
+ return 0; |
+} |
+ |
+int |
+label_to_max_skip (rtx label) |
+{ |
+ if (CODE_LABEL_NUMBER (label) <= max_labelno) |
+ return LABEL_TO_MAX_SKIP (label); |
+ return 0; |
} |
#ifdef HAVE_ATTR_length |
@@ -801,7 +820,7 @@ struct rtl_opt_pass pass_compute_alignments = |
NULL, /* sub */ |
NULL, /* next */ |
0, /* static_pass_number */ |
- 0, /* tv_id */ |
+ TV_NONE, /* tv_id */ |
0, /* properties_required */ |
0, /* properties_provided */ |
0, /* properties_destroyed */ |
@@ -891,6 +910,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) |
if (LABEL_P (insn)) |
{ |
rtx next; |
+ bool next_is_jumptable; |
/* Merge in alignments computed by compute_alignments. */ |
log = LABEL_TO_ALIGNMENT (insn); |
@@ -900,31 +920,30 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) |
max_skip = LABEL_TO_MAX_SKIP (insn); |
} |
- log = LABEL_ALIGN (insn); |
- if (max_log < log) |
+ next = next_nonnote_insn (insn); |
+ next_is_jumptable = next && JUMP_TABLE_DATA_P (next); |
+ if (!next_is_jumptable) |
{ |
- max_log = log; |
- max_skip = LABEL_ALIGN_MAX_SKIP; |
+ log = LABEL_ALIGN (insn); |
+ if (max_log < log) |
+ { |
+ max_log = log; |
+ max_skip = LABEL_ALIGN_MAX_SKIP; |
+ } |
} |
- next = next_nonnote_insn (insn); |
/* ADDR_VECs only take room if read-only data goes into the text |
section. */ |
- if (JUMP_TABLES_IN_TEXT_SECTION |
- || readonly_data_section == text_section) |
- if (next && JUMP_P (next)) |
- { |
- rtx nextbody = PATTERN (next); |
- if (GET_CODE (nextbody) == ADDR_VEC |
- || GET_CODE (nextbody) == ADDR_DIFF_VEC) |
- { |
- log = ADDR_VEC_ALIGN (next); |
- if (max_log < log) |
- { |
- max_log = log; |
- max_skip = LABEL_ALIGN_MAX_SKIP; |
- } |
- } |
- } |
+ if ((JUMP_TABLES_IN_TEXT_SECTION |
+ || readonly_data_section == text_section) |
+ && next_is_jumptable) |
+ { |
+ log = ADDR_VEC_ALIGN (next); |
+ if (max_log < log) |
+ { |
+ max_log = log; |
+ max_skip = LABEL_ALIGN_MAX_SKIP; |
+ } |
+ } |
LABEL_TO_ALIGNMENT (insn) = max_log; |
LABEL_TO_MAX_SKIP (insn) = max_skip; |
max_log = 0; |
@@ -1063,7 +1082,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED) |
INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid]; |
if (NOTE_P (insn) || BARRIER_P (insn) |
- || LABEL_P (insn)) |
+ || LABEL_P (insn) || DEBUG_INSN_P(insn)) |
continue; |
if (INSN_DELETED_P (insn)) |
continue; |
@@ -1381,13 +1400,23 @@ static int |
asm_insn_count (rtx body) |
{ |
const char *templ; |
- int count = 1; |
if (GET_CODE (body) == ASM_INPUT) |
templ = XSTR (body, 0); |
else |
templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL); |
+ return asm_str_count (templ); |
+} |
+#endif |
+ |
+/* Return the number of machine instructions likely to be generated for the |
+ inline-asm template. */ |
+int |
+asm_str_count (const char *templ) |
+{ |
+ int count = 1; |
+ |
if (!*templ) |
return 0; |
@@ -1398,7 +1427,6 @@ asm_insn_count (rtx body) |
return count; |
} |
-#endif |
/* ??? This is probably the wrong place for these. */ |
/* Structure recording the mapping from source file and directory |
@@ -1433,10 +1461,10 @@ add_debug_prefix_map (const char *arg) |
return; |
} |
map = XNEW (debug_prefix_map); |
- map->old_prefix = ggc_alloc_string (arg, p - arg); |
+ map->old_prefix = xstrndup (arg, p - arg); |
map->old_len = p - arg; |
p++; |
- map->new_prefix = ggc_strdup (p); |
+ map->new_prefix = xstrdup (p); |
map->new_len = strlen (p); |
map->next = debug_prefix_maps; |
debug_prefix_maps = map; |
@@ -1466,6 +1494,20 @@ remap_debug_filename (const char *filename) |
return ggc_strdup (s); |
} |
+/* Return true if DWARF2 debug info can be emitted for DECL. */ |
+ |
+static bool |
+dwarf2_debug_info_emitted_p (tree decl) |
+{ |
+ if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG) |
+ return false; |
+ |
+ if (DECL_IGNORED_P (decl)) |
+ return false; |
+ |
+ return true; |
+} |
+ |
/* Output assembler code for the start of a function, |
and initialize some of the variables in this file |
for the new function. The label for the function and associated |
@@ -1486,13 +1528,15 @@ final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file, |
last_filename = locator_file (prologue_locator); |
last_linenum = locator_line (prologue_locator); |
+ last_discriminator = discriminator = 0; |
high_block_linenum = high_function_linenum = last_linenum; |
- (*debug_hooks->begin_prologue) (last_linenum, last_filename); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->begin_prologue (last_linenum, last_filename); |
#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO) |
- if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG) |
+ if (!dwarf2_debug_info_emitted_p (current_function_decl)) |
dwarf2out_begin_prologue (0, NULL); |
#endif |
@@ -1560,12 +1604,14 @@ profile_function (FILE *file ATTRIBUTE_UNUSED) |
#ifndef NO_PROFILE_COUNTERS |
# define NO_PROFILE_COUNTERS 0 |
#endif |
-#if defined(ASM_OUTPUT_REG_PUSH) |
- int sval = cfun->returns_struct; |
- rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1); |
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM) |
- int cxt = cfun->static_chain_decl != NULL; |
-#endif |
+#ifdef ASM_OUTPUT_REG_PUSH |
+ rtx sval = NULL, chain = NULL; |
+ |
+ if (cfun->returns_struct) |
+ sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), |
+ true); |
+ if (cfun->static_chain_decl) |
+ chain = targetm.calls.static_chain (current_function_decl, true); |
#endif /* ASM_OUTPUT_REG_PUSH */ |
if (! NO_PROFILE_COUNTERS) |
@@ -1579,44 +1625,20 @@ profile_function (FILE *file ATTRIBUTE_UNUSED) |
switch_to_section (current_function_section ()); |
-#if defined(ASM_OUTPUT_REG_PUSH) |
- if (sval && svrtx != NULL_RTX && REG_P (svrtx)) |
- { |
- ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx)); |
- } |
-#endif |
- |
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) |
- if (cxt) |
- ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM); |
-#else |
-#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) |
- if (cxt) |
- { |
- ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM); |
- } |
-#endif |
+#ifdef ASM_OUTPUT_REG_PUSH |
+ if (sval && REG_P (sval)) |
+ ASM_OUTPUT_REG_PUSH (file, REGNO (sval)); |
+ if (chain && REG_P (chain)) |
+ ASM_OUTPUT_REG_PUSH (file, REGNO (chain)); |
#endif |
FUNCTION_PROFILER (file, current_function_funcdef_no); |
-#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) |
- if (cxt) |
- ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM); |
-#else |
-#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) |
- if (cxt) |
- { |
- ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM); |
- } |
-#endif |
-#endif |
- |
-#if defined(ASM_OUTPUT_REG_PUSH) |
- if (sval && svrtx != NULL_RTX && REG_P (svrtx)) |
- { |
- ASM_OUTPUT_REG_POP (file, REGNO (svrtx)); |
- } |
+#ifdef ASM_OUTPUT_REG_PUSH |
+ if (chain && REG_P (chain)) |
+ ASM_OUTPUT_REG_POP (file, REGNO (chain)); |
+ if (sval && REG_P (sval)) |
+ ASM_OUTPUT_REG_POP (file, REGNO (sval)); |
#endif |
} |
@@ -1629,17 +1651,19 @@ final_end_function (void) |
{ |
app_disable (); |
- (*debug_hooks->end_function) (high_function_linenum); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->end_function (high_function_linenum); |
/* Finally, output the function epilogue: |
code to restore the stack frame and return to the caller. */ |
targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ()); |
/* And debug output. */ |
- (*debug_hooks->end_epilogue) (last_linenum, last_filename); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->end_epilogue (last_linenum, last_filename); |
#if defined (DWARF2_UNWIND_INFO) |
- if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG |
+ if (!dwarf2_debug_info_emitted_p (current_function_decl) |
&& dwarf2out_do_frame ()) |
dwarf2out_end_epilogue (last_linenum, last_filename); |
#endif |
@@ -1820,7 +1844,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
dwarf2out_switch_text_section (); |
else |
#endif |
- (*debug_hooks->switch_text_section) (); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->switch_text_section (); |
switch_to_section (current_function_section ()); |
break; |
@@ -1842,6 +1867,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
else |
*seen |= SEEN_BB; |
+ discriminator = NOTE_BASIC_BLOCK (insn)->discriminator; |
+ |
break; |
case NOTE_INSN_EH_REGION_BEG: |
@@ -1869,12 +1896,23 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
break; |
case NOTE_INSN_EPILOGUE_BEG: |
+#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_epilogue) |
+ if (dwarf2out_do_frame ()) |
+ dwarf2out_begin_epilogue (insn); |
+#endif |
targetm.asm_out.function_begin_epilogue (file); |
break; |
+ case NOTE_INSN_CFA_RESTORE_STATE: |
+#if defined (DWARF2_UNWIND_INFO) |
+ dwarf2out_frame_debug_restore_state (); |
+#endif |
+ break; |
+ |
case NOTE_INSN_FUNCTION_BEG: |
app_disable (); |
- (*debug_hooks->end_prologue) (last_linenum, last_filename); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->end_prologue (last_linenum, last_filename); |
if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE) |
{ |
@@ -1900,7 +1938,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
high_block_linenum = last_linenum; |
/* Output debugging info about the symbol-block beginning. */ |
- (*debug_hooks->begin_block) (last_linenum, n); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->begin_block (last_linenum, n); |
/* Mark this block as output. */ |
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1; |
@@ -1934,7 +1973,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
--block_depth; |
gcc_assert (block_depth >= 0); |
- (*debug_hooks->end_block) (high_block_linenum, n); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->end_block (high_block_linenum, n); |
} |
if (write_symbols == DBX_DEBUG |
|| write_symbols == SDB_DEBUG) |
@@ -1964,7 +2004,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
break; |
case NOTE_INSN_VAR_LOCATION: |
- (*debug_hooks->var_location) (insn); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->var_location (insn); |
break; |
default: |
@@ -2007,54 +2048,47 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
CC_STATUS_INIT; |
#endif |
- if (LABEL_NAME (insn)) |
- (*debug_hooks->label) (insn); |
+ if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn)) |
+ debug_hooks->label (insn); |
app_disable (); |
next = next_nonnote_insn (insn); |
- if (next != 0 && JUMP_P (next)) |
+ /* If this label is followed by a jump-table, make sure we put |
+ the label in the read-only section. Also possibly write the |
+ label and jump table together. */ |
+ if (next != 0 && JUMP_TABLE_DATA_P (next)) |
{ |
- rtx nextbody = PATTERN (next); |
- |
- /* If this label is followed by a jump-table, |
- make sure we put the label in the read-only section. Also |
- possibly write the label and jump table together. */ |
- |
- if (GET_CODE (nextbody) == ADDR_VEC |
- || GET_CODE (nextbody) == ADDR_DIFF_VEC) |
- { |
#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC) |
- /* In this case, the case vector is being moved by the |
- target, so don't output the label at all. Leave that |
- to the back end macros. */ |
+ /* In this case, the case vector is being moved by the |
+ target, so don't output the label at all. Leave that |
+ to the back end macros. */ |
#else |
- if (! JUMP_TABLES_IN_TEXT_SECTION) |
- { |
- int log_align; |
+ if (! JUMP_TABLES_IN_TEXT_SECTION) |
+ { |
+ int log_align; |
- switch_to_section (targetm.asm_out.function_rodata_section |
- (current_function_decl)); |
+ switch_to_section (targetm.asm_out.function_rodata_section |
+ (current_function_decl)); |
#ifdef ADDR_VEC_ALIGN |
- log_align = ADDR_VEC_ALIGN (next); |
+ log_align = ADDR_VEC_ALIGN (next); |
#else |
- log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); |
+ log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); |
#endif |
- ASM_OUTPUT_ALIGN (file, log_align); |
- } |
- else |
- switch_to_section (current_function_section ()); |
+ ASM_OUTPUT_ALIGN (file, log_align); |
+ } |
+ else |
+ switch_to_section (current_function_section ()); |
#ifdef ASM_OUTPUT_CASE_LABEL |
- ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), |
- next); |
+ ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), |
+ next); |
#else |
- targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); |
+ targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn)); |
#endif |
#endif |
- break; |
- } |
+ break; |
} |
if (LABEL_ALT_ENTRY_P (insn)) |
output_alternate_entry_point (file, insn); |
@@ -2067,11 +2101,11 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
rtx body = PATTERN (insn); |
int insn_code_number; |
const char *templ; |
+ bool is_stmt; |
-#ifdef HAVE_conditional_execution |
/* Reset this early so it is correct for ASM statements. */ |
current_insn_predicate = NULL_RTX; |
-#endif |
+ |
/* An INSN, JUMP_INSN or CALL_INSN. |
First check for special kinds that recog doesn't recognize. */ |
@@ -2168,10 +2202,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
} |
/* Output this line note if it is the first or the last line |
note in a row. */ |
- if (notice_source_line (insn)) |
- { |
- (*debug_hooks->source_line) (last_linenum, last_filename); |
- } |
+ if (!DECL_IGNORED_P (current_function_decl) |
+ && notice_source_line (insn, &is_stmt)) |
+ (*debug_hooks->source_line) (last_linenum, last_filename, |
+ last_discriminator, is_stmt); |
if (GET_CODE (body) == ASM_INPUT) |
{ |
@@ -2235,6 +2269,10 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
#endif |
} |
+ if (targetm.asm_out.final_postscan_insn) |
+ targetm.asm_out.final_postscan_insn (file, insn, ops, |
+ insn_noperands); |
+ |
this_is_asm_operands = 0; |
break; |
} |
@@ -2316,9 +2354,13 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
&& GET_CODE (SET_DEST (set)) == CC0 |
&& insn != last_ignored_compare) |
{ |
+ rtx src1, src2; |
if (GET_CODE (SET_SRC (set)) == SUBREG) |
SET_SRC (set) = alter_subreg (&SET_SRC (set)); |
- else if (GET_CODE (SET_SRC (set)) == COMPARE) |
+ |
+ src1 = SET_SRC (set); |
+ src2 = NULL_RTX; |
+ if (GET_CODE (SET_SRC (set)) == COMPARE) |
{ |
if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG) |
XEXP (SET_SRC (set), 0) |
@@ -2326,11 +2368,18 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG) |
XEXP (SET_SRC (set), 1) |
= alter_subreg (&XEXP (SET_SRC (set), 1)); |
+ if (XEXP (SET_SRC (set), 1) |
+ == CONST0_RTX (GET_MODE (XEXP (SET_SRC (set), 0)))) |
+ src2 = XEXP (SET_SRC (set), 0); |
} |
if ((cc_status.value1 != 0 |
- && rtx_equal_p (SET_SRC (set), cc_status.value1)) |
+ && rtx_equal_p (src1, cc_status.value1)) |
|| (cc_status.value2 != 0 |
- && rtx_equal_p (SET_SRC (set), cc_status.value2))) |
+ && rtx_equal_p (src1, cc_status.value2)) |
+ || (src2 != 0 && cc_status.value1 != 0 |
+ && rtx_equal_p (src2, cc_status.value1)) |
+ || (src2 != 0 && cc_status.value2 != 0 |
+ && rtx_equal_p (src2, cc_status.value2))) |
{ |
/* Don't delete insn if it has an addressing side-effect. */ |
if (! FIND_REG_INC_NOTE (insn, NULL_RTX) |
@@ -2344,9 +2393,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
} |
} |
} |
-#endif |
-#ifdef HAVE_cc0 |
/* If this is a conditional branch, maybe modify it |
if the cc's are in a nonstandard state |
so that it accomplishes the same thing that it would |
@@ -2543,10 +2590,9 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands); |
#endif |
-#ifdef HAVE_conditional_execution |
- if (GET_CODE (PATTERN (insn)) == COND_EXEC) |
+ if (targetm.have_conditional_execution () |
+ && GET_CODE (PATTERN (insn)) == COND_EXEC) |
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn)); |
-#endif |
#ifdef HAVE_cc0 |
cc_prev_status = cc_status; |
@@ -2637,6 +2683,32 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
/* Output assembler code from the template. */ |
output_asm_insn (templ, recog_data.operand); |
+ /* Record point-of-call information for ICF debugging. */ |
+ if (flag_enable_icf_debug && CALL_P (insn)) |
+ { |
+ rtx x = call_from_call_insn (insn); |
+ x = XEXP (x, 0); |
+ if (x && MEM_P (x)) |
+ { |
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF) |
+ { |
+ tree t; |
+ x = XEXP (x, 0); |
+ t = SYMBOL_REF_DECL (x); |
+ if (t) |
+ (*debug_hooks->direct_call) (t); |
+ } |
+ else |
+ (*debug_hooks->virtual_call) (INSN_UID (insn)); |
+ } |
+ } |
+ |
+ /* Some target machines need to postscan each insn after |
+ it is output. */ |
+ if (targetm.asm_out.final_postscan_insn) |
+ targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand, |
+ recog_data.n_operands); |
+ |
/* If necessary, report the effect that the instruction has on |
the unwind info. We've already done this for delay slots |
and call instructions. */ |
@@ -2655,10 +2727,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, |
return NEXT_INSN (insn); |
} |
-/* Return whether a source line note needs to be emitted before INSN. */ |
+/* Return whether a source line note needs to be emitted before INSN. |
+ Sets IS_STMT to TRUE if the line should be marked as a possible |
+ breakpoint location. */ |
static bool |
-notice_source_line (rtx insn) |
+notice_source_line (rtx insn, bool *is_stmt) |
{ |
const char *filename; |
int linenum; |
@@ -2674,18 +2748,33 @@ notice_source_line (rtx insn) |
linenum = insn_line (insn); |
} |
- if (filename |
- && (force_source_line |
- || filename != last_filename |
- || last_linenum != linenum)) |
+ if (filename == NULL) |
+ return false; |
+ |
+ if (force_source_line |
+ || filename != last_filename |
+ || last_linenum != linenum) |
{ |
force_source_line = false; |
last_filename = filename; |
last_linenum = linenum; |
+ last_discriminator = discriminator; |
+ *is_stmt = true; |
high_block_linenum = MAX (last_linenum, high_block_linenum); |
high_function_linenum = MAX (last_linenum, high_function_linenum); |
return true; |
} |
+ |
+ if (SUPPORTS_DISCRIMINATOR && last_discriminator != discriminator) |
+ { |
+ /* If the discriminator changed, but the line number did not, |
+ output the line table entry with is_stmt false so the |
+ debugger does not treat this as a breakpoint location. */ |
+ last_discriminator = discriminator; |
+ *is_stmt = false; |
+ return true; |
+ } |
+ |
return false; |
} |
@@ -3065,7 +3154,7 @@ get_mem_expr_from_op (rtx op, int *paddressp) |
&& (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp))) |
return expr; |
- while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY |
+ while (UNARY_P (op) |
|| GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH) |
op = XEXP (op, 0); |
@@ -3268,7 +3357,7 @@ output_asm_insn (const char *templ, rtx *operands) |
} |
else if (letter == 'n') |
{ |
- if (GET_CODE (operands[opnum]) == CONST_INT) |
+ if (CONST_INT_P (operands[opnum])) |
fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, |
- INTVAL (operands[opnum])); |
else |
@@ -3500,7 +3589,7 @@ output_addr_const (FILE *file, rtx x) |
case PLUS: |
/* Some assemblers need integer constants to appear last (eg masm). */ |
- if (GET_CODE (XEXP (x, 0)) == CONST_INT) |
+ if (CONST_INT_P (XEXP (x, 0))) |
{ |
output_addr_const (file, XEXP (x, 1)); |
if (INTVAL (XEXP (x, 0)) >= 0) |
@@ -3510,7 +3599,7 @@ output_addr_const (FILE *file, rtx x) |
else |
{ |
output_addr_const (file, XEXP (x, 0)); |
- if (GET_CODE (XEXP (x, 1)) != CONST_INT |
+ if (!CONST_INT_P (XEXP (x, 1)) |
|| INTVAL (XEXP (x, 1)) >= 0) |
fprintf (file, "+"); |
output_addr_const (file, XEXP (x, 1)); |
@@ -3526,7 +3615,7 @@ output_addr_const (FILE *file, rtx x) |
output_addr_const (file, XEXP (x, 0)); |
fprintf (file, "-"); |
- if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0) |
+ if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0) |
|| GET_CODE (XEXP (x, 1)) == PC |
|| GET_CODE (XEXP (x, 1)) == SYMBOL_REF) |
output_addr_const (file, XEXP (x, 1)); |
@@ -3734,7 +3823,7 @@ asm_fprintf (FILE *file, const char *p, ...) |
void |
split_double (rtx value, rtx *first, rtx *second) |
{ |
- if (GET_CODE (value) == CONST_INT) |
+ if (CONST_INT_P (value)) |
{ |
if (HOST_BITS_PER_WIDE_INT >= (2 * BITS_PER_WORD)) |
{ |
@@ -4197,7 +4286,8 @@ rest_of_handle_final (void) |
*will* be routed past here. */ |
timevar_push (TV_SYMOUT); |
- (*debug_hooks->function_decl) (current_function_decl); |
+ if (!DECL_IGNORED_P (current_function_decl)) |
+ debug_hooks->function_decl (current_function_decl); |
timevar_pop (TV_SYMOUT); |
/* Release the blocks that are linked to DECL_INITIAL() to free the memory. */ |
@@ -4220,7 +4310,7 @@ struct rtl_opt_pass pass_final = |
{ |
{ |
RTL_PASS, |
- NULL, /* name */ |
+ "final", /* name */ |
NULL, /* gate */ |
rest_of_handle_final, /* execute */ |
NULL, /* sub */ |
@@ -4268,6 +4358,44 @@ static unsigned int |
rest_of_clean_state (void) |
{ |
rtx insn, next; |
+ FILE *final_output = NULL; |
+ int save_unnumbered = flag_dump_unnumbered; |
+ int save_noaddr = flag_dump_noaddr; |
+ |
+ if (flag_dump_final_insns) |
+ { |
+ final_output = fopen (flag_dump_final_insns, "a"); |
+ if (!final_output) |
+ { |
+ error ("could not open final insn dump file %qs: %s", |
+ flag_dump_final_insns, strerror (errno)); |
+ flag_dump_final_insns = NULL; |
+ } |
+ else |
+ { |
+ const char *aname; |
+ |
+ aname = (IDENTIFIER_POINTER |
+ (DECL_ASSEMBLER_NAME (current_function_decl))); |
+ fprintf (final_output, "\n;; Function (%s) %s\n\n", aname, |
+ cfun->function_frequency == FUNCTION_FREQUENCY_HOT |
+ ? " (hot)" |
+ : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED |
+ ? " (unlikely executed)" |
+ : ""); |
+ |
+ flag_dump_noaddr = flag_dump_unnumbered = 1; |
+ if (flag_compare_debug_opt || flag_compare_debug) |
+ dump_flags |= TDF_NOUID; |
+ final_insns_dump_p = true; |
+ |
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) |
+ if (LABEL_P (insn)) |
+ INSN_UID (insn) = CODE_LABEL_NUMBER (insn); |
+ else |
+ INSN_UID (insn) = 0; |
+ } |
+ } |
/* It is very important to decompose the RTL instruction chain here: |
debug information keeps pointing into CODE_LABEL insns inside the function |
@@ -4278,6 +4406,29 @@ rest_of_clean_state (void) |
next = NEXT_INSN (insn); |
NEXT_INSN (insn) = NULL; |
PREV_INSN (insn) = NULL; |
+ |
+ if (final_output |
+ && (!NOTE_P (insn) || |
+ (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION |
+ && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG |
+ && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END |
+ && NOTE_KIND (insn) != NOTE_INSN_CFA_RESTORE_STATE))) |
+ print_rtl_single (final_output, insn); |
+ |
+ } |
+ |
+ if (final_output) |
+ { |
+ flag_dump_noaddr = save_noaddr; |
+ flag_dump_unnumbered = save_unnumbered; |
+ final_insns_dump_p = false; |
+ |
+ if (fclose (final_output)) |
+ { |
+ error ("could not close final insn dump file %qs: %s", |
+ flag_dump_final_insns, strerror (errno)); |
+ flag_dump_final_insns = NULL; |
+ } |
} |
/* In case the function was not output, |
@@ -4288,6 +4439,7 @@ rest_of_clean_state (void) |
sdbout_types (NULL_TREE); |
#endif |
+ flag_rerun_cse_after_global_opts = 0; |
reload_completed = 0; |
epilogue_completed = 0; |
#ifdef STACK_REGS |
@@ -4303,6 +4455,8 @@ rest_of_clean_state (void) |
free_bb_for_insn (); |
+ delete_tree_ssa (); |
+ |
if (targetm.binds_local_p (current_function_decl)) |
{ |
unsigned int pref = crtl->preferred_stack_boundary; |
@@ -4332,7 +4486,7 @@ struct rtl_opt_pass pass_clean_state = |
{ |
{ |
RTL_PASS, |
- NULL, /* name */ |
+ "*clean_state", /* name */ |
NULL, /* gate */ |
rest_of_clean_state, /* execute */ |
NULL, /* sub */ |
@@ -4346,4 +4500,3 @@ struct rtl_opt_pass pass_clean_state = |
0 /* todo_flags_finish */ |
} |
}; |
- |