Commit 2e9182fd by Eric Botcazou Committed by Eric Botcazou

re PR rtl-optimization/28726 (-fsched2-use-superblock produces wrong code)

	PR rtl-optimization/28726
	* sched-deps.c (sched_analyze_reg): New function extracted from...
	(sched_analyze_1): ...here.  Call it to analyze references to
	registers.  Treat again writes to a stack register as writing to the
	register.
	(sched_analyze_2): ...and here.  Call it to analyze references to
	registers.  Treat again reads of a stack register as reading the
	register.

From-SVN: r116855
parent c2b448c6
2006-09-11 Eric Botcazou <ebotcazou@libertysurf.fr>
PR rtl-optimization/28726
* sched-deps.c (sched_analyze_reg): New function extracted from...
(sched_analyze_1): ...here. Call it to analyze references to
registers. Treat again writes to a stack register as writing to the
register.
(sched_analyze_2): ...and here. Call it to analyze references to
registers. Treat again reads of a stack register as reading the
register.
2006-09-11 Guenter Roeck <guenter@roeck-us.net>
David Edelsohn <edelsohn@gnu.org>
......
......@@ -715,6 +715,78 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
deps->pending_flush_length = 1;
}
/* Analyze a single reference to register (reg:MODE REGNO) in INSN.
The type of the reference is specified by REF and can be SET,
CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE. */
static void
sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode,
enum rtx_code ref, rtx insn)
{
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
if (regno < FIRST_PSEUDO_REGISTER)
{
int i = hard_regno_nregs[regno][mode];
if (ref == SET)
{
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_sets, regno + i);
}
else if (ref == USE)
{
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_uses, regno + i);
}
else
{
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_clobbers, regno + i);
}
}
/* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
it does not reload. Ignore these as they have served their
purpose already. */
else if (regno >= deps->max_reg)
{
enum rtx_code code = GET_CODE (PATTERN (insn));
gcc_assert (code == USE || code == CLOBBER);
}
else
{
if (ref == SET)
SET_REGNO_REG_SET (reg_pending_sets, regno);
else if (ref == USE)
SET_REGNO_REG_SET (reg_pending_uses, regno);
else
SET_REGNO_REG_SET (reg_pending_clobbers, regno);
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
if (!reload_completed && get_reg_known_equiv_p (regno))
{
rtx t = get_reg_known_value (regno);
if (MEM_P (t))
sched_analyze_2 (deps, XEXP (t, 0), insn);
}
/* Don't let it cross a call after scheduling if it doesn't
already cross one. */
if (REG_N_CALLS_CROSSED (regno) == 0)
{
if (ref == USE)
deps->sched_before_next_call
= alloc_INSN_LIST (insn, deps->sched_before_next_call);
else
add_dependence_list (insn, deps->last_function_call, 1,
REG_DEP_ANTI);
}
}
}
/* Analyze a single SET, CLOBBER, PRE_DEC, POST_DEC, PRE_INC or POST_INC
rtx, X, creating all dependencies generated by the write to the
destination of X, and reads of everything mentioned. */
......@@ -722,7 +794,6 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
static void
sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
{
int regno;
rtx dest = XEXP (x, 0);
enum rtx_code code = GET_CODE (x);
......@@ -771,64 +842,21 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
if (REG_P (dest))
{
regno = REGNO (dest);
int regno = REGNO (dest);
enum machine_mode mode = GET_MODE (dest);
sched_analyze_reg (deps, regno, mode, code, insn);
#ifdef STACK_REGS
/* Treat all writes to a stack register as modifying the TOS. */
if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
{
SET_REGNO_REG_SET (reg_pending_uses, FIRST_STACK_REG);
regno = FIRST_STACK_REG;
/* Avoid analyzing the same register twice. */
if (regno != FIRST_STACK_REG)
sched_analyze_reg (deps, FIRST_STACK_REG, mode, code, insn);
sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn);
}
#endif
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
if (regno < FIRST_PSEUDO_REGISTER)
{
int i = hard_regno_nregs[regno][GET_MODE (dest)];
if (code == SET)
{
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_sets, regno + i);
}
else
{
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_clobbers, regno + i);
}
}
/* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
it does not reload. Ignore these as they have served their
purpose already. */
else if (regno >= deps->max_reg)
{
gcc_assert (GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER);
}
else
{
if (code == SET)
SET_REGNO_REG_SET (reg_pending_sets, regno);
else
SET_REGNO_REG_SET (reg_pending_clobbers, regno);
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
if (!reload_completed && get_reg_known_equiv_p (regno))
{
rtx t = get_reg_known_value (regno);
if (MEM_P (t))
sched_analyze_2 (deps, XEXP (t, 0), insn);
}
/* Don't let it cross a call after scheduling if it doesn't
already cross one. */
if (REG_N_CALLS_CROSSED (regno) == 0)
add_dependence_list (insn, deps->last_function_call, 1,
REG_DEP_ANTI);
}
}
else if (MEM_P (dest))
{
......@@ -935,51 +963,20 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
case REG:
{
int regno = REGNO (x);
enum machine_mode mode = GET_MODE (x);
sched_analyze_reg (deps, regno, mode, USE, insn);
#ifdef STACK_REGS
/* Treat all reads of a stack register as modifying the TOS. */
if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
{
SET_REGNO_REG_SET (reg_pending_sets, FIRST_STACK_REG);
regno = FIRST_STACK_REG;
/* Avoid analyzing the same register twice. */
if (regno != FIRST_STACK_REG)
sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn);
sched_analyze_reg (deps, FIRST_STACK_REG, mode, SET, insn);
}
#endif
if (regno < FIRST_PSEUDO_REGISTER)
{
int i = hard_regno_nregs[regno][GET_MODE (x)];
while (--i >= 0)
SET_REGNO_REG_SET (reg_pending_uses, regno + i);
}
/* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
it does not reload. Ignore these as they have served their
purpose already. */
else if (regno >= deps->max_reg)
{
gcc_assert (GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER);
}
else
{
SET_REGNO_REG_SET (reg_pending_uses, regno);
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
if (!reload_completed && get_reg_known_equiv_p (regno))
{
rtx t = get_reg_known_value (regno);
if (MEM_P (t))
sched_analyze_2 (deps, XEXP (t, 0), insn);
}
/* If the register does not already cross any calls, then add this
insn to the sched_before_next_call list so that it will still
not cross calls after scheduling. */
if (REG_N_CALLS_CROSSED (regno) == 0)
deps->sched_before_next_call
= alloc_INSN_LIST (insn, deps->sched_before_next_call);
}
return;
}
......
2006-09-11 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/pr28726.c: New test.
2006-09-11 Josh Conner <jconner@apple.com>
* gcc.dg/nrv3.c: Increase size of structure.
/* PR rtl-optimization/28726 */
/* Origin: Sigurd Schneider <sg313d@gmail.com> */
/* { dg-do run } */
/* { dg-options "-O2 -fsched2-use-superblocks" } */
extern void abort (void);
static double my_loop(void) __attribute__((noinline));
static double my_loop(void)
{
double retval = 0.0;
const unsigned char *start = "\005\b\000";
const unsigned char *const end = start + 2;
while (start < end)
retval += *start++;
return retval;
}
int main(void)
{
if (my_loop() != 13.0)
abort ();
return 0;
}
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