re PR tree-optimization/50693 (Loop optimization restricted by GOTOs)

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.

From-SVN: r181014
This commit is contained in:
Jakub Jelinek 2011-11-05 20:58:37 +01:00 committed by Jakub Jelinek
parent eed33268ff
commit 5619e52cfb
11 changed files with 122 additions and 7 deletions

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}
}