This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A sched.c patch


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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]