This is the mail archive of the gcc@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]

Re: State of maturity for gcc 2.95.3 and gcc 2.96


On Sun, 15 Oct 2000, Franz Sirl wrote:

> On Sat, 14 Oct 2000, Bernd Schmidt wrote:
> > On Sat, 14 Oct 2000, Toon Moene wrote:
> > > Bernd Schmidt wrote:
> > > > On Thu, 12 Oct 2000, David O'Brien wrote:
> > > > > Since 3.0 is still quite some time away, can 2.95.3 finally be
> > > > > released? Some very major bugs have been fixed, but commits have been
> > > > > very cautious to that branch.  I'd almost imagine all that would be
> > > > > needed is to do a checkout and tar it up.
> > > >
> > > > You'd want to fix at least one new bug introduced in reload...
> > >
> > > This would indicate that our process to update the release branch is not
> > > correct.
> >
> > No, it indicates that not everything that looks like an obvious bug fix
> > is necessarily correct.
> >
> > More specifically, this patch
> >         * reload1.c (reload_reg_free_for_value_p): Don't use a register
> >         that is in reload_reg_used.
> > is incorrect; there's a correct solution for the bug in the current
> > sources.
> 
> Could you be a bit more specific on what patch is the correct bugfix so I can 
> find it in the mainline and/or lists? I'll look into backporting it to the 
> gcc-2_95-branch then.

Here's a set of patches that may be helpful.  I did a diff between the current
2.95 reload and loop code and tried to figure out patches I remembered or which
seemed obvious, then I backported those.
Off-hand, I can think of a few more patches that may be worthwhile.  Better to
test this set thoroughly first, though.


Bernd

Wed Oct 27 03:09:23 1999  J"orn Rennecke <amylaar@redhat.co.uk>

	* reload.h (earlyclobber_operand_p): Declare.
	* reload.c (earlyclobber_operand_p): Don't declare.  No longer static.
	* reload1.c (reload_reg_free_for_value_p):  RELOAD_OTHER reloads with
	an earlyclobbered output conflict with RELOAD_INPUT reloads - handle
	case where the RELOAD_OTHER reload is new.  Use earlyclobber_operand_p.

2000-01-12  Bernd Schmidt  <bernds@redhat.co.uk>

	* reload1.c (reload_reg_unavailable): New static variable.
	(reload_reg_free_p): Test it.
	(reload_reg_free_for_value_p): Test it instead of
	reload_reg_used.
	(choose_reload_regs_init): Compute it.

Sun Oct 10 13:28:48 1999  Bernd Schmidt  <bernds@redhat.co.uk>

	* loop.c (find_and_verify_loops): When looking for a BARRIER, don't
	use one before a jump table.

Thu Jul  6 18:30:36 2000  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* reload.c (push_reload): When seeing if can reuse a register,
	check extra registers against widest of INMODE and OUTMODE.

1999-11-29  Bernd Schmidt  <bernds@redhat.co.uk>

	* reload.c (push_reload): When looking for a register to put into
	reg_rtx, make sure all hard regs in a multi-reg register are in the
	right class and nonfixed.

1999-11-29  Joern Rennecke  <amylaar@redhat.co.uk>

	* reload1.c (reloads_conflict): Reverse test comparing operand
	numbers when testing for conflict between output/outaddr reloads.

2000-07-12  Richard Henderson  <rth@redhat.com>

	* reload.c (push_secondary_reload): Make sure to add the new
	reload at the end, after acquiring secondary memory.

Fri Jul  9 10:48:28 1999  Bernd Schmidt  <bernds@redhat.co.uk>

	* loop.c (check_dbra_loop): When reversing a loop, delete all
	REG_EQUAL notes referencing the reversed biv except those which are
	for a giv based on it.

2000-09-14  Alexandre Oliva  <aoliva@redhat.com>, Bernd Schmidt  <bernds@redhat.co.uk>

	* reload.c (find_reloads_address_1): Generate reloads for auto_inc
	pseudos that refer to the original pseudos, not only to their
	equivalent memory locations.

2000-09-18  Bernd Schmidt  <bernds@redhat.co.uk>

	* reload1.c (forget_old_reloads_1): If a hard reg is stored, clear
	its entry in spill_reg_store.

Tue Oct 26 00:41:54 1999  Bernd Schmidt  <bernds@cygnus.co.uk>

	* reload1.c (reload_reg_free_for_value_p): Show
	RELOAD_FOR_OTHER_ADDRESS reloads can conflict with RELOAD_OTHER
	reloads.

Index: loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.156.4.12
diff -u -p -r1.156.4.12 loop.c
--- loop.c	2000/03/08 04:47:42	1.156.4.12
+++ loop.c	2000/10/13 12:33:41
@@ -2829,16 +2829,30 @@ find_and_verify_loops (f)
 		rtx target
 		  = JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn ();
 		int target_loop_num = uid_loop_num[INSN_UID (target)];
-		rtx loc;
+		rtx loc, loc2;
 
 		for (loc = target; loc; loc = PREV_INSN (loc))
 		  if (GET_CODE (loc) == BARRIER
+		      /* Don't move things inside a tablejump.  */
+		      && ((loc2 = next_nonnote_insn (loc)) == 0
+			  || GET_CODE (loc2) != CODE_LABEL
+			  || (loc2 = next_nonnote_insn (loc2)) == 0
+			  || GET_CODE (loc2) != JUMP_INSN
+			  || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
+			      && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
 		      && uid_loop_num[INSN_UID (loc)] == target_loop_num)
 		    break;
 
 		if (loc == 0)
 		  for (loc = target; loc; loc = NEXT_INSN (loc))
 		    if (GET_CODE (loc) == BARRIER
+			/* Don't move things inside a tablejump.  */
+			&& ((loc2 = next_nonnote_insn (loc)) == 0
+			    || GET_CODE (loc2) != CODE_LABEL
+			    || (loc2 = next_nonnote_insn (loc2)) == 0
+			    || GET_CODE (loc2) != JUMP_INSN
+			    || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
+				&& GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
 			&& uid_loop_num[INSN_UID (loc)] == target_loop_num)
 		      break;
 
@@ -8154,6 +8168,40 @@ check_dbra_loop (loop_end, insn_count, l
 		    }
 		  bl->nonneg = 1;
 		}
+
+	      /* No insn may reference both the reversed and another biv or it
+		 will fail (see comment near the top of the loop reversal
+		 code).
+		 Earlier on, we have verified that the biv has no use except
+		 counting, or it is the only biv in this function.
+		 However, the code that computes no_use_except_counting does
+		 not verify reg notes.  It's possible to have an insn that
+		 references another biv, and has a REG_EQUAL note with an
+		 expression based on the reversed biv.  To avoid this case,
+		 remove all REG_EQUAL notes based on the reversed biv
+		 here.  */
+	      for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
+		if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+		  {
+		    rtx *pnote;
+		    rtx set = single_set (p);
+		    /* If this is a set of a GIV based on the reversed biv, any
+		       REG_EQUAL notes should still be correct.  */
+		    if (! set
+			|| GET_CODE (SET_DEST (set)) != REG
+			|| (size_t) REGNO (SET_DEST (set)) >= reg_iv_type->num_elements
+			|| REG_IV_TYPE (REGNO (SET_DEST (set))) != GENERAL_INDUCT
+			|| REG_IV_INFO (REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
+		      for (pnote = &REG_NOTES (p); *pnote;)
+			{
+			  if (REG_NOTE_KIND (*pnote) == REG_EQUAL
+			      && reg_mentioned_p (regno_reg_rtx[bl->regno],
+						  XEXP (*pnote, 0)))
+			    *pnote = XEXP (*pnote, 1);
+			  else
+			    pnote = &XEXP (*pnote, 1);
+			}
+		  }
 
 	      /* Mark that this biv has been reversed.  Each giv which depends
 		 on this biv, and which is also live past the end of the loop
Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.71.4.2
diff -u -p -r1.71.4.2 reload.c
--- reload.c	1999/07/14 22:29:48	1.71.4.2
+++ reload.c	2000/10/13 12:33:43
@@ -322,7 +322,6 @@ static int find_reusable_reload	PROTO((r
 static rtx find_dummy_reload	PROTO((rtx, rtx, rtx *, rtx *,
 				       enum machine_mode, enum machine_mode,
 				       enum reg_class, int, int));
-static int earlyclobber_operand_p PROTO((rtx));
 static int hard_reg_set_here_p	PROTO((int, int, rtx));
 static struct decomposition decompose PROTO((rtx));
 static int immune_p		PROTO((rtx, rtx, struct decomposition));
@@ -591,7 +590,13 @@ push_secondary_reload (in_p, x, opnum, o
 
       if (in_p && icode == CODE_FOR_nothing
 	  && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
-	get_secondary_mem (x, reload_mode, opnum, type);
+	{
+	  get_secondary_mem (x, reload_mode, opnum, type);
+
+	  /* We may have just added new reloads.  Make sure we add
+	     the new reload at the end.  */
+	  s_reload = n_reloads;
+	}
 #endif
 
       /* We need to make a new secondary reload for this register class.  */
@@ -1529,12 +1534,23 @@ push_reload (in, out, inloc, outloc, cla
 	    && GET_MODE_SIZE (inmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
 	    && HARD_REGNO_MODE_OK (regno, inmode)
 	    && GET_MODE_SIZE (outmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
-	    && HARD_REGNO_MODE_OK (regno, outmode)
-	    && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
-	    && !fixed_regs[regno])
+	    && HARD_REGNO_MODE_OK (regno, outmode))
 	  {
-	    reload_reg_rtx[i] = gen_rtx_REG (inmode, regno);
-	    break;
+	    unsigned int offs;
+	    unsigned int nregs = MAX (HARD_REGNO_NREGS (regno, inmode),
+				      HARD_REGNO_NREGS (regno, outmode));
+
+	    for (offs = 0; offs < nregs; offs++)
+	      if (fixed_regs[regno + offs]
+		  || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+					  regno + offs))
+		break;
+
+	    if (offs == nregs)
+	      {
+		reload_reg_rtx[i] = gen_rtx_REG (inmode, regno);
+		break;
+	      }
 	  }
     }
 
@@ -1989,7 +2005,7 @@ find_dummy_reload (real_in, real_out, in
 
 /* Return 1 if X is an operand of an insn that is being earlyclobbered.  */
 
-static int
+int
 earlyclobber_operand_p (x)
      rtx x;
 {
@@ -5346,20 +5362,18 @@ find_reloads_address_1 (mode, x, context
 			&& (*insn_operand_predicate[icode][0]) (equiv, Pmode)
 			&& (*insn_operand_predicate[icode][1]) (equiv, Pmode)))
 		{
-		  loc = &XEXP (x, 0);
+		  /* We use the original pseudo for loc, so that
+		     emit_reload_insns() knows which pseudo this
+		     reload refers to and updates the pseudo rtx, not
+		     its equivalent memory location, as well as the
+		     corresponding entry in reg_last_reload_reg.  */
+		  loc = &XEXP (x_orig, 0);
 		  x = XEXP (x, 0);
 		  reloadnum
 		    = push_reload (x, x, loc, loc,
 				   (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
 				    GET_MODE (x), GET_MODE (x), 0, 0,
 				    opnum, RELOAD_OTHER);
-
-		  /* If we created a new MEM based on reg_equiv_mem[REGNO], then
-		     LOC above is part of the new MEM, not the MEM in INSN.
-
-		     We must also replace the address of the MEM in INSN.  */
-		  if (&XEXP (x_orig, 0) != loc)
-		    push_replacement (&XEXP (x_orig, 0), reloadnum, VOIDmode);
 
 		}
 	      else
Index: reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.17
diff -u -p -r1.17 reload.h
--- reload.h	1998/12/16 20:57:55	1.17
+++ reload.h	2000/10/13 12:33:43
@@ -342,3 +342,5 @@ extern void save_call_clobbered_regs PRO
 
 /* Replace (subreg (reg)) with the appropriate (reg) for any operands.  */
 extern void cleanup_subreg_operands PROTO ((rtx));
+
+extern int earlyclobber_operand_p PROTO((rtx));
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.145.4.2
diff -u -p -r1.145.4.2 reload1.c
--- reload1.c	2000/03/08 05:02:46	1.145.4.2
+++ reload1.c	2000/10/13 12:33:46
@@ -4518,7 +4518,10 @@ forget_old_reloads_1 (x, ignored)
 	   reload reg in the current instruction.  */
 	if (n_reloads == 0
 	    || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
-	  CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+	  {
+	    CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+	    spill_reg_store[regno + i] = 0;
+	  }
     }
 
   /* Since value of X has changed,
@@ -4577,6 +4580,8 @@ reload_reg_class_lower (r1p, r2p)
 /* The following HARD_REG_SETs indicate when each hard register is
    used for a reload of various parts of the current insn.  */
 
+/* If reg is unavailable for all reloads.  */
+static HARD_REG_SET reload_reg_unavailable;
 /* If reg is in use as a reload reg for a RELOAD_OTHER reload.  */
 static HARD_REG_SET reload_reg_used;
 /* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I.  */
@@ -4799,8 +4804,8 @@ reload_reg_free_p (regno, opnum, type)
 {
   int i;
 
-  /* In use for a RELOAD_OTHER means it's not available for anything.  */
-  if (TEST_HARD_REG_BIT (reload_reg_used, regno))
+  if (TEST_HARD_REG_BIT (reload_reg_used, regno)
+      || TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
     return 0;
 
   switch (type)
@@ -5133,7 +5138,7 @@ reloads_conflict (r1, r2)
       return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT
 	      || ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS
 		   || r2_type == RELOAD_FOR_OUTADDR_ADDRESS)
-		  && r2_opnum >= r1_opnum));
+		  && r2_opnum <= r1_opnum));
 
     case RELOAD_FOR_INSN:
       return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_OUTPUT
@@ -5201,6 +5206,10 @@ reload_reg_free_for_value_p (regno, opnu
      int ignore_address_reloads;
 {
   int time1;
+  /* Set if we see an input reload that must not share its reload register
+     with any new earlyclobber, but might otherwise share the reload
+     register with an output or input-output reload.  */
+  int check_earlyclobber = 0;
   int i;
   int copy = 0;
 
@@ -5208,7 +5217,7 @@ reload_reg_free_for_value_p (regno, opnu
      available as spill registers, including hard registers that are
      earlyclobbered in asms.  As a temporary measure, reject anything
      in reload_reg_used.  */
-  if (TEST_HARD_REG_BIT (reload_reg_used, regno))
+  if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
     return 0;
 
   if (out == const0_rtx)
@@ -5235,7 +5244,8 @@ reload_reg_free_for_value_p (regno, opnu
   switch (type)
     {
     case RELOAD_FOR_OTHER_ADDRESS:
-      time1 = 0;
+      /* RELOAD_FOR_OTHER_ADDRESS conflicts with RELOAD_OTHER reloads.  */
+      time1 = copy ? 0 : 1;
       break;
     case RELOAD_OTHER:
       time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5;
@@ -5327,6 +5337,7 @@ reload_reg_free_for_value_p (regno, opnu
 		  break;
 		case RELOAD_FOR_INPUT:
 		  time2 = reload_opnum[i] * 4 + 4;
+		  check_earlyclobber = 1;
 		  break;
 		/* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4
 		   == MAX_RECOG_OPERAND * 4  */
@@ -5339,6 +5350,7 @@ reload_reg_free_for_value_p (regno, opnu
 		  break;
 		case RELOAD_FOR_OPERAND_ADDRESS:
 		  time2 = MAX_RECOG_OPERANDS * 4 + 2;
+		  check_earlyclobber = 1;
 		  break;
 		case RELOAD_FOR_INSN:
 		  time2 = MAX_RECOG_OPERANDS * 4 + 3;
@@ -5367,6 +5379,9 @@ reload_reg_free_for_value_p (regno, opnu
 		  if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
 		    {
 		      time2 = MAX_RECOG_OPERANDS * 4 + 4;
+		      /* Earlyclobbered outputs must conflict with inputs.  */
+		      if (earlyclobber_operand_p (reload_out[i]))
+			time2 = MAX_RECOG_OPERANDS * 4 + 3;
 		      break;
 		    }
 		  time2 = 1;
@@ -5389,6 +5404,11 @@ reload_reg_free_for_value_p (regno, opnu
 	    }
 	}
     }
+
+  /* Earlyclobbered outputs must conflict with inputs.  */
+  if (check_earlyclobber && out && earlyclobber_operand_p (out))
+    return 0;
+
   return 1;
 }
 
@@ -5669,7 +5689,7 @@ choose_reload_regs (chain)
       CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
     }
 
-  IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+  COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs);
   
 #if 0  /* Not needed, now that we can always retry without inheritance.  */
   /* See if we have more mandatory reloads than spill regs.


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