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> 2006-09-11 Guenter Roeck <guenter@roeck-us.net>
David Edelsohn <edelsohn@gnu.org> David Edelsohn <edelsohn@gnu.org>
......
...@@ -715,6 +715,78 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read, ...@@ -715,6 +715,78 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
deps->pending_flush_length = 1; 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 /* 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 rtx, X, creating all dependencies generated by the write to the
destination of X, and reads of everything mentioned. */ destination of X, and reads of everything mentioned. */
...@@ -722,7 +794,6 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read, ...@@ -722,7 +794,6 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
static void static void
sched_analyze_1 (struct deps *deps, rtx x, rtx insn) sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
{ {
int regno;
rtx dest = XEXP (x, 0); rtx dest = XEXP (x, 0);
enum rtx_code code = GET_CODE (x); enum rtx_code code = GET_CODE (x);
...@@ -771,64 +842,21 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn) ...@@ -771,64 +842,21 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
if (REG_P (dest)) 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 #ifdef STACK_REGS
/* Treat all writes to a stack register as modifying the TOS. */ /* Treat all writes to a stack register as modifying the TOS. */
if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG) if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
{ {
SET_REGNO_REG_SET (reg_pending_uses, FIRST_STACK_REG); /* Avoid analyzing the same register twice. */
regno = FIRST_STACK_REG; 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 #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)) else if (MEM_P (dest))
{ {
...@@ -935,51 +963,20 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn) ...@@ -935,51 +963,20 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
case REG: case REG:
{ {
int regno = REGNO (x); int regno = REGNO (x);
enum machine_mode mode = GET_MODE (x);
sched_analyze_reg (deps, regno, mode, USE, insn);
#ifdef STACK_REGS #ifdef STACK_REGS
/* Treat all reads of a stack register as modifying the TOS. */ /* Treat all reads of a stack register as modifying the TOS. */
if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG) if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
{ {
SET_REGNO_REG_SET (reg_pending_sets, FIRST_STACK_REG); /* Avoid analyzing the same register twice. */
regno = FIRST_STACK_REG; 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 #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; return;
} }
......
2006-09-11 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/pr28726.c: New test.
2006-09-11 Josh Conner <jconner@apple.com> 2006-09-11 Josh Conner <jconner@apple.com>
* gcc.dg/nrv3.c: Increase size of structure. * 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