summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/cfglayout.c6
-rw-r--r--gcc/config/i386/i386.c15
-rw-r--r--gcc/config/rs6000/rs6000.c15
-rw-r--r--gcc/dwarf2out.c8
-rw-r--r--gcc/final.c9
-rw-r--r--gcc/gengtype.c1
-rw-r--r--gcc/insn-notes.def4
-rw-r--r--gcc/print-rtl.c4
-rw-r--r--gcc/tree-cfg.c19
-rw-r--r--gcc/var-tracking.c23
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);
+ }
}
}