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]

Patches for the 2.95 branch


I'll apply the following patches, one by one, to the 2.95 branch.  I've
bootstrapped this set on i686-linux, sparc-sun-solaris2.5.1 and alphaev6-linux
and regression tested it on the same targets against the current testsuite.

These patches are mostly taken from Franz Sirl's patchkit.


Bernd

	2000-09-01  Jim Wilson  <wilson@cygnus.com>
	* loop.c (check_final_value): Check for biv use before checking for
	giv use.  Check for both biv and giv uses.  Always set last_giv_use
	if there is a giv use.

	Based on a patch from Geoff Keating <geoffk@redhat.com>:
	* loop.c (basic_induction_var): If a REG is set from something
	that is not a biv, then the REG is not a biv.  Even if it is
	earlier set from something that is a biv.

	2000-09-29  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
	* loop.c (check_final_value): A GIV is not replaceable if used
	before set.

	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.

	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-11-24  Bernd Schmidt  <bernds@redhat.co.uk>
	* reload1.c (conflicts_with_override): New function.
	(emit_input_reload_insns): Use it to tighten test for validity
	of substituting into output of previous insn.

	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.

	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.

	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.

	2000-02-26  Geoff Keating  <geoffk@cygnus.com>
	* reload1.c (do_output_reload): Check reg_reloaded_valid before
	looking at reg_reloaded_contents.

	Thu Apr 13 19:39:56 2000  Clinton Popetz  <cpopetz@cygnus.com>
	* emit-rtl.c (try_split): Avoid infinite loop if the split
	results in a sequence that contains the original insn.

	1999-12-14  Bernd Schmidt  <bernds@cygnus.co.uk>
	* combine.c (combine_simplify_rtx): Don't make shared rtl.
	(simplify_logical): Likewise.

	Sat May 20 07:27:35 2000  Alexandre Oliva  <aoliva@cygnus.com>
	* fold-const.c (make_range): Handle degenerated intervals.
	Fixes c-torture/execute/991221-1.c

	2000-07-15  Michael Meissner  <meissner@redhat.com>
	* fold-const.c (fold): When optimizing FOO++ == CONST into ++FOO
	== CONST + INCREMENT, don't overwrite the tree node for FOO++,
	create a new node instead.

	2000-01-01  Bernd Schmidt  <bernds@cygnus.co.uk>
	* expmed.c (emit_store_flag): Prevent losing a pending stack
	adjust the same way we prevent losing queued increments.

Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.62.4.1
diff -u -p -r1.62.4.1 combine.c
--- gcc/combine.c	1999/10/18 07:52:32	1.62.4.1
+++ gcc/combine.c	2000/11/29 15:16:54
@@ -4015,7 +4015,8 @@ simplify_rtx (x, op0_mode, last, in_dest
 			 gen_binary (MULT, mode,
 				     XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
 			 gen_binary (MULT, mode,
-				     XEXP (XEXP (x, 0), 1), XEXP (x, 1))));
+				     XEXP (XEXP (x, 0), 1),
+				     copy_rtx (XEXP (x, 1)))));
 
 	  if (GET_CODE (x) != MULT)
 	    return x;
@@ -4954,7 +4955,8 @@ simplify_logical (x, last)
 	  x = apply_distributive_law
 	    (gen_binary (GET_CODE (op0), mode,
 			 gen_binary (AND, mode, XEXP (op0, 0), op1),
-			 gen_binary (AND, mode, XEXP (op0, 1), op1)));
+			 gen_binary (AND, mode, XEXP (op0, 1),
+				     copy_rtx (op1))));
 	  if (GET_CODE (x) != AND)
 	    return x;
 	}
@@ -4963,7 +4965,8 @@ simplify_logical (x, last)
 	return apply_distributive_law
 	  (gen_binary (GET_CODE (op1), mode,
 		       gen_binary (AND, mode, XEXP (op1, 0), op0),
-		       gen_binary (AND, mode, XEXP (op1, 1), op0)));
+		       gen_binary (AND, mode, XEXP (op1, 1),
+				   copy_rtx (op0))));
 
       /* Similarly, taking advantage of the fact that
 	 (and (not A) (xor B C)) == (xor (ior A B) (ior A C))  */
@@ -4972,13 +4975,14 @@ simplify_logical (x, last)
 	return apply_distributive_law
 	  (gen_binary (XOR, mode,
 		       gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
-		       gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1))));
+		       gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
+				   XEXP (op1, 1))));
 							    
       else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
 	return apply_distributive_law
 	  (gen_binary (XOR, mode,
 		       gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)),
-		       gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1))));
+		       gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
       break;
 
     case IOR:
@@ -5004,7 +5008,8 @@ simplify_logical (x, last)
 	  x = apply_distributive_law
 	    (gen_binary (AND, mode,
 			 gen_binary (IOR, mode, XEXP (op0, 0), op1),
-			 gen_binary (IOR, mode, XEXP (op0, 1), op1)));
+			 gen_binary (IOR, mode, XEXP (op0, 1),
+				     copy_rtx (op1))));
 
 	  if (GET_CODE (x) != IOR)
 	    return x;
@@ -5015,7 +5020,8 @@ simplify_logical (x, last)
 	  x = apply_distributive_law
 	    (gen_binary (AND, mode,
 			 gen_binary (IOR, mode, XEXP (op1, 0), op0),
-			 gen_binary (IOR, mode, XEXP (op1, 1), op0)));
+			 gen_binary (IOR, mode, XEXP (op1, 1),
+				     copy_rtx (op0))));
 
 	  if (GET_CODE (x) != IOR)
 	    return x;
Index: gcc/emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.59.4.4
diff -u -p -r1.59.4.4 emit-rtl.c
--- gcc/emit-rtl.c	1999/08/11 07:28:52	1.59.4.4
+++ gcc/emit-rtl.c	2000/11/29 15:16:59
@@ -2359,10 +2359,18 @@ try_split (pat, trial, last)
 	 it, in turn, will be split (SFmode on the 29k is an example).  */
       if (GET_CODE (seq) == SEQUENCE)
 	{
+	  int i;
+
+	  /* Avoid infinite loop if any insn of the result matches 
+	     the original pattern.  */
+	  for (i = 0; i < XVECLEN (seq, 0); i++)
+  	    if (GET_CODE (XVECEXP (seq, 0, i)) == INSN 
+		&& rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat))
+  	      return trial;
+
 	  /* If we are splitting a JUMP_INSN, look for the JUMP_INSN in
 	     SEQ and copy our JUMP_LABEL to it.  If JUMP_LABEL is non-zero,
 	     increment the usage count so we don't delete the label.  */
-	  int i;
 
 	  if (GET_CODE (trial) == JUMP_INSN)
 	    for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
Index: gcc/expmed.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expmed.c,v
retrieving revision 1.31.4.1
diff -u -p -r1.31.4.1 expmed.c
--- gcc/expmed.c	1999/06/28 03:09:17	1.31.4.1
+++ gcc/expmed.c	2000/11/29 15:17:00
@@ -4194,9 +4194,11 @@ emit_store_flag (target, code, op0, op1,
 	 comparison and then the scc insn.
 
 	 compare_from_rtx may call emit_queue, which would be deleted below
-	 if the scc insn fails.  So call it ourselves before setting LAST.  */
+	 if the scc insn fails.  So call it ourselves before setting LAST.
+	 Likewise for do_pending_stack_adjust.  */
 
       emit_queue ();
+      do_pending_stack_adjust ();
       last = get_last_insn ();
 
       comparison
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fold-const.c,v
retrieving revision 1.64.4.6
diff -u -p -r1.64.4.6 fold-const.c
--- gcc/fold-const.c	1999/12/24 18:05:27	1.64.4.6
+++ gcc/fold-const.c	2000/11/29 15:17:05
@@ -3259,8 +3259,17 @@ make_range (exp, pin_p, plow, phigh)
 	      low = range_binop (PLUS_EXPR, type, n_high, 0,
 				 integer_one_node, 0);
 	      high = range_binop (MINUS_EXPR, type, n_low, 0,
-				 integer_one_node, 0);
-	      in_p = ! in_p;
+				  integer_one_node, 0);
+
+	      /* If the range is of the form +/- [ x+1, x ], we won't
+		 be able to normalize it.  But then, it represents the
+		 whole range or the empty set, so make it +/- [ -, - ].
+	      */
+	      if (tree_int_cst_equal (n_low, low)
+		  && tree_int_cst_equal (n_high, high))
+		low = high = 0;
+	      else
+		in_p = ! in_p;
 	    }
 	  else
 	    low = n_low, high = n_high;
@@ -5625,8 +5634,16 @@ fold (expr) 
 		tree newconst
 		  = fold (build (PLUS_EXPR, TREE_TYPE (varop),
 				 constop, TREE_OPERAND (varop, 1)));
-		TREE_SET_CODE (varop, PREINCREMENT_EXPR);
 
+		/* Do not overwrite the current varop to be a preincrement,
+		   create a new node so that we won't confuse our caller who
+		   might create trees and throw them away, reusing the
+		   arguments that they passed to build.  This shows up in
+		   the THEN or ELSE parts of ?: being postincrements.  */
+		varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop),
+			       TREE_OPERAND (varop, 0),
+			       TREE_OPERAND (varop, 1));
+
 		/* If VAROP is a reference to a bitfield, we must mask
 		   the constant by the width of the field.  */
 		if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
@@ -5669,9 +5686,9 @@ fold (expr) 
 		  }
 							 
 
-		t = build (code, type, TREE_OPERAND (t, 0),
-			   TREE_OPERAND (t, 1));
-		TREE_OPERAND (t, constopnum) = newconst;
+		t = build (code, type,
+			   (constopnum == 0) ? newconst : varop,
+			   (constopnum == 1) ? newconst : varop);
 		return t;
 	      }
 	  }
@@ -5684,7 +5701,15 @@ fold (expr) 
 		tree newconst
 		  = fold (build (MINUS_EXPR, TREE_TYPE (varop),
 				 constop, TREE_OPERAND (varop, 1)));
-		TREE_SET_CODE (varop, PREDECREMENT_EXPR);
+
+		/* Do not overwrite the current varop to be a predecrement,
+		   create a new node so that we won't confuse our caller who
+		   might create trees and throw them away, reusing the
+		   arguments that they passed to build.  This shows up in
+		   the THEN or ELSE parts of ?: being postdecrements.  */
+		varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop),
+			       TREE_OPERAND (varop, 0),
+			       TREE_OPERAND (varop, 1));
 
 		if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
 		    && DECL_BIT_FIELD(TREE_OPERAND
@@ -5723,9 +5748,9 @@ fold (expr) 
 		  }
 							 
 
-		t = build (code, type, TREE_OPERAND (t, 0),
-			   TREE_OPERAND (t, 1));
-		TREE_OPERAND (t, constopnum) = newconst;
+		t = build (code, type,
+			   (constopnum == 0) ? newconst : varop,
+			   (constopnum == 1) ? newconst : varop);
 		return t;
 	      }
 	  }
Index: gcc/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
--- gcc/loop.c	2000/03/08 04:47:42	1.156.4.12
+++ gcc/loop.c	2000/11/29 15:17:10
@@ -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;
 
@@ -5678,6 +5692,7 @@ check_final_value (v, loop_start, loop_e
         or all uses follow that insn in the same basic block),
      - its final value can be calculated (this condition is different
        than the one above in record_giv)
+     - it's not used before it's set
      - no assignments to the biv occur during the giv's lifetime.  */
 
 #if 0
@@ -5689,7 +5704,7 @@ check_final_value (v, loop_start, loop_e
   if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations))
       && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
     {
-      int biv_increment_seen = 0;
+      int biv_increment_seen = 0, before_giv_insn = 0;
       rtx p = v->insn;
       rtx last_giv_use;
 
@@ -5719,26 +5734,35 @@ check_final_value (v, loop_start, loop_e
 	{
 	  p = NEXT_INSN (p);
 	  if (p == loop_end)
-	    p = NEXT_INSN (loop_start);
+	    {
+	      before_giv_insn = 1;
+	      p = NEXT_INSN (loop_start);
+	    }
 	  if (p == v->insn)
 	    break;
 
 	  if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
 	      || GET_CODE (p) == CALL_INSN)
 	    {
-	      if (biv_increment_seen)
+	      /* It is possible for the BIV increment to use the GIV if we
+		 have a cycle.  Thus we must be sure to check each insn for
+		 both BIV and GIV uses, and we must check for BIV uses
+		 first.  */
+
+	      if (! biv_increment_seen
+		  && reg_set_p (v->src_reg, PATTERN (p)))
+		biv_increment_seen = 1;
+
+	      if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
 		{
-		  if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
+		  if (biv_increment_seen || before_giv_insn)
 		    {
 		      v->replaceable = 0;
 		      v->not_replaceable = 1;
 		      break;
 		    }
+		  last_giv_use = p;
 		}
-	      else if (reg_set_p (v->src_reg, PATTERN (p)))
-		biv_increment_seen = 1;
-	      else if (reg_mentioned_p (v->dest_reg, PATTERN (p)))
-		last_giv_use = p;
 	    }
 	}
       
@@ -5983,6 +6007,7 @@ basic_induction_var (x, mode, dest_reg, 
       insn = p;
       while (1)
 	{
+	  rtx dest;
 	  do {
 	    insn = PREV_INSN (insn);
 	  } while (insn && GET_CODE (insn) == NOTE
@@ -5994,20 +6019,26 @@ basic_induction_var (x, mode, dest_reg, 
 	  if (set == 0)
 	    break;
 
-	  if ((SET_DEST (set) == x
-	       || (GET_CODE (SET_DEST (set)) == SUBREG
-		   && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
-		       <= UNITS_PER_WORD)
-		   && (GET_MODE_CLASS (GET_MODE (SET_DEST (set)))
-		       == MODE_INT)
-		   && SUBREG_REG (SET_DEST (set)) == x))
-	      && basic_induction_var (SET_SRC (set),
-				      (GET_MODE (SET_SRC (set)) == VOIDmode
-				       ? GET_MODE (x)
-				       : GET_MODE (SET_SRC (set))),
-				      dest_reg, insn,
-				      inc_val, mult_val, location))
-	    return 1;
+	  dest = SET_DEST (set);
+	  if (dest == x
+	      || (GET_CODE (dest) == SUBREG
+		  && (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD)
+		  && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
+		  && SUBREG_REG (dest) == x))
+	    return basic_induction_var (SET_SRC (set),
+					(GET_MODE (SET_SRC (set)) == VOIDmode
+					 ? GET_MODE (x)
+					 : GET_MODE (SET_SRC (set))),
+					dest_reg, insn,
+					inc_val, mult_val, location);
+
+	  while (GET_CODE (dest) == SIGN_EXTRACT
+		 || GET_CODE (dest) == ZERO_EXTRACT
+		 || GET_CODE (dest) == SUBREG
+		 || GET_CODE (dest) == STRICT_LOW_PART)
+	    dest = XEXP (dest, 0);
+	  if (dest == x)
+	    break;
 	}
       /* ... fall through ...  */
 
@@ -8154,6 +8185,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: gcc/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
--- gcc/reload.c	1999/07/14 22:29:48	1.71.4.2
+++ gcc/reload.c	2000/11/29 15:17:12
@@ -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: gcc/reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.17
diff -u -p -r1.17 reload.h
--- gcc/reload.h	1998/12/16 20:57:55	1.17
+++ gcc/reload.h	2000/11/29 15:17:12
@@ -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: gcc/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
--- gcc/reload1.c	2000/03/08 05:02:46	1.145.4.2
+++ gcc/reload1.c	2000/11/29 15:17:15
@@ -423,6 +423,7 @@ static int reload_reg_free_for_value_p	P
 static int reload_reg_reaches_end_p	PROTO((int, int, enum reload_type));
 static int allocate_reload_reg		PROTO((struct insn_chain *, int, int,
 					       int));
+static int conflicts_with_override	PROTO((rtx));
 static void choose_reload_regs		PROTO((struct insn_chain *));
 static void merge_assigned_reloads	PROTO((rtx));
 static void emit_reload_insns		PROTO((struct insn_chain *));
@@ -4518,7 +4519,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 +4581,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 +4805,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 +5139,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 +5207,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 +5218,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 +5245,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 +5338,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 +5351,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 +5380,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,9 +5405,29 @@ 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;
 }
 
+/* Determine whether the reload reg X overlaps any rtx'es used for
+   overriding inheritance.  Return nonzero if so.  */
+
+static int
+conflicts_with_override (x)
+     rtx x;
+{
+  int i;
+  for (i = 0; i < n_reloads; i++)
+    if (reload_override_in[i]
+	&& reg_overlap_mentioned_p (x, reload_override_in[i]))
+      return 1;
+  return 0;
+}
+
 /* Find a spill register to use as a reload register for reload R.
    LAST_RELOAD is non-zero if this is the last reload for the insn being
    processed.
@@ -5669,7 +5705,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.
@@ -6799,6 +6835,7 @@ emit_reload_insns (chain)
 		   && dead_or_set_p (insn, old)
 		   /* This is unsafe if some other reload
 		      uses the same reg first.  */
+		   && ! conflicts_with_override (reloadreg)
 		   && reload_reg_free_for_value_p (REGNO (reloadreg),
 						   reload_opnum[j],
 						   reload_when_needed[j], 
@@ -7112,7 +7149,8 @@ emit_reload_insns (chain)
 	    /* We don't need to test full validity of last_regno for
 	       inherit here; we only want to know if the store actually
 	       matches the pseudo.  */
-	    if (reg_reloaded_contents[last_regno] == pseudo_no
+	    if (TEST_HARD_REG_BIT (reg_reloaded_valid, last_regno)
+		&& reg_reloaded_contents[last_regno] == pseudo_no
 		&& spill_reg_store[last_regno]
 		&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
 	      delete_output_reload (insn, j, last_regno);


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