diff options
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/cfglayout.c | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 15 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 15 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 8 | ||||
-rw-r--r-- | gcc/final.c | 9 | ||||
-rw-r--r-- | gcc/gengtype.c | 1 | ||||
-rw-r--r-- | gcc/insn-notes.def | 4 | ||||
-rw-r--r-- | gcc/print-rtl.c | 4 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 19 | ||||
-rw-r--r-- | gcc/var-tracking.c | 23 |
11 files changed, 122 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9765e3ce154..25eb1ce4bb1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2011-11-05 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/50693 + * tree-cfg.c (gimple_can_merge_blocks_p): Allow merging with + non-forced user labels. + (gimple_merge_blocks): Turn non-forced user labels into + debug bind stmt with the label as first operand and reset value. + (gimple_duplicate_bb): Don't duplicate label debug stmts. + * dwarf2out.c (gen_label_die): Handle NOTE_INSN_DELETED_DEBUG_LABEL. + * final.c (final_scan_insn): Likewise. + (rest_of_clean_state): Don't dump NOTE_INSN_DELETED_DEBUG_LABEL. + * var-tracking.c (debug_label_num): New variable. + (delete_debug_insns): Don't delete DEBUG_INSNs for LABEL_DECLs, + instead turn them into NOTE_INSN_DELETED_DEBUG_LABEL notes. + * cfglayout.c (skip_insns_after_block, duplicate_insn_chain): Handle + NOTE_INSN_DELETED_DEBUG_LABEL. + (duplicate_insn_chain): Don't duplicate LABEL_DECL DEBUG_INSNs. + * insn-notes.def (DELETED_DEBUG_LABEL): New note kind. + * print-rtl.c (print_rtx): Handle NOTE_INSN_DELETED_DEBUG_LABEL. + * gengtype.c (adjust_field_rtx_def): Likewise. + * config/i386/i386.c (ix86_output_function_epilogue): For MachO + clear CODE_LABEL_NUMBER of NOTE_INSN_DELETED_DEBUG_LABEL + if their are at the end of function and nop hasn't been emitted. + * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Likewise. + 2011-11-05 Georg-Johann Lay <avr@gjlay.de> PR rtl-optimization/50448 diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 62ac6bfe151..22d3d87e68b 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -149,6 +149,7 @@ skip_insns_after_block (basic_block bb) break; case NOTE_INSN_DELETED: case NOTE_INSN_DELETED_LABEL: + case NOTE_INSN_DELETED_DEBUG_LABEL: continue; default: reorder_insns (insn, insn, last_insn); @@ -1174,6 +1175,10 @@ duplicate_insn_chain (rtx from, rtx to) switch (GET_CODE (insn)) { case DEBUG_INSN: + /* Don't duplicate label debug insns. */ + if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL) + break; + /* FALLTHRU */ case INSN: case CALL_INSN: case JUMP_INSN: @@ -1219,6 +1224,7 @@ duplicate_insn_chain (rtx from, rtx to) case NOTE_INSN_DELETED: case NOTE_INSN_DELETED_LABEL: + case NOTE_INSN_DELETED_DEBUG_LABEL: /* No problem to strip these. */ case NOTE_INSN_FUNCTION_BEG: /* There is always just single entry to function. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fb0ac8de0b0..ca62b229089 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10879,15 +10879,28 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, it looks like we might want one, insert a NOP. */ { rtx insn = get_last_insn (); + rtx deleted_debug_label = NULL_RTX; while (insn && NOTE_P (insn) && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL) - insn = PREV_INSN (insn); + { + /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL + notes only, instead set their CODE_LABEL_NUMBER to -1, + otherwise there would be code generation differences + in between -g and -g0. */ + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL) + deleted_debug_label = insn; + insn = PREV_INSN (insn); + } if (insn && (LABEL_P (insn) || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))) fputs ("\tnop\n", file); + else if (deleted_debug_label) + for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn)) + if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL) + CODE_LABEL_NUMBER (insn) = -1; } #endif diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 86fe85906e6..779086a30b1 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21461,15 +21461,28 @@ rs6000_output_function_epilogue (FILE *file, it looks like we might want one, insert a NOP. */ { rtx insn = get_last_insn (); + rtx deleted_debug_label = NULL_RTX; while (insn && NOTE_P (insn) && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL) - insn = PREV_INSN (insn); + { + /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL + notes only, instead set their CODE_LABEL_NUMBER to -1, + otherwise there would be code generation differences + in between -g and -g0. */ + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL) + deleted_debug_label = insn; + insn = PREV_INSN (insn); + } if (insn && (LABEL_P (insn) || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))) fputs ("\tnop\n", file); + else if (deleted_debug_label) + for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn)) + if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL) + CODE_LABEL_NUMBER (insn) = -1; } #endif diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e6f86a49854..39be9a16e9c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -18020,6 +18020,14 @@ gen_label_die (tree decl, dw_die_ref context_die) ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn)); add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); } + else if (insn + && NOTE_P (insn) + && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL + && CODE_LABEL_NUMBER (insn) != -1) + { + ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn)); + add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); + } } } diff --git a/gcc/final.c b/gcc/final.c index e6d288639b7..bd4e7a762a7 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2080,6 +2080,12 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); break; + case NOTE_INSN_DELETED_DEBUG_LABEL: + /* Similarly, but need to use different namespace for it. */ + if (CODE_LABEL_NUMBER (insn) != -1) + ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn)); + break; + case NOTE_INSN_VAR_LOCATION: case NOTE_INSN_CALL_ARG_LOCATION: if (!DECL_IGNORED_P (current_function_decl)) @@ -4369,7 +4375,8 @@ rest_of_clean_state (void) (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION && NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG - && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END))) + && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END + && NOTE_KIND (insn) != NOTE_INSN_DELETED_DEBUG_LABEL))) print_rtl_single (final_output, insn); } diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 6063d81daa5..c9c08a4db31 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1015,6 +1015,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) { case NOTE_INSN_MAX: case NOTE_INSN_DELETED_LABEL: + case NOTE_INSN_DELETED_DEBUG_LABEL: note_flds = create_field (note_flds, &string_type, "rt_str"); break; diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 2ea673f05e6..c1d621a1d16 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -36,6 +36,10 @@ INSN_NOTE (DELETED) /* Generated in place of user-declared labels when they are deleted. */ INSN_NOTE (DELETED_LABEL) +/* Similarly, but for labels that have been present in debug stmts + earlier and thus will only appear with -g. These must use different + label namespace. */ +INSN_NOTE (DELETED_DEBUG_LABEL) /* These are used to mark the beginning and end of a lexical block. See NOTE_BLOCK and reorder_blocks. */ diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index edeeefa6071..9bd8621c4ed 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -283,6 +283,7 @@ print_rtx (const_rtx in_rtx) } case NOTE_INSN_DELETED_LABEL: + case NOTE_INSN_DELETED_DEBUG_LABEL: { const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); if (label) @@ -442,7 +443,8 @@ print_rtx (const_rtx in_rtx) { /* This field is only used for NOTE_INSN_DELETED_LABEL, and other times often contains garbage from INSN->NOTE death. */ - if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL) + if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL + || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL) fprintf (outfile, " %d", XINT (in_rtx, i)); } #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 2819e7b2fc6..28aea2f6933 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1454,8 +1454,8 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b) break; lab = gimple_label_label (stmt); - /* Do not remove user labels. */ - if (!DECL_ARTIFICIAL (lab)) + /* Do not remove user forced labels. */ + if (!DECL_ARTIFICIAL (lab) && FORCED_LABEL (lab)) return false; } @@ -1701,6 +1701,15 @@ gimple_merge_blocks (basic_block a, basic_block b) gimple_stmt_iterator dest_gsi = gsi_start_bb (a); gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT); } + /* Other user labels keep around in a form of a debug stmt. */ + else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_STMTS) + { + gimple dbg = gimple_build_debug_bind (label, + integer_zero_node, + stmt); + gimple_debug_bind_reset_value (dbg); + gsi_insert_before (&gsi, dbg, GSI_SAME_STMT); + } lp_nr = EH_LANDING_PAD_NR (label); if (lp_nr) @@ -5207,6 +5216,12 @@ gimple_duplicate_bb (basic_block bb) if (gimple_code (stmt) == GIMPLE_LABEL) continue; + /* Don't duplicate label debug stmts. */ + if (gimple_debug_bind_p (stmt) + && TREE_CODE (gimple_debug_bind_get_var (stmt)) + == LABEL_DECL) + continue; + /* Create a new copy of STMT and duplicate STMT's virtual operands. */ copy = gimple_copy (stmt); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 11d4efdcdc2..95bc02b183c 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -9517,6 +9517,12 @@ vt_initialize (void) return true; } +/* This is *not* reset after each function. It gives each + NOTE_INSN_DELETED_DEBUG_LABEL in the entire compilation + a unique label number. */ + +static int debug_label_num = 1; + /* Get rid of all debug insns from the insn stream. */ static void @@ -9532,7 +9538,22 @@ delete_debug_insns (void) { FOR_BB_INSNS_SAFE (bb, insn, next) if (DEBUG_INSN_P (insn)) - delete_insn (insn); + { + tree decl = INSN_VAR_LOCATION_DECL (insn); + if (TREE_CODE (decl) == LABEL_DECL + && DECL_NAME (decl) + && !DECL_RTL_SET_P (decl)) + { + PUT_CODE (insn, NOTE); + NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL; + NOTE_DELETED_LABEL_NAME (insn) + = IDENTIFIER_POINTER (DECL_NAME (decl)); + SET_DECL_RTL (decl, insn); + CODE_LABEL_NUMBER (insn) = debug_label_num++; + } + else + delete_insn (insn); + } } } |