Commit d9e7c8e3 by Roger Sayle Committed by Roger Sayle

re PR rtl-optimization/11634 ([hppa] ICE in verify_local_live_at_start, at flow.c:555)


	PR optimization/11634
	* recog.c (split_insn): Factor test of INSN_P and handling of
	set_noop_p out of here into the two callers.
	(split_all_insns): Add INSN_P test and set_noop_p handling here.
	If deleting a no-op set after reload that has a REG_UNUSED note,
	mark the basic block as changed and recalculate life information.
	(split_all_insns_noflow): Add INSN_P test and set_noop_p handling
	here.

	* gcc.dg/20031201-2.c: New test case.

From-SVN: r74145
parent b58b21d5
2003-12-01 Roger Sayle <roger@eyesopen.com>
PR optimization/11634
* recog.c (split_insn): Factor test of INSN_P and handling of
set_noop_p out of here into the two callers.
(split_all_insns): Add INSN_P test and set_noop_p handling here.
If deleting a no-op set after reload that has a REG_UNUSED note,
mark the basic block as changed and recalculate life information.
(split_all_insns_noflow): Add INSN_P test and set_noop_p handling
here.
2003-12-01 Roger Sayle <roger@eyesopen.com>
PR optimization/12322
* gcse.c (struct ls_expr): Change type of hash_index from int to
unsigned int.
......
......@@ -2642,61 +2642,42 @@ reg_fits_class_p (rtx operand, enum reg_class class, int offset,
return 0;
}
/* Split single instruction. Helper function for split_all_insns.
Return last insn in the sequence if successful, or NULL if unsuccessful. */
/* Split single instruction. Helper function for split_all_insns and
split_all_insns_noflow. Return last insn in the sequence if successful,
or NULL if unsuccessful. */
static rtx
split_insn (rtx insn)
{
rtx set;
if (!INSN_P (insn))
;
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
/* Split insns here to get max fine-grain parallelism. */
rtx first = PREV_INSN (insn);
rtx last = try_split (PATTERN (insn), insn, 1);
else if ((set = single_set (insn)) != NULL && set_noop_p (set))
{
/* Nops get in the way while scheduling, so delete them
now if register allocation has already been done. It
is too risky to try to do this before register
allocation, and there are unlikely to be very many
nops then anyways. */
if (reload_completed)
delete_insn_and_edges (insn);
}
else
{
/* Split insns here to get max fine-grain parallelism. */
rtx first = PREV_INSN (insn);
rtx last = try_split (PATTERN (insn), insn, 1);
if (last == insn)
return NULL_RTX;
/* try_split returns the NOTE that INSN became. */
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (last != insn)
/* ??? Coddle to md files that generate subregs in post-reload
splitters instead of computing the proper hard register. */
if (reload_completed && first != last)
{
first = NEXT_INSN (first);
for (;;)
{
/* try_split returns the NOTE that INSN became. */
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
/* ??? Coddle to md files that generate subregs in post-
reload splitters instead of computing the proper
hard register. */
if (reload_completed && first != last)
{
first = NEXT_INSN (first);
while (1)
{
if (INSN_P (first))
cleanup_subreg_operands (first);
if (first == last)
break;
first = NEXT_INSN (first);
}
}
return last;
if (INSN_P (first))
cleanup_subreg_operands (first);
if (first == last)
break;
first = NEXT_INSN (first);
}
}
return NULL_RTX;
return last;
}
/* Split all insns in the function. If UPD_LIFE, update life info after. */
void
......@@ -2717,24 +2698,52 @@ split_all_insns (int upd_life)
for (insn = bb->head; !finish ; insn = next)
{
rtx last;
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
finish = (insn == bb->end);
last = split_insn (insn);
if (last)
if (INSN_P (insn))
{
/* The split sequence may include barrier, but the
BB boundary we are interested in will be set to previous
one. */
while (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
SET_BIT (blocks, bb->index);
changed = true;
insn = last;
rtx set = single_set (insn);
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
if (set && set_noop_p (set))
{
/* Nops get in the way while scheduling, so delete them
now if register allocation has already been done. It
is too risky to try to do this before register
allocation, and there are unlikely to be very many
nops then anyways. */
if (reload_completed)
{
/* If the no-op set has a REG_UNUSED note, we need
to update liveness information. */
if (find_reg_note (insn, REG_UNUSED, NULL_RTX))
{
SET_BIT (blocks, bb->index);
changed = true;
}
/* ??? Is life info affected by deleting edges? */
delete_insn_and_edges (insn);
}
}
else
{
rtx last = split_insn (insn);
if (last)
{
/* The split sequence may include barrier, but the
BB boundary we are interested in will be set to
previous one. */
while (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
SET_BIT (blocks, bb->index);
changed = true;
}
}
}
}
}
......@@ -2771,9 +2780,28 @@ split_all_insns_noflow (void)
for (insn = get_insns (); insn; insn = next)
{
next = NEXT_INSN (insn);
split_insn (insn);
if (INSN_P (insn))
{
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
rtx set = single_set (insn);
if (set && set_noop_p (set))
{
/* Nops get in the way while scheduling, so delete them
now if register allocation has already been done. It
is too risky to try to do this before register
allocation, and there are unlikely to be very many
nops then anyways.
??? Should we use delete_insn when the CFG isn't valid? */
if (reload_completed)
delete_insn_and_edges (insn);
}
else
split_insn (insn);
}
}
return;
}
#ifdef HAVE_peephole2
......
2003-12-01 Roger Sayle <roger@eyesopen.com>
PR optimization/11634
* gcc.dg/20031201-2.c: New test case.
2003-12-01 Zack Weinberg <zack@codesourcery.com>
PR 11433
......
/* PR optimization/11634 */
/* The following code used to ICE in verify_local_live_at_start on
PA when compiled with -O2. The cause was that split_all_insns was
not updating liveness information when deleting no-op moves that
had REG_UNUSED notes. */
/* { dg-do compile { target hppa*-*-* } } */
/* { dg-options "-O2" } */
void *f(void *s);
void H5T_conv_vlen (unsigned long long nelmts, unsigned char *bg_ptr)
{
long long seq_len;
unsigned long long bg_seq_len = 0;
unsigned src_base_size, dst_base_size;
void *tmp_buf = 0;
unsigned tmp_buf_size = 0;
unsigned long long elmtno;
for (elmtno = 0; elmtno < nelmts; elmtno++)
{
unsigned char *tmp = bg_ptr;
bg_seq_len = *tmp;
if (bg_seq_len > 0
&& tmp_buf_size <
(unsigned) (bg_seq_len *
(src_base_size > dst_base_size
? src_base_size
: dst_base_size)))
{
tmp_buf_size =
(unsigned) (bg_seq_len *
(src_base_size > dst_base_size
? src_base_size
: dst_base_size));
}
if (bg_seq_len < seq_len)
f ((unsigned char *) tmp_buf + dst_base_size * bg_seq_len);
}
}
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