This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
A sched.c patch
- To: law at cygnus dot com
- Subject: A sched.c patch
- From: hjl at lucon dot org (H.J. Lu)
- Date: Sun, 12 Jul 1998 18:52:12 -0700 (PDT)
- Cc: egcs-patches at cygnus dot com
This patch fixes
http://www.cygnus.com/ml/egcs-bugs/1998-Jul/0297.html
http://www.cygnus.com/ml/egcs-bugs/1998-Jul/0298.html
BTW, those bugs may be only visible on x86 with -march=i586 -mcpu=i586.
The problem is the interaction between true_dependence and rtx_varies_p
called from sched_analyze_2. sched_analyze_2 is called for a block. But
rtx_varies_p doesn't realy work very well on a block. true_dependence
will miss dependency within a block when rtx_varies_p is used.
This patch intrudoce a new function, sched_rtx_varies_p, which works on
block. It uses reg_last_sets to check if a register varies within a
block.
That patch may not be perfect. I hope someone can come up with a better
one.
Thanks.
--
H.J. Lu (hjl@gnu.org)
---
Sun Jul 12 18:38:49 1998 H.J. Lu (hjl@gnu.org)
* sched.c (sched_rtx_varies_p): New function to check if a
rtx varies within a block.
(note_get_set_src): New function to get the source of a SET
insn.
(sched_analyze_2): Call true_dependence with sched_rtx_varies_p
instead of rtx_varies_p.
--- ../../../src/egcs/gcc/sched.c Fri Jun 19 09:13:59 1998
+++ ./sched.c Sun Jul 12 17:41:34 1998
@@ -339,6 +339,8 @@ static void split_hard_reg_notes PROTO((
static void new_insn_dead_notes PROTO((rtx, rtx, rtx, rtx));
static void update_n_sets PROTO((rtx, int));
static void update_flow_info PROTO((rtx, rtx, rtx, rtx));
+static int sched_rtx_varies_p PROTO((rtx));
+static void note_get_set_src PROTO((rtx, rtx));
/* Main entry point of this file. */
void schedule_insns PROTO((FILE *));
@@ -541,6 +543,109 @@ static rtx last_scheduled_insn;
We are careful to build only dependencies which actually exist, and
use transitivity to avoid building too many links. */
+static rtx set_dest;
+static rtx set_src;
+
+static void
+note_get_set_src (x, pat)
+ rtx x;
+ rtx pat;
+{
+ if (set_src != (rtx) -1 && rtx_equal_p (x, set_dest))
+ {
+ if (GET_CODE (pat) != SET)
+ pat = single_set (pat);
+
+ if (pat && rtx_equal_p (x, SET_DEST (pat)))
+ {
+ if (set_src || reg_mentioned_p (x, SET_SRC (pat)))
+ set_src = (rtx) -1;
+ else
+ set_src = SET_SRC (pat);
+ }
+ }
+}
+
+static HARD_REG_SET scanned_regs;
+
+/* Return 1 if X has a value that can vary in the current block.
+ It is very similar to rtx_varies_p (), but it only checks the
+ current block. */
+
+static int
+sched_rtx_varies_p (x)
+ rtx x;
+{
+ register RTX_CODE code = GET_CODE (x);
+ register int i;
+ register char *fmt;
+
+ switch (code)
+ {
+ case MEM:
+ case QUEUED:
+ return 1;
+
+ case CONST:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 0;
+
+ case REG:
+ /* Note that we have to test for the actual rtx used for the frame
+ and arg pointers and not just the register number in case we have
+ eliminated the frame and/or arg pointer and are using it
+ for pseudos. */
+ if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
+ || x == arg_pointer_rtx || x == pic_offset_table_rtx)
+ return 0;
+ else if (reg_last_sets [REGNO (x)])
+ {
+ if (TEST_HARD_REG_BIT (scanned_regs, REGNO (x)))
+ return 1;
+ else
+ SET_HARD_REG_BIT (scanned_regs, REGNO (x));
+
+ set_src = NULL_RTX;
+ set_dest = x;
+ note_stores (PATTERN (reg_last_sets [REGNO (x)]),
+ note_get_set_src);
+ if (set_src && set_src != (rtx) -1)
+ {
+ switch (GET_CODE (set_src))
+ {
+ case MEM:
+ return sched_rtx_varies_p (XEXP (set_src, 0));
+
+ default:
+ return sched_rtx_varies_p (set_src);
+ }
+ }
+ else
+ return 1;
+ }
+ else
+ return 0;
+
+ case LO_SUM:
+ /* The operand 0 of a LO_SUM is considered constant
+ (in fact is it related specifically to operand 1). */
+ return sched_rtx_varies_p (XEXP (x, 1));
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ if (sched_rtx_varies_p (XEXP (x, i)))
+ return 1;
+ return 0;
+}
+
/* Return the INSN_LIST containing INSN in LIST, or NULL
if LIST does not contain INSN. */
@@ -1392,9 +1497,12 @@ sched_analyze_2 (x, insn)
{
/* If a dependency already exists, don't create a new one. */
if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn)))
- if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
- x, rtx_varies_p))
- add_dependence (insn, XEXP (pending, 0), 0);
+ {
+ CLEAR_HARD_REG_SET (scanned_regs);
+ if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
+ x, sched_rtx_varies_p))
+ add_dependence (insn, XEXP (pending, 0), 0);
+ }
pending = XEXP (pending, 1);
pending_mem = XEXP (pending_mem, 1);