summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/sched-deps.c177
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/pr28726.c29
4 files changed, 131 insertions, 90 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 22e113f5014..defc9d59188 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+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>
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index a408fab0706..0cde4f2e94f 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bfffc3269ff..3be624e205d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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.
diff --git a/gcc/testsuite/gcc.dg/pr28726.c b/gcc/testsuite/gcc.dg/pr28726.c
new file mode 100644
index 00000000000..11232ac86a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr28726.c
@@ -0,0 +1,29 @@
+/* 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;
+}