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]
Other format: [Raw text]

[PATCH] Fix sched-ebb.c bug (was Re: [3.3 branch] IA64 bootstrap failure) (take 2)


Hi!

Seems like I missed an important detail about sched-ebb.c, particularly
if (deps->pending_lists_length > MAX_PENDING_LIST_LENGTH) flush the lists.
MAX_PENDING_LIST_LENGTH is by default 32, so the chains shouldn't be that
long to walk them through during unchain_one_value.
All VALUE rtxs with CSELIB_VAL_PTR(value)->locs == 0 should behave
the same in alias.c unless the identical VALUE is on both sides, so we can
IMHO put all useless VALUEs into the empty_vals chain and just replace them
with a special one which will be only present on the pending chains.

Here is the patch to implement it for gcc 3.3. cselib_unknown_addr could
be maybe replaced with a (cached) gen_rtx_SCRATCH (VOIDmode), I think it
should behave identically in alias.c as a VALUE with locs == 0.

For the trunk, I think we should put all cselib_val/elt_list/elt_loc_list
structs from the hash_table during clear_table and cselib_finish into
the empty_* chain.
Also, if empty_vals were chained through say addr_list instead of val_rtx,
new_cselib_val could reuse VALUE rtx attached to it instead of generating
a new one again and again.

2003-07-16  Jakub Jelinek  <jakub@redhat.com>

	* cselib.c (unknown_addr, discard_callback, discard_callback_arg): New
	variables.
	(unchain_one_value): Call discard_callback.
	(cselib_init): Initialize discard_callback{,_arg}.
	(cselib_register_discard_callback, cselib_unknown_addr): New
	functions.
	* cselib.h (cselib_discard_callback): New type.
	(cselib_register_discard_callback, cselib_unknown_addr): New
	prototypes.
	* sched-deps.c (sched_analyze_insn): Don't walk pending_write_mems
	when not neccessary.
	(sched_discard_callback): New function.
	(sched_analyze): Register sched_discard_callback with cselib.

--- gcc/cselib.c.jj	2003-06-10 18:29:24.000000000 -0400
+++ gcc/cselib.c	2003-07-16 09:52:31.000000000 -0400
@@ -1,6 +1,6 @@
 /* Common subexpression elimination library for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -123,9 +123,16 @@ static GTY((deletable (""))) cselib_val 
 static GTY((deletable (""))) struct elt_list *empty_elt_lists;
 static GTY((deletable (""))) struct elt_loc_list *empty_elt_loc_lists;
 
+/* An unknown VALUE to be used which replaces any VALUE after it has
+   been garbage collected as useless.  */
+static GTY(()) rtx unknown_addr;
+
 /* Set by discard_useless_locs if it deleted the last location of any
    value.  */
 static int values_became_useless;
+
+static cselib_discard_callback discard_callback;
+static void *discard_callback_arg;
 
 
 /* Allocate a struct elt_list and fill in its two elements with the
@@ -205,6 +212,9 @@ unchain_one_value (v)
   while (v->addr_list)
     unchain_one_elt_list (&v->addr_list);
 
+  if (discard_callback)
+    (*discard_callback) (discard_callback_arg, v->u.val_rtx);
+
   v->u.next_free = empty_vals;
   empty_vals = v;
 }
@@ -1400,6 +1410,9 @@ cselib_init ()
   if (! callmem)
     callmem = gen_rtx_MEM (BLKmode, const0_rtx);
 
+  discard_callback = NULL;
+  discard_callback_arg = NULL;
+
   cselib_nregs = max_reg_num ();
   if (reg_values_old != NULL && VARRAY_SIZE (reg_values_old) >= cselib_nregs)
     {
@@ -1419,6 +1432,31 @@ cselib_init ()
   cselib_current_insn_in_libcall = false;
 }
 
+/* Register a callback for freeing useless VALUEs.  */
+
+void
+cselib_register_discard_callback (callback, arg)
+     cselib_discard_callback callback;
+     void *arg;
+{
+  discard_callback = callback;
+  discard_callback_arg = arg;
+}
+
+/* Return a VALUE that can replace a VALUE which became
+   useless and is to be discarded.  */
+
+rtx
+cselib_unknown_addr ()
+{
+  if (! unknown_addr)
+    {
+      cselib_val *v = new_cselib_val (-1, Pmode);
+      unknown_addr = v->u.val_rtx;
+    }
+  return unknown_addr;
+}
+
 /* Called when the current user is done with cselib.  */
 
 void
--- gcc/cselib.h.jj	2003-03-19 07:58:30.000000000 -0500
+++ gcc/cselib.h	2003-07-16 10:30:43.000000000 -0400
@@ -1,6 +1,6 @@
 /* Common subexpression elimination for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999 Free Software Foundation, Inc.
+   1999, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -60,6 +60,8 @@ struct elt_list GTY(())
   cselib_val *elt;
 };
 
+typedef void (*cselib_discard_callback) PARAMS ((void *, rtx));
+
 extern cselib_val *cselib_lookup	PARAMS ((rtx, enum machine_mode, int));
 extern void cselib_update_varray_sizes	PARAMS ((void));
 extern void cselib_init			PARAMS ((void));
@@ -68,3 +70,6 @@ extern void cselib_process_insn		PARAMS 
 extern int rtx_equal_for_cselib_p	PARAMS ((rtx, rtx));
 extern int references_value_p		PARAMS ((rtx, int));
 extern rtx cselib_subst_to_values	PARAMS ((rtx));
+extern void cselib_register_discard_callback
+     PARAMS ((cselib_discard_callback, void *));
+extern rtx cselib_unknown_addr		PARAMS ((void));
--- gcc/sched-deps.c.jj	2003-03-19 07:58:38.000000000 -0500
+++ gcc/sched-deps.c	2003-07-16 10:33:29.000000000 -0400
@@ -1,7 +1,7 @@
 /* Instruction scheduling pass.  This file computes dependencies between
    instructions.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -89,6 +89,7 @@ static void sched_analyze_1 PARAMS ((str
 static void sched_analyze_2 PARAMS ((struct deps *, rtx, rtx));
 static void sched_analyze_insn PARAMS ((struct deps *, rtx, rtx, rtx));
 static rtx group_leader PARAMS ((rtx));
+static void sched_discard_callback PARAMS ((void *, rtx));
 
 static rtx get_condition PARAMS ((rtx));
 static int conditions_mutex_p PARAMS ((rtx, rtx));
@@ -989,12 +990,10 @@ sched_analyze_insn (deps, x, insn, loop_
 	     the result is needed by the above register used mask.  */
 
 	  pending = deps->pending_write_insns;
-	  pending_mem = deps->pending_write_mems;
 	  while (pending)
 	    {
 	      add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
 	      pending = XEXP (pending, 1);
-	      pending_mem = XEXP (pending_mem, 1);
 	    }
 
 	  pending = deps->pending_read_insns;
@@ -1226,6 +1225,45 @@ sched_analyze_insn (deps, x, insn, loop_
     }
 }
 
+/* Called when cselib is about to discard a VALUE
+   (which can be reused from that point onwards).
+   This function replaces such VALUEs with a special
+   VALUE which can stand for any address.
+   sched_analyze needs to ensure it never calls
+   *_dependence functions with this VALUE in both
+   MEM expressions.  */
+
+static void
+sched_discard_callback (arg, value)
+     void *arg;
+     rtx value;
+{
+  struct deps *deps = (struct deps *) arg;
+  rtx pending_mem;
+
+  pending_mem = deps->pending_read_mems;
+  while (pending_mem)
+    {
+      rtx mem = XEXP (pending_mem, 0);
+
+      if (XEXP (mem, 0) == value)
+	XEXP (mem, 0) = cselib_unknown_addr ();
+
+      pending_mem = XEXP (pending_mem, 1);
+    }
+
+  pending_mem = deps->pending_write_mems;
+  while (pending_mem)
+    {
+      rtx mem = XEXP (pending_mem, 0);
+
+      if (XEXP (mem, 0) == value)
+	XEXP (mem, 0) = cselib_unknown_addr ();
+
+      pending_mem = XEXP (pending_mem, 1);
+    }
+}
+
 /* Analyze every insn between HEAD and TAIL inclusive, creating LOG_LINKS
    for every dependency.  */
 
@@ -1238,7 +1276,10 @@ sched_analyze (deps, head, tail)
   rtx loop_notes = 0;
 
   if (current_sched_info->use_cselib)
-    cselib_init ();
+    {
+      cselib_init ();
+      cselib_register_discard_callback (sched_discard_callback, deps);
+    }
 
   for (insn = head;; insn = NEXT_INSN (insn))
     {


	Jakub


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