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]

Re: RFA: Support separate class for base regs in REG+REG addressing


On Mon, Sep 20, 2004 at 05:06:28PM -0400, Daniel Jacobowitz wrote:
> On Mon, Sep 20, 2004 at 04:58:51PM -0400, Ian Lance Taylor wrote:
> > Daniel Jacobowitz <drow@false.org> writes:
> > 
> > > @@ -5234,7 +5226,8 @@ update_auto_inc_notes (rtx insn ATTRIBUT
> > >     is strictly valid.)
> > >  
> > >     CONTEXT = 1 means we are considering regs as index regs,
> > > -   = 0 means we are considering them as base regs.
> > > +   = 0 means we are considering them as base regs, = 2 means we
> > > +   are considering them as base regs for REG + REG.
> > >  
> > >     OPNUM and TYPE specify the purpose of any reloads made.
> > >  
> > 
> > I'm sure I'm missing something, but where does this get called with
> > CONTEXT == 2?
> 
> Um, no, you're not missing anything.  I appear to have completely
> fouled up a merge.  It's supposed to happen in the recursive call for
> REG+REG.  I am going to go investigate this - a backported version of
> the patch with that omission still fixed the original proprietay
> testcase.

The CONTEXT == 2 case only triggers if the address is of the form
[register ok for index but not base + register not ok for base].
ARM doesn't have any, so I didn't notice the omission.  Here's the
revised patch.

-- 
Daniel Jacobowitz

2004-09-20  Daniel Jacobowitz  <dan@debian.org>

	* defaults.h (REGNO_MODE_OK_FOR_BASE_P, REG_MODE_OK_FOR_BASE_P)
	(MODE_BASE_REG_REG_CLASS, REGNO_MODE_OK_FOR_REG_BASE_P)
	(REG_MODE_OK_FOR_REG_BASE_P): Provide default definitions.
	* regclass.c (record_address_regs): Remove ifdef.  Use
	REG_MODE_OK_FOR_REG_BASE_P and MODE_BASE_REG_REG_CLASS.
	* regrename.c (REG_MODE_OK_FOR_BASE_P): Remove unnecessary
	definition.
	(scan_rtx_address, replace_oldest_value_addr): Use
	REG_MODE_OK_FOR_REG_BASE_P and MODE_BASE_REG_REG_CLASS.
	* reload.c (REGNO_MODE_OK_FOR_BASE_P, REG_MODE_OK_FOR_BASE_P): Remove
	unnecessary definitions.
	(find_reloads_address_1): Support REG_MODE_OK_FOR_REG_BASE_P
	and MODE_BASE_REG_REG_CLASS.
	* config/arm/arm.h (MODE_BASE_REG_CLASS): Don't check reload_completed.
	(MODE_BASE_REG_REG_CLASS): Define.
	(REGNO_MODE_OK_FOR_REG_BASE_P): Define.
	(REG_MODE_OK_FOR_REG_BASE_P): Define.
	* doc/tm.texi (Register Classes): Document MODE_BASE_REG_REG_CLASS,
	REG_MODE_OK_FOR_REG_BASE_P, and REGNO_MODE_OK_FOR_REG_BASE_P.

Index: gcc/defaults.h
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/defaults.h,v
retrieving revision 1.156
diff -u -p -r1.156 defaults.h
--- gcc/defaults.h	10 Sep 2004 10:44:45 -0000	1.156
+++ gcc/defaults.h	20 Sep 2004 01:04:23 -0000
@@ -587,6 +587,19 @@ do { fputs (integer_asm_op (POINTER_SIZE
 #define	TARGET_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
 #endif
 
+/* Some macros can be defined by the backend in either a mode-dependent
+   or mode-independent form.  The compiler proper should only use the
+   mode-dependent form, providing VOIDmode when the mode is unknown.
+   We can't poison the macros because the backend may reference them.  */
+
+#ifndef REGNO_MODE_OK_FOR_BASE_P
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
+#endif
+
+#ifndef REG_MODE_OK_FOR_BASE_P
+#define REG_MODE_OK_FOR_BASE_P(REG, MODE) REG_OK_FOR_BASE_P (REG)
+#endif
+
 /* Determine the register class for registers suitable to be the base
    address register in a MEM.  Allow the choice to be dependent upon
    the mode of the memory access.  */
@@ -594,6 +607,20 @@ do { fputs (integer_asm_op (POINTER_SIZE
 #define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
 #endif
 
+/* Some machines require a different base register class if the index
+   is a register.  By default, assume that a base register is acceptable.  */
+#ifndef MODE_BASE_REG_REG_CLASS
+#define MODE_BASE_REG_REG_CLASS(MODE) MODE_BASE_REG_CLASS(MODE)
+#endif
+
+#ifndef REGNO_MODE_OK_FOR_REG_BASE_P
+#define REGNO_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)
+#endif
+
+#ifndef REG_MODE_OK_FOR_REG_BASE_P
+#define REG_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REG_MODE_OK_FOR_BASE_P (REGNO, MODE)
+#endif
+
 #ifndef LARGEST_EXPONENT_IS_NORMAL
 #define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0
 #endif
Index: gcc/regclass.c
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/regclass.c,v
retrieving revision 1.196
diff -u -p -r1.196 regclass.c
--- gcc/regclass.c	14 Sep 2004 22:52:38 -0000	1.196
+++ gcc/regclass.c	20 Sep 2004 01:04:26 -0000
@@ -2016,25 +2016,27 @@ record_address_regs (rtx x, enum reg_cla
 	  record_address_regs (arg0, INDEX_REG_CLASS, scale);
 
 	/* If both operands are registers but one is already a hard register
-	   of index or base class, give the other the class that the hard
-	   register is not.  */
+	   of index or reg-base class, give the other the class that the
+	   hard register is not.  */
 
-#ifdef REG_OK_FOR_BASE_P
 	else if (code0 == REG && code1 == REG
 		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
-		 && (REG_OK_FOR_BASE_P (arg0) || REG_OK_FOR_INDEX_P (arg0)))
+		 && (REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode)
+		     || REG_OK_FOR_INDEX_P (arg0)))
 	  record_address_regs (arg1,
-			       REG_OK_FOR_BASE_P (arg0)
-			       ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (VOIDmode),
+			       REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode)
+			       ? INDEX_REG_CLASS
+			       : MODE_BASE_REG_REG_CLASS (VOIDmode),
 			       scale);
 	else if (code0 == REG && code1 == REG
 		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
-		 && (REG_OK_FOR_BASE_P (arg1) || REG_OK_FOR_INDEX_P (arg1)))
+		 && (REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode)
+		     || REG_OK_FOR_INDEX_P (arg1)))
 	  record_address_regs (arg0,
-			       REG_OK_FOR_BASE_P (arg1)
-			       ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (VOIDmode),
+			       REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode)
+			       ? INDEX_REG_CLASS
+			       : MODE_BASE_REG_REG_CLASS (VOIDmode),
 			       scale);
-#endif
 
 	/* If one operand is known to be a pointer, it must be the base
 	   with the other operand the index.  Likewise if the other operand
@@ -2043,14 +2045,16 @@ record_address_regs (rtx x, enum reg_cla
 	else if ((code0 == REG && REG_POINTER (arg0))
 		 || code1 == MULT)
 	  {
-	    record_address_regs (arg0, MODE_BASE_REG_CLASS (VOIDmode), scale);
+	    record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode),
+				 scale);
 	    record_address_regs (arg1, INDEX_REG_CLASS, scale);
 	  }
 	else if ((code1 == REG && REG_POINTER (arg1))
 		 || code0 == MULT)
 	  {
 	    record_address_regs (arg0, INDEX_REG_CLASS, scale);
-	    record_address_regs (arg1, MODE_BASE_REG_CLASS (VOIDmode), scale);
+	    record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode),
+				 scale);
 	  }
 
 	/* Otherwise, count equal chances that each might be a base
@@ -2058,10 +2062,10 @@ record_address_regs (rtx x, enum reg_cla
 
 	else
 	  {
-	    record_address_regs (arg0, MODE_BASE_REG_CLASS (VOIDmode),
+	    record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode),
 				 scale / 2);
 	    record_address_regs (arg0, INDEX_REG_CLASS, scale / 2);
-	    record_address_regs (arg1, MODE_BASE_REG_CLASS (VOIDmode),
+	    record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode),
 				 scale / 2);
 	    record_address_regs (arg1, INDEX_REG_CLASS, scale / 2);
 	  }
Index: gcc/regrename.c
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/regrename.c,v
retrieving revision 1.87
diff -u -p -r1.87 regrename.c
--- gcc/regrename.c	9 Sep 2004 17:19:12 -0000	1.87
+++ gcc/regrename.c	20 Sep 2004 01:04:26 -0000
@@ -36,10 +36,6 @@
 #include "toplev.h"
 #include "obstack.h"
 
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
-
 static const char *const reg_class_names[] = REG_CLASS_NAMES;
 
 struct du_chain
@@ -524,6 +520,7 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	rtx op1 = orig_op1;
 	rtx *locI = NULL;
 	rtx *locB = NULL;
+	rtx *locB_reg = NULL;
 
 	if (GET_CODE (op0) == SUBREG)
 	  {
@@ -560,14 +557,14 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	    int index_op;
 
 	    if (REG_OK_FOR_INDEX_P (op0)
-		&& REG_MODE_OK_FOR_BASE_P (op1, mode))
+		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      index_op = 0;
 	    else if (REG_OK_FOR_INDEX_P (op1)
-		     && REG_MODE_OK_FOR_BASE_P (op0, mode))
+		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      index_op = 1;
-	    else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      index_op = 0;
-	    else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      index_op = 1;
 	    else if (REG_OK_FOR_INDEX_P (op1))
 	      index_op = 1;
@@ -575,7 +572,7 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	      index_op = 0;
 
 	    locI = &XEXP (x, index_op);
-	    locB = &XEXP (x, !index_op);
+	    locB_reg = &XEXP (x, !index_op);
 	  }
 	else if (code0 == REG)
 	  {
@@ -592,6 +589,9 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
 	if (locB)
 	  scan_rtx_address (insn, locB, MODE_BASE_REG_CLASS (mode), action, mode);
+	if (locB_reg)
+	  scan_rtx_address (insn, locB_reg, MODE_BASE_REG_REG_CLASS (mode),
+			    action, mode);
 	return;
       }
 
@@ -1415,6 +1415,7 @@ replace_oldest_value_addr (rtx *loc, enu
 	rtx op1 = orig_op1;
 	rtx *locI = NULL;
 	rtx *locB = NULL;
+	rtx *locB_reg = NULL;
 
 	if (GET_CODE (op0) == SUBREG)
 	  {
@@ -1451,14 +1452,14 @@ replace_oldest_value_addr (rtx *loc, enu
 	    int index_op;
 
 	    if (REG_OK_FOR_INDEX_P (op0)
-		&& REG_MODE_OK_FOR_BASE_P (op1, mode))
+		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      index_op = 0;
 	    else if (REG_OK_FOR_INDEX_P (op1)
-		     && REG_MODE_OK_FOR_BASE_P (op0, mode))
+		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      index_op = 1;
-	    else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      index_op = 0;
-	    else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      index_op = 1;
 	    else if (REG_OK_FOR_INDEX_P (op1))
 	      index_op = 1;
@@ -1466,7 +1467,7 @@ replace_oldest_value_addr (rtx *loc, enu
 	      index_op = 0;
 
 	    locI = &XEXP (x, index_op);
-	    locB = &XEXP (x, !index_op);
+	    locB_reg = &XEXP (x, !index_op);
 	  }
 	else if (code0 == REG)
 	  {
@@ -1486,6 +1487,10 @@ replace_oldest_value_addr (rtx *loc, enu
 	  changed |= replace_oldest_value_addr (locB,
 						MODE_BASE_REG_CLASS (mode),
 						mode, insn, vd);
+	if (locB_reg)
+	  changed |= replace_oldest_value_addr (locB_reg,
+						MODE_BASE_REG_REG_CLASS (mode),
+						mode, insn, vd);
 	return changed;
       }
 
Index: gcc/reload.c
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/reload.c,v
retrieving revision 1.255
diff -u -p -r1.255 reload.c
--- gcc/reload.c	15 Sep 2004 20:47:47 -0000	1.255
+++ gcc/reload.c	20 Sep 2004 21:25:12 -0000
@@ -108,14 +108,6 @@ a register with any other reload.  */
 #include "params.h"
 #include "target.h"
 
-#ifndef REGNO_MODE_OK_FOR_BASE_P
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
-#endif
-
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
-
 /* True if X is a constant that can be forced into the constant pool.  */
 #define CONST_POOL_OK_P(X)			\
   (CONSTANT_P (X)				\
@@ -5227,7 +5219,8 @@ update_auto_inc_notes (rtx insn ATTRIBUT
    is strictly valid.)
 
    CONTEXT = 1 means we are considering regs as index regs,
-   = 0 means we are considering them as base regs.
+   = 0 means we are considering them as base regs, = 2 means we
+   are considering them as base regs for REG + REG.
 
    OPNUM and TYPE specify the purpose of any reloads made.
 
@@ -5250,6 +5243,22 @@ find_reloads_address_1 (enum machine_mod
 			rtx *loc, int opnum, enum reload_type type,
 			int ind_levels, rtx insn)
 {
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE)		\
+  ((CONTEXT) == 2					\
+   ? REGNO_MODE_OK_FOR_REG_BASE_P (REGNO, MODE)		\
+   : (CONTEXT) == 1					\
+   ? REGNO_OK_FOR_INDEX_P (REGNO)			\
+   : REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE))
+
+  enum reg_class context_reg_class;
+
+  if (context == 2)
+    context_reg_class = MODE_BASE_REG_REG_CLASS (mode);
+  else if (context == 1)
+    context_reg_class = INDEX_REG_CLASS;
+  else
+    context_reg_class = MODE_BASE_REG_CLASS (mode);
+
   RTX_CODE code = GET_CODE (x);
 
   switch (code)
@@ -5294,12 +5303,12 @@ find_reloads_address_1 (enum machine_mod
 	   register remateralization for expression like &localvar*4.  Reload it.
 	   It may be possible to combine the displacement on the outer level,
 	   but it is probably not worthwhile to do so.  */
-	if (context)
+	if (context == 1)
 	  {
 	    find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
 				  opnum, ADDR_TYPE (type), ind_levels, insn);
 	    push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
-			 (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+			 context_reg_class,
 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 	    return 1;
 	  }
@@ -5335,22 +5344,22 @@ find_reloads_address_1 (enum machine_mod
 	else if (code0 == REG && code1 == REG)
 	  {
 	    if (REG_OK_FOR_INDEX_P (op0)
-		&& REG_MODE_OK_FOR_BASE_P (op1, mode))
+		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      return 0;
 	    else if (REG_OK_FOR_INDEX_P (op1)
-		     && REG_MODE_OK_FOR_BASE_P (op0, mode))
+		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      return 0;
-	    else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
 	      find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
 				      type, ind_levels, insn);
-	    else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
 	      find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
 				      type, ind_levels, insn);
 	    else if (REG_OK_FOR_INDEX_P (op1))
-	      find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+	      find_reloads_address_1 (mode, orig_op0, 2, &XEXP (x, 0), opnum,
 				      type, ind_levels, insn);
 	    else if (REG_OK_FOR_INDEX_P (op0))
-	      find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+	      find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), opnum,
 				      type, ind_levels, insn);
 	    else
 	      {
@@ -5514,9 +5523,8 @@ find_reloads_address_1 (enum machine_mod
 
 	  if (reg_renumber[regno] >= 0)
 	    regno = reg_renumber[regno];
-	  if ((regno >= FIRST_PSEUDO_REGISTER
-	       || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-		    : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+	  if (regno >= FIRST_PSEUDO_REGISTER
+	      || !REG_OK_FOR_CONTEXT (context, regno, mode))
 	    {
 	      int reloadnum;
 
@@ -5552,8 +5560,7 @@ find_reloads_address_1 (enum machine_mod
 		  x = XEXP (x, 0);
 		  reloadnum
 		    = push_reload (x, x, loc, loc,
-				   (context ? INDEX_REG_CLASS :
-				    MODE_BASE_REG_CLASS (mode)),
+				   context_reg_class,
 				   GET_MODE (x), GET_MODE (x), 0, 0,
 				   opnum, RELOAD_OTHER);
 		}
@@ -5561,8 +5568,7 @@ find_reloads_address_1 (enum machine_mod
 		{
 		  reloadnum
 		    = push_reload (x, NULL_RTX, loc, (rtx*) 0,
-				   (context ? INDEX_REG_CLASS :
-				    MODE_BASE_REG_CLASS (mode)),
+				   context_reg_class,
 				   GET_MODE (x), GET_MODE (x), 0, 0,
 				   opnum, type);
 		  rld[reloadnum].inc
@@ -5602,8 +5608,7 @@ find_reloads_address_1 (enum machine_mod
 				opnum, type, ind_levels, insn);
 
 	  reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
-				   (context ? INDEX_REG_CLASS :
-				    MODE_BASE_REG_CLASS (mode)),
+				   context_reg_class,
 				   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 	  rld[reloadnum].inc
 	    = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -5632,7 +5637,7 @@ find_reloads_address_1 (enum machine_mod
       find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
 			    opnum, ADDR_TYPE (type), ind_levels, insn);
       push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
-		   (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+		   context_reg_class,
 		   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
       return 1;
 
@@ -5643,8 +5648,7 @@ find_reloads_address_1 (enum machine_mod
 	if (reg_equiv_constant[regno] != 0)
 	  {
 	    find_reloads_address_part (reg_equiv_constant[regno], loc,
-				       (context ? INDEX_REG_CLASS :
-					MODE_BASE_REG_CLASS (mode)),
+				       context_reg_class,
 				       GET_MODE (x), opnum, type, ind_levels);
 	    return 1;
 	  }
@@ -5654,8 +5658,7 @@ find_reloads_address_1 (enum machine_mod
 	if (reg_equiv_mem[regno] != 0)
 	  {
 	    push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
-			 (context ? INDEX_REG_CLASS :
-			  MODE_BASE_REG_CLASS (mode)),
+			 context_reg_class,
 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 	    return 1;
 	  }
@@ -5678,12 +5681,11 @@ find_reloads_address_1 (enum machine_mod
 	if (reg_renumber[regno] >= 0)
 	  regno = reg_renumber[regno];
 
-	if ((regno >= FIRST_PSEUDO_REGISTER
-	     || !(context ? REGNO_OK_FOR_INDEX_P (regno)
-		  : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+	if (regno >= FIRST_PSEUDO_REGISTER
+	    || !REG_OK_FOR_CONTEXT (context, regno, mode))
 	  {
 	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
-			 (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+			 context_reg_class,
 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 	    return 1;
 	  }
@@ -5695,7 +5697,7 @@ find_reloads_address_1 (enum machine_mod
 	if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
 	  {
 	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
-			 (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+			 context_reg_class,
 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 	    return 1;
 	  }
@@ -5712,12 +5714,10 @@ find_reloads_address_1 (enum machine_mod
 	    {
 	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
 
-	      if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
-		     : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
+	      if (! REG_OK_FOR_CONTEXT (context, regno, mode))
 		{
 		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
-			       (context ? INDEX_REG_CLASS :
-				MODE_BASE_REG_CLASS (mode)),
+			       context_reg_class,
 			       GET_MODE (x), VOIDmode, 0, 0, opnum, type);
 		  return 1;
 		}
@@ -5726,8 +5726,7 @@ find_reloads_address_1 (enum machine_mod
 	     is larger than the class size, then reload the whole SUBREG.  */
 	  else
 	    {
-	      enum reg_class class = (context ? INDEX_REG_CLASS
-				      : MODE_BASE_REG_CLASS (mode));
+	      enum reg_class class = context_reg_class;
 	      if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
 		  > reg_class_size[class])
 		{
@@ -5757,6 +5756,7 @@ find_reloads_address_1 (enum machine_mod
       }
   }
 
+#undef REG_OK_FOR_CONTEXT
   return 0;
 }
 
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.257
diff -u -p -r1.257 arm.h
--- gcc/config/arm/arm.h	10 Sep 2004 11:55:11 -0000	1.257
+++ gcc/config/arm/arm.h	20 Sep 2004 01:04:41 -0000
@@ -1218,12 +1218,14 @@ enum reg_class
 
 /* For the Thumb the high registers cannot be used as base registers
    when addressing quantities in QI or HI mode; if we don't know the
-   mode, then we must be conservative.  After reload we must also be
-   conservative, since we can't support SP+reg addressing, and we
-   can't fix up any bad substitutions.  */
+   mode, then we must be conservative.  */
 #define MODE_BASE_REG_CLASS(MODE)					\
     (TARGET_ARM ? GENERAL_REGS :					\
-     (((MODE) == SImode && !reload_completed) ? BASE_REGS : LO_REGS))
+     (((MODE) == SImode) ? BASE_REGS : LO_REGS))
+
+/* For Thumb we can not support SP+reg addressing, so we return LO_REGS
+   instead of BASE_REGS.  */
+#define MODE_BASE_REG_REG_CLASS(MODE) BASE_REG_CLASS
 
 /* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
    registers explicitly used in the rtl to be used as spill registers
@@ -1980,6 +1982,11 @@ typedef struct
    ? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)	\
    : ARM_REGNO_OK_FOR_BASE_P (REGNO))
 
+/* Nonzero if X can be the base register in a reg+reg addressing mode.
+   For Thumb, we can not use SP + reg, so reject SP.  */
+#define REGNO_MODE_OK_FOR_REG_BASE_P(X, MODE)	\
+  REGNO_OK_FOR_INDEX_P (X)
+
 /* For ARM code, we don't care about the mode, but for Thumb, the index
    must be suitable for use in a QImode load.  */
 #define REGNO_OK_FOR_INDEX_P(REGNO)	\
@@ -2123,6 +2130,10 @@ typedef struct
    ? THUMB_REG_OK_FOR_INDEX_P (X)		\
    : ARM_REG_OK_FOR_INDEX_P (X))
 
+/* Nonzero if X can be the base register in a reg+reg addressing mode.
+   For Thumb, we can not use SP + reg, so reject SP.  */
+#define REG_MODE_OK_FOR_REG_BASE_P(X, MODE)	\
+  REG_OK_FOR_INDEX_P (X)
 
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
    that is a valid memory address for an instruction.
Index: gcc/doc/tm.texi
===================================================================
RCS file: /home/drow/rsync/gcc-cvs/gcc/gcc/doc/tm.texi,v
retrieving revision 1.372
diff -u -p -r1.372 tm.texi
--- gcc/doc/tm.texi	17 Sep 2004 08:22:49 -0000	1.372
+++ gcc/doc/tm.texi	20 Sep 2004 01:04:51 -0000
@@ -2387,6 +2387,13 @@ the selection of a base register in a mo
 @code{BASE_REG_CLASS}.
 @end defmac
 
+@defmac MODE_BASE_REG_REG_CLASS (@var{mode})
+A C expression whose value is the register class to which a valid
+base register must belong in order to be used in a base plus index
+register address.  You should define this macro if base plus index
+addresses have different requirements than other base register uses.
+@end defmac
+
 @defmac INDEX_REG_CLASS
 A macro whose definition is the name of the class to which a valid
 index register must belong.  An index register is one used in an
@@ -2440,6 +2447,15 @@ you define this macro, the compiler will
 @code{REGNO_OK_FOR_BASE_P}.
 @end defmac
 
+@defmac REGNO_MODE_OK_FOR_REG_BASE_P (@var{num}, @var{mode})
+A C expression which is nonzero if register number @var{num} is suitable for
+use as a base register in base plus index operand addresses, accessing
+memory in mode @var{mode}.  It may be either a suitable hard register or a
+pseudo register that has been allocated such a hard register.  You should
+define this macro if base plus index addresses have different requirements
+than other base register uses.
+@end defmac
+
 @defmac REGNO_OK_FOR_INDEX_P (@var{num})
 A C expression which is nonzero if register number @var{num} is
 suitable for use as an index register in operand addresses.  It may be
@@ -4980,6 +4996,15 @@ you define this macro, the compiler will
 @code{REG_OK_FOR_BASE_P}.
 @end defmac
 
+@defmac REG_MODE_OK_FOR_REG_BASE_P (@var{x}, @var{mode})
+A C expression which is nonzero if @var{x} (assumed to be a @code{reg} RTX)
+is suitable for use as a base register in base plus index operand addresses,
+accessing memory in mode @var{mode}.  It may be either a suitable hard
+register or a pseudo register that has been allocated such a hard register. 
+You should define this macro if base plus index addresses have different
+requirements than other base register uses.
+@end defmac
+
 @defmac REG_OK_FOR_INDEX_P (@var{x})
 A C expression that is nonzero if @var{x} (assumed to be a @code{reg}
 RTX) is valid for use as an index register.


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