Commit 02b47899 by Kenneth Zadeck Committed by Kenneth Zadeck

re PR rtl-optimization/37922 (code generation error)

2008-12-18  Kenneth Zadeck <zadeck@naturalbridge.com>

	PR rtl-optimization/37922
	* dse.c (bb_info): Added regs_live field.
	(look_for_hardregs): New function.
	(replace_read): Added regs_live parameter and code to check that
	shift sequence does not clobber live hardregs.
	(check_mem_read_rtx): Added parameter to replace_read.
	(dse_step1): Added regs_live bitmap and initialize it.
	(rest_of_handle_dse): Added DF_NOTES problem and earlier call to
	df_analyze.
	* df-problems.c Renamed to 
	df_simulate_initialize_backwards.
	(df_simulate_one_insn): Renamed to
	df_simulate_one_insn_backwards.
	(df_simulate_artificial_refs_at_top): Renamed to 
	df_simulate_finalize_backwards.
	(df_simulate_initialized_forwards,
	df_simulate_one_insn_forwards,
	df_simulate_finalize_backwards): New functions.
	* df.h (df_simulate_artificial_refs_at_end): Renamed to 
	df_simulate_initialize_backwards.
	(df_simulate_one_insn): Renamed to
	df_simulate_one_insn_backwards.
	(df_simulate_artificial_refs_at_top): Renamed to 
	df_simulate_finalize_backwards.
	(df_simulate_initialized_forwards,
	df_simulate_one_insn_forwards,
	df_simulate_finalize_backwards): New functions.
	* ra-conflict.c (global_conflicts): Renamed
	df_simulate_artificial_refs_at_end to
	df_simulate_initialize_backwards.
	* sel-sched.c (propagate_lv_set): Renamed df_simulate_one_insn to
	df_simulate_one_insn_backwards.
	* ifcvt.c (dead_or_predicable): Renamed
	df_simulate_artificial_refs_at_end to
	df_simulate_initialize_backwards. Renamed df_simulate_one_insn to
	df_simulate_one_insn_backwards.
	* recog.c (peephole2_optimize): Ditto.
	* rtl-factoring (collect_pattern_seqs, clear_regs_live_in_seq): Ditto.

2008-12-18  Kenneth Zadeck <zadeck@naturalbridge.com>

	PR rtl-optimization/37922
	* g++.dg/torture/pr37922.C: New test.

From-SVN: r142809
parent fb5bc08b
2008-12-18 Kenneth Zadeck <zadeck@naturalbridge.com>
PR rtl-optimization/37922
* dse.c (bb_info): Added regs_live field.
(look_for_hardregs): New function.
(replace_read): Added regs_live parameter and code to check that
shift sequence does not clobber live hardregs.
(check_mem_read_rtx): Added parameter to replace_read.
(dse_step1): Added regs_live bitmap and initialize it.
(rest_of_handle_dse): Added DF_NOTES problem and earlier call to
df_analyze.
* df-problems.c Renamed to
df_simulate_initialize_backwards.
(df_simulate_one_insn): Renamed to
df_simulate_one_insn_backwards.
(df_simulate_artificial_refs_at_top): Renamed to
df_simulate_finalize_backwards.
(df_simulate_initialized_forwards,
df_simulate_one_insn_forwards,
df_simulate_finalize_backwards): New functions.
* df.h (df_simulate_artificial_refs_at_end): Renamed to
df_simulate_initialize_backwards.
(df_simulate_one_insn): Renamed to
df_simulate_one_insn_backwards.
(df_simulate_artificial_refs_at_top): Renamed to
df_simulate_finalize_backwards.
(df_simulate_initialized_forwards,
df_simulate_one_insn_forwards,
df_simulate_finalize_backwards): New functions.
* ra-conflict.c (global_conflicts): Renamed
df_simulate_artificial_refs_at_end to
df_simulate_initialize_backwards.
* sel-sched.c (propagate_lv_set): Renamed df_simulate_one_insn to
df_simulate_one_insn_backwards.
* ifcvt.c (dead_or_predicable): Renamed
df_simulate_artificial_refs_at_end to
df_simulate_initialize_backwards. Renamed df_simulate_one_insn to
df_simulate_one_insn_backwards.
* recog.c (peephole2_optimize): Ditto.
* rtl-factoring (collect_pattern_seqs, clear_regs_live_in_seq): Ditto.
2008-12-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/38533
......@@ -607,7 +607,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
bitmap_copy (local_live, DF_LR_OUT (bb));
df_simulate_artificial_refs_at_end (bb, local_live);
df_simulate_initialize_backwards (bb, local_live);
FOR_BB_INSNS_REVERSE (bb, insn)
if (INSN_P (insn))
......@@ -636,7 +636,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
df_simulate_uses (insn, local_live);
}
df_simulate_artificial_refs_at_top (bb, local_live);
df_simulate_finalize_backwards (bb, local_live);
block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
if (block_changed)
......
......@@ -3759,24 +3759,19 @@ df_simulate_fixup_sets (basic_block bb, bitmap live)
The following three functions are used only for BACKWARDS scanning:
i.e. they process the defs before the uses.
df_simulate_artificial_refs_at_end should be called first with a
df_simulate_initialize_backwards should be called first with a
bitvector copyied from the DF_LIVE_OUT or DF_LR_OUT. Then
df_simulate_one_insn should be called for each insn in the block,
starting with the last on. Finally,
df_simulate_artificial_refs_at_top can be called to get a new value
df_simulate_one_insn_backwards should be called for each insn in
the block, starting with the last on. Finally,
df_simulate_finalize_backwards can be called to get a new value
of the sets at the top of the block (this is rarely used).
It would be not be difficult to define a similar set of functions
that work in the forwards direction. In that case the functions
would ignore the use sets and look for the REG_DEAD and REG_UNUSED
notes.
----------------------------------------------------------------------------*/
----------------------------------------------------------------------------*/
/* Apply the artificial uses and defs at the end of BB in a backwards
direction. */
void
df_simulate_artificial_refs_at_end (basic_block bb, bitmap live)
df_simulate_initialize_backwards (basic_block bb, bitmap live)
{
df_ref *def_rec;
df_ref *use_rec;
......@@ -3801,7 +3796,7 @@ df_simulate_artificial_refs_at_end (basic_block bb, bitmap live)
/* Simulate the backwards effects of INSN on the bitmap LIVE. */
void
df_simulate_one_insn (basic_block bb, rtx insn, bitmap live)
df_simulate_one_insn_backwards (basic_block bb, rtx insn, bitmap live)
{
if (! INSN_P (insn))
return;
......@@ -3816,7 +3811,7 @@ df_simulate_one_insn (basic_block bb, rtx insn, bitmap live)
direction. */
void
df_simulate_artificial_refs_at_top (basic_block bb, bitmap live)
df_simulate_finalize_backwards (basic_block bb, bitmap live)
{
df_ref *def_rec;
#ifdef EH_USES
......@@ -3840,3 +3835,92 @@ df_simulate_artificial_refs_at_top (basic_block bb, bitmap live)
}
#endif
}
/*----------------------------------------------------------------------------
The following three functions are used only for FORWARDS scanning:
i.e. they process the defs and the REG_DEAD and REG_UNUSED notes.
Thus it is important to add the DF_NOTES problem to the stack of
problems computed before using these functions.
df_simulate_initialize_forwards should be called first with a
bitvector copyied from the DF_LIVE_IN or DF_LR_IN. Then
df_simulate_one_insn_forwards should be called for each insn in
the block, starting with the last on. Finally,
df_simulate_finalize_forwards can be called to get a new value
of the sets at the bottom of the block (this is rarely used).
----------------------------------------------------------------------------*/
/* Apply the artificial uses and defs at the top of BB in a backwards
direction. */
void
df_simulate_initialize_forwards (basic_block bb, bitmap live)
{
df_ref *def_rec;
int bb_index = bb->index;
for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
{
df_ref def = *def_rec;
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
}
/* Simulate the backwards effects of INSN on the bitmap LIVE. */
void
df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live)
{
rtx link;
if (! INSN_P (insn))
return;
/* Make sure that the DF_NOTES really is an active df problem. */
gcc_assert (df_note);
df_simulate_defs (insn, live);
/* Clear all of the registers that go dead. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
{
switch (REG_NOTE_KIND (link))
case REG_DEAD:
case REG_UNUSED:
{
rtx reg = XEXP (link, 0);
int regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
{
int n = hard_regno_nregs[regno][GET_MODE (reg)];
while (--n >= 0)
bitmap_clear_bit (live, regno + n);
}
else
bitmap_clear_bit (live, regno);
break;
default:
break;
}
}
df_simulate_fixup_sets (bb, live);
}
/* Apply the artificial uses and defs at the end of BB in a backwards
direction. */
void
df_simulate_finalize_forwards (basic_block bb, bitmap live)
{
df_ref *def_rec;
int bb_index = bb->index;
for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
{
df_ref def = *def_rec;
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
}
......@@ -959,9 +959,12 @@ extern void df_note_add_problem (void);
extern void df_simulate_find_defs (rtx, bitmap);
extern void df_simulate_defs (rtx, bitmap);
extern void df_simulate_uses (rtx, bitmap);
extern void df_simulate_artificial_refs_at_end (basic_block, bitmap);
extern void df_simulate_one_insn (basic_block, rtx, bitmap);
extern void df_simulate_artificial_refs_at_top (basic_block, bitmap);
extern void df_simulate_initialize_backwards (basic_block, bitmap);
extern void df_simulate_one_insn_backwards (basic_block, rtx, bitmap);
extern void df_simulate_finalize_backwards (basic_block, bitmap);
extern void df_simulate_initialize_forwards (basic_block, bitmap);
extern void df_simulate_one_insn_forwards (basic_block, rtx, bitmap);
extern void df_simulate_finalize_forwards (basic_block, bitmap);
/* Functions defined in df-scan.c. */
......
......@@ -374,6 +374,10 @@ struct bb_info
operations. */
bool apply_wild_read;
/* The following 4 bitvectors hold information about which positions
of which stores are live or dead. They are indexed by
get_bitmap_index. */
/* The set of store positions that exist in this block before a wild read. */
bitmap gen;
......@@ -401,6 +405,14 @@ struct bb_info
just initializes the vector from one of the out sets of the
successors of the block. */
bitmap out;
/* The following bitvector is indexed by the reg number. It
contains the set of regs that are live at the current instruction
being processed. While it contains info for all of the
registers, only the pseudos are actually examined. It is used to
assure that shift sequences that are inserted do not accidently
clobber live hard regs. */
bitmap regs_live;
};
typedef struct bb_info *bb_info_t;
......@@ -1533,6 +1545,25 @@ find_shift_sequence (int access_size,
}
/* Call back for note_stores to find the hard regs set or clobbered by
insn. Data is a bitmap of the hardregs set so far. */
static void
look_for_hardregs (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
{
bitmap regs_set = (bitmap) data;
if (REG_P (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
{
int regno = REGNO (x);
int n = hard_regno_nregs[regno][GET_MODE (x)];
while (--n >= 0)
bitmap_set_bit (regs_set, regno + n);
}
}
/* Take a sequence of:
A <- r1
...
......@@ -1566,13 +1597,13 @@ find_shift_sequence (int access_size,
static bool
replace_read (store_info_t store_info, insn_info_t store_insn,
read_info_t read_info, insn_info_t read_insn, rtx *loc)
read_info_t read_info, insn_info_t read_insn, rtx *loc, bitmap regs_live)
{
enum machine_mode store_mode = GET_MODE (store_info->mem);
enum machine_mode read_mode = GET_MODE (read_info->mem);
int shift;
int access_size; /* In bytes. */
rtx insns, read_reg;
rtx insns, this_insn, read_reg;
if (!dbg_cnt (dse))
return false;
......@@ -1624,6 +1655,34 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
insns = get_insns ();
end_sequence ();
if (insns != NULL_RTX)
{
/* Now we have to scan the set of new instructions to see if the
sequence contains and sets of hardregs that happened to be
live at this point. For instance, this can happen if one of
the insns sets the CC and the CC happened to be live at that
point. This does occasionally happen, see PR 37922. */
bitmap regs_set = BITMAP_ALLOC (NULL);
for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn))
note_stores (PATTERN (this_insn), look_for_hardregs, regs_set);
bitmap_and_into (regs_set, regs_live);
if (!bitmap_empty_p (regs_set))
{
if (dump_file)
{
fprintf (dump_file,
"abandoning replacement because sequence clobbers live hardregs:");
df_print_regset (dump_file, regs_set);
}
BITMAP_FREE (regs_set);
return false;
}
BITMAP_FREE (regs_set);
}
if (validate_change (read_insn->insn, loc, read_reg, 0))
{
deferred_change_t deferred_change =
......@@ -1842,7 +1901,7 @@ check_mem_read_rtx (rtx *loc, void *data)
if ((store_info->positions_needed & mask) == mask
&& replace_read (store_info, i_ptr,
read_info, insn_info, loc))
read_info, insn_info, loc, bb_info->regs_live))
return 0;
}
/* The bases are the same, just see if the offsets
......@@ -1911,7 +1970,7 @@ check_mem_read_rtx (rtx *loc, void *data)
if ((store_info->positions_needed & mask) == mask
&& replace_read (store_info, i_ptr,
read_info, insn_info, loc))
read_info, insn_info, loc, bb_info->regs_live))
return 0;
}
......@@ -2139,7 +2198,8 @@ static void
dse_step1 (void)
{
basic_block bb;
bitmap regs_live = BITMAP_ALLOC (NULL);
cselib_init (false);
all_blocks = BITMAP_ALLOC (NULL);
bitmap_set_bit (all_blocks, ENTRY_BLOCK);
......@@ -2152,6 +2212,10 @@ dse_step1 (void)
memset (bb_info, 0, sizeof (struct bb_info));
bitmap_set_bit (all_blocks, bb->index);
bb_info->regs_live = regs_live;
bitmap_copy (regs_live, DF_LR_IN (bb));
df_simulate_initialize_forwards (bb, regs_live);
bb_table[bb->index] = bb_info;
cselib_discard_hook = remove_useless_values;
......@@ -2172,6 +2236,8 @@ dse_step1 (void)
if (INSN_P (insn))
scan_insn (bb_info, insn);
cselib_process_insn (insn);
if (INSN_P (insn))
df_simulate_one_insn_forwards (bb, insn, regs_live);
}
/* This is something of a hack, because the global algorithm
......@@ -2238,8 +2304,10 @@ dse_step1 (void)
free_alloc_pool (cse_store_info_pool);
}
bb_info->regs_live = NULL;
}
BITMAP_FREE (regs_live);
cselib_finish ();
htab_empty (rtx_group_table);
}
......@@ -3239,6 +3307,11 @@ rest_of_handle_dse (void)
df_set_flags (DF_DEFER_INSN_RESCAN);
/* Need the notes since we must track live hardregs in the forwards
direction. */
df_note_add_problem ();
df_analyze ();
dse_step0 ();
dse_step1 ();
dse_step2_init ();
......
......@@ -3950,13 +3950,13 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
/* The loop below takes the set of live registers
after JUMP, and calculates the live set before EARLIEST. */
bitmap_copy (test_live, df_get_live_in (other_bb));
df_simulate_artificial_refs_at_end (test_bb, test_live);
df_simulate_initialize_backwards (test_bb, test_live);
for (insn = jump; ; insn = prev)
{
if (INSN_P (insn))
{
df_simulate_find_defs (insn, test_set);
df_simulate_one_insn (test_bb, insn, test_live);
df_simulate_one_insn_backwards (test_bb, insn, test_live);
}
prev = PREV_INSN (insn);
if (insn == earliest)
......
......@@ -774,7 +774,7 @@ global_conflicts (void)
bitmap_iterator bi;
bitmap_copy (live, DF_LIVE_OUT (bb));
df_simulate_artificial_refs_at_end (bb, live);
df_simulate_initialize_backwards (bb, live);
sparseset_clear (allocnos_live);
memset (live_subregs_used, 0, max_allocno * sizeof (int));
......
......@@ -3039,7 +3039,7 @@ peephole2_optimize (void)
/* Start up propagation. */
bitmap_copy (live, DF_LR_OUT (bb));
df_simulate_artificial_refs_at_end (bb, live);
df_simulate_initialize_backwards (bb, live);
bitmap_copy (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
for (insn = BB_END (bb); ; insn = prev)
......@@ -3059,7 +3059,7 @@ peephole2_optimize (void)
&& peep2_insn_data[peep2_current].insn == NULL_RTX)
peep2_current_count++;
peep2_insn_data[peep2_current].insn = insn;
df_simulate_one_insn (bb, insn, live);
df_simulate_one_insn_backwards (bb, insn, live);
COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
if (RTX_FRAME_RELATED_P (insn))
......@@ -3218,7 +3218,7 @@ peephole2_optimize (void)
peep2_current_count++;
peep2_insn_data[i].insn = x;
df_insn_rescan (x);
df_simulate_one_insn (bb, x, live);
df_simulate_one_insn_backwards (bb, x, live);
bitmap_copy (peep2_insn_data[i].live_before, live);
}
x = PREV_INSN (x);
......
......@@ -464,7 +464,7 @@ collect_pattern_seqs (void)
/* Initialize liveness propagation. */
INIT_REG_SET (&live);
bitmap_copy (&live, DF_LR_OUT (bb));
df_simulate_artificial_refs_at_end (bb, &live);
df_simulate_initialize_backwards (bb, &live);
/* Propagate liveness info and mark insns where a stack reg is live. */
insn = BB_END (bb);
......@@ -486,7 +486,7 @@ collect_pattern_seqs (void)
}
if (insn == BB_HEAD (bb))
break;
df_simulate_one_insn (bb, insn, &live);
df_simulate_one_insn_backwards (bb, insn, &live);
insn = prev;
}
......@@ -572,11 +572,11 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length)
bb = BLOCK_FOR_INSN (insn);
INIT_REG_SET (&live);
bitmap_copy (&live, DF_LR_OUT (bb));
df_simulate_artificial_refs_at_end (bb, &live);
df_simulate_initialize_backwards (bb, &live);
/* Propagate until INSN if found. */
for (x = BB_END (bb); x != insn; x = PREV_INSN (x))
df_simulate_one_insn (bb, x, &live);
df_simulate_one_insn_backwards (bb, x, &live);
/* Clear registers live after INSN. */
renumbered_reg_set_to_hard_reg_set (&hlive, &live);
......@@ -586,7 +586,7 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length)
for (i = 0; i < length;)
{
rtx prev = PREV_INSN (x);
df_simulate_one_insn (bb, x, &live);
df_simulate_one_insn_backwards (bb, x, &live);
if (INSN_P (x))
{
......
......@@ -2947,7 +2947,7 @@ propagate_lv_set (regset lv, insn_t insn)
if (INSN_NOP_P (insn))
return;
df_simulate_one_insn (BLOCK_FOR_INSN (insn), insn, lv);
df_simulate_one_insn_backwards (BLOCK_FOR_INSN (insn), insn, lv);
}
/* Return livness set at the end of BB. */
......
2008-12-18 Kenneth Zadeck <zadeck@naturalbridge.com>
PR rtl-optimization/37922
* g++.dg/torture/pr37922.C: New test.
2008-12-18 Daniel Kraft <d@domob.eu>
PR fortran/31822
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment