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: [Patch, AVR]: Fix PR46779


Denis Chertykov wrote:
> 2011/6/27 Georg-Johann Lay:
>> Denis Chertykov wrote:

>>> The main problem for me is that the new addressing mode produce a
>>> worse code in many tests.
>> You have an example source?
> 
> In attachment.
> 
> Denis.

Hi Denis.

I had a look at the sources you sent.

sort.c:
=======

There is some difference because of register allocation, but the new
code does not look awfully bad, just a bit different because of
different register allocation that might need some more bytes.

The difference is *not* because of deny fake X addressing, it's
because of the new avr_hard_regno_mode_ok implementation to fix
PR46779.  When I add


  if (GET_MODE_SIZE (mode) == 1)
     return 1;

+     if (SImode == mode && regno == 28)
+       return 0;

   return regno % 2 == 0;

to that function, the difference in code disappears.

pr.c:
=====

I get the following sizes with pr-0 the original compile and pr qith
my patch:

>avr-size pr-0.o
   text    data     bss     dec     hex filename
   2824      24       0    2848     b20 pr-0.o
>avr-size pr.o
   text    data     bss     dec     hex filename
   2564      24       0    2588     a1c pr.o

So the size actually decreased significantly.  Avoiding SI in
avr_hard_regno_mode_ok like above does not change code size.

============

Note that I did *not* use the version from the git repository; I could
not get reasonable code out of it (even after some fixes).  Hundreds
of testsuite crashes...

I used the initial patch that I posted; I attached it again for
reference. Note that LEGITIMIZE_RELOAD_ADDRESS is still not
implemented there.

============

Did you decide about the fix for PR46779?

http://gcc.gnu.org/ml/gcc-patches/2011-06/msg00810.html

Is it ok to commit?

I think fix PR46779 and fix fake X addresses (PR46278) should be
separate patches and not intermixed.

Johann

Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 175956)
+++ config/avr/avr.md	(working copy)
@@ -246,8 +246,8 @@ (define_expand "movqi"
   ")
 
 (define_insn "*movqi"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
-	(match_operand:QI 1 "general_operand"       "rL,i,rL,Qm,r,q,i"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,m,r,q,r,*r")
+	(match_operand:QI 1 "general_operand"       "rL,i,rL,m,r,q,i"))]
   "(register_operand (operands[0],QImode)
     || register_operand (operands[1], QImode) || const0_rtx == operands[1])"
   "* return output_movqi (insn, operands, NULL);"
@@ -295,15 +295,6 @@ (define_expand "movhi"
     }
 }")
 
-(define_insn "*movhi_sp"
-  [(set (match_operand:HI 0 "register_operand" "=q,r")
-        (match_operand:HI 1 "register_operand"  "r,q"))]
-  "((stack_register_operand(operands[0], HImode) && register_operand (operands[1], HImode))
-    || (register_operand (operands[0], HImode) && stack_register_operand(operands[1], HImode)))"
-  "* return output_movhi (insn, operands, NULL);"
-  [(set_attr "length" "5,2")
-   (set_attr "cc" "none,none")])
-
 (define_insn "movhi_sp_r_irq_off"
   [(set (match_operand:HI 0 "stack_register_operand" "=q")
         (unspec_volatile:HI [(match_operand:HI 1 "register_operand"  "r")] 
@@ -427,8 +418,8 @@ (define_insn "*reload_insi"
 
 
 (define_insn "*movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
-        (match_operand:SI 1 "general_operand"       "r,L,Qm,rL,i,i"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,!d,r")
+        (match_operand:SI 1 "general_operand"       "r,L,m,rL,i,i"))]
   "(register_operand (operands[0],SImode)
     || register_operand (operands[1],SImode) || const0_rtx == operands[1])"
   {
@@ -455,8 +446,8 @@ (define_expand "movsf"
 }")
 
 (define_insn "*movsf"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
-        (match_operand:SF 1 "general_operand"       "r,G,Qm,rG,F,F"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,m,!d,r")
+        (match_operand:SF 1 "general_operand"       "r,G,m,rG,F,F"))]
   "register_operand (operands[0], SFmode)
    || register_operand (operands[1], SFmode)
    || operands[1] == CONST0_RTX (SFmode)"
@@ -1592,8 +1583,8 @@ (define_mode_attr rotx [(DI "&r,&r,X") (
 (define_mode_attr rotsmode [(DI "QI") (SI "HI") (HI "QI")])
 
 (define_expand "rotl<mode>3"
-  [(parallel [(set (match_operand:HIDI 0 "register_operand" "")
-		   (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
+  [(parallel [(set (match_operand:HISI 0 "register_operand" "")
+		   (rotate:HISI (match_operand:HISI 1 "register_operand" "")
 				(match_operand:VOID 2 "const_int_operand" "")))
 		(clobber (match_dup 3))])]
   ""
@@ -1692,7 +1683,7 @@ (define_split ; ashlqi3_const6
 (define_insn "*ashlqi3"
   [(set (match_operand:QI 0 "register_operand"           "=r,r,r,r,!d,r,r")
 	(ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
-		   (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,Qm")))]
+		   (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,m")))]
   ""
   "* return ashlqi3_out (insn, operands, NULL);"
   [(set_attr "length" "5,0,1,2,4,6,9")
@@ -1701,7 +1692,7 @@ (define_insn "*ashlqi3"
 (define_insn "ashlhi3"
   [(set (match_operand:HI 0 "register_operand"           "=r,r,r,r,r,r,r")
 	(ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
-		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return ashlhi3_out (insn, operands, NULL);"
   [(set_attr "length" "6,0,2,2,4,10,10")
@@ -1710,7 +1701,7 @@ (define_insn "ashlhi3"
 (define_insn "ashlsi3"
   [(set (match_operand:SI 0 "register_operand"           "=r,r,r,r,r,r,r")
 	(ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
-		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return ashlsi3_out (insn, operands, NULL);"
   [(set_attr "length" "8,0,4,4,8,10,12")
@@ -1799,7 +1790,7 @@ (define_insn "*ashlsi3_const"
 (define_insn "ashrqi3"
   [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r")
 	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,K,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,K,n,m")))]
   ""
   "* return ashrqi3_out (insn, operands, NULL);"
   [(set_attr "length" "5,0,1,2,5,9")
@@ -1808,7 +1799,7 @@ (define_insn "ashrqi3"
 (define_insn "ashrhi3"
   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return ashrhi3_out (insn, operands, NULL);"
   [(set_attr "length" "6,0,2,4,4,10,10")
@@ -1817,7 +1808,7 @@ (define_insn "ashrhi3"
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return ashrsi3_out (insn, operands, NULL);"
   [(set_attr "length" "8,0,4,6,8,10,12")
@@ -1907,7 +1898,7 @@ (define_split	; lshrqi3_const6
 (define_insn "*lshrqi3"
   [(set (match_operand:QI 0 "register_operand"             "=r,r,r,r,!d,r,r")
 	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,K,n,n,m")))]
   ""
   "* return lshrqi3_out (insn, operands, NULL);"
   [(set_attr "length" "5,0,1,2,4,6,9")
@@ -1916,7 +1907,7 @@ (define_insn "*lshrqi3"
 (define_insn "lshrhi3"
   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return lshrhi3_out (insn, operands, NULL);"
   [(set_attr "length" "6,0,2,2,4,10,10")
@@ -1925,7 +1916,7 @@ (define_insn "lshrhi3"
 (define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
-		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
+		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,m")))]
   ""
   "* return lshrsi3_out (insn, operands, NULL);"
   [(set_attr "length" "8,0,4,4,8,10,12")
@@ -2198,54 +2189,6 @@ (define_insn_and_split "zero_extendhisi2
   operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off);
 })
 
-(define_insn_and_split "zero_extendqidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
-  ""
-  "#"
-  "reload_completed"
-  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
-   (set (match_dup 3) (const_int 0))]
-{
-  unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
-  unsigned int high_off = subreg_highpart_offset (SImode, DImode);
-
-  operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
-  operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
-})
-
-(define_insn_and_split "zero_extendhidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
-  ""
-  "#"
-  "reload_completed"
-  [(set (match_dup 2) (zero_extend:SI (match_dup 1)))
-   (set (match_dup 3) (const_int 0))]
-{
-  unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
-  unsigned int high_off = subreg_highpart_offset (SImode, DImode);
-
-  operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
-  operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
-})
-
-(define_insn_and_split "zero_extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-        (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
-  ""
-  "#"
-  "reload_completed"
-  [(set (match_dup 2) (match_dup 1))
-   (set (match_dup 3) (const_int 0))]
-{
-  unsigned int low_off = subreg_lowpart_offset (SImode, DImode);
-  unsigned int high_off = subreg_highpart_offset (SImode, DImode);
-
-  operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off);
-  operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off);
-})
-
 ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
 ;; compare
 
@@ -2504,7 +2447,7 @@ (define_insn "*sbrx_branch<mode>"
   [(set (pc)
         (if_then_else
 	 (match_operator 0 "eqne_operator"
-			 [(zero_extract:QIDI
+			 [(zero_extract:QISI
 			   (match_operand:VOID 1 "register_operand" "r")
 			   (const_int 1)
 			   (match_operand 2 "const_int_operand" "n"))
Index: config/avr/avr-protos.h
===================================================================
--- config/avr/avr-protos.h	(revision 175956)
+++ config/avr/avr-protos.h	(working copy)
@@ -24,7 +24,7 @@
 
 extern int function_arg_regno_p (int r);
 extern void avr_cpu_cpp_builtins (struct cpp_reader * pfile);
-extern enum reg_class avr_regno_reg_class (int r);
+extern reg_class_t avr_regno_reg_class (unsigned int r);
 extern void asm_globalize_label (FILE *file, const char *name);
 extern void avr_asm_declare_function_name (FILE *, const char *, tree);
 extern void order_regs_for_local_alloc (void);
@@ -107,6 +107,8 @@ extern RTX_CODE avr_normalize_condition
 extern int compare_eq_p (rtx insn);
 extern void out_shift_with_cnt (const char *templ, rtx insn,
 				rtx operands[], int *len, int t_len);
+extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, RTX_CODE, RTX_CODE);
+extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, RTX_CODE, RTX_CODE);
 extern rtx avr_incoming_return_addr_rtx (void);
 #endif /* RTX_CODE */
 
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 175956)
+++ config/avr/avr.c	(working copy)
@@ -279,18 +279,27 @@ avr_option_override (void)
 
 /*  return register class from register number.  */
 
-static const enum reg_class reg_class_tab[]={
-  GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
-  GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
-  GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
-  GENERAL_REGS, /* r0 - r15 */
-  LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
-  LD_REGS,                      /* r16 - 23 */
-  ADDW_REGS,ADDW_REGS,          /* r24,r25 */
-  POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
-  POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
-  POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
-  STACK_REG,STACK_REG           /* SPL,SPH */
+static const reg_class_t reg_class_tab[] =
+  {
+    /* r0 */
+    R0_REG,
+    /* r1 - r15 */
+    NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
+    NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
+    NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
+    /* r16 - r23 */
+    SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
+    SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
+    /* r24, r25 */
+    ADDW_REGS, ADDW_REGS,
+    /* r26, r27 */
+    POINTER_X_REGS, POINTER_X_REGS,
+    /* r28, r29 */
+    POINTER_Y_REGS, POINTER_Y_REGS,
+    /* r30, r31 */
+    POINTER_Z_REGS, POINTER_Z_REGS,
+    /* SPL, SPH */
+    STACK_REG, STACK_REG
 };
 
 /* Function to set up the backend function structure.  */
@@ -303,8 +312,8 @@ avr_init_machine_status (void)
 
 /* Return register class for register R.  */
 
-enum reg_class
-avr_regno_reg_class (int r)
+reg_class_t
+avr_regno_reg_class (unsigned int r)
 {
   if (r <= 33)
     return reg_class_tab[r];
@@ -1082,74 +1091,75 @@ avr_cannot_modify_jumps_p (void)
 }
 
 
-/* Return nonzero if X (an RTX) is a legitimate memory address on the target
-   machine for a memory operand of mode MODE.  */
+/* Helper function for `avr_legitimate_address_p'.  */
+
+static inline int
+avr_reg_ok_for_addr (rtx reg, int strict)
+{
+  return (REG_P (reg)
+          && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode, MEM, SCRATCH)
+              || (!strict && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
+}
+
+
+/* Implement `TARGET_LEGITIMATE_ADDRESS_P'.  */
 
 bool
 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 {
-  enum reg_class r = NO_REGS;
-  
-  if (TARGET_ALL_DEBUG)
-    {
-      fprintf (stderr, "mode: (%s) %s %s %s %s:",
-	       GET_MODE_NAME(mode),
-	       strict ? "(strict)": "",
-	       reload_completed ? "(reload_completed)": "",
-	       reload_in_progress ? "(reload_in_progress)": "",
-	       reg_renumber ? "(reg_renumber)" : "");
-      if (GET_CODE (x) == PLUS
-	  && REG_P (XEXP (x, 0))
-	  && GET_CODE (XEXP (x, 1)) == CONST_INT
-	  && INTVAL (XEXP (x, 1)) >= 0
-	  && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
-	  && reg_renumber
-	  )
-	fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
-		 true_regnum (XEXP (x, 0)));
-      debug_rtx (x);
-    }
-  if (!strict && GET_CODE (x) == SUBREG)
-	x = SUBREG_REG (x);
-  if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
-                    : REG_OK_FOR_BASE_NOSTRICT_P (x)))
-    r = POINTER_REGS;
-  else if (CONSTANT_ADDRESS_P (x))
-    r = ALL_REGS;
-  else if (GET_CODE (x) == PLUS
-           && REG_P (XEXP (x, 0))
-	   && GET_CODE (XEXP (x, 1)) == CONST_INT
-	   && INTVAL (XEXP (x, 1)) >= 0)
-    {
-      int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
-      if (fit)
-	{
-	  if (! strict
-	      || REGNO (XEXP (x,0)) == REG_X
-	      || REGNO (XEXP (x,0)) == REG_Y
-	      || REGNO (XEXP (x,0)) == REG_Z)
-	    r = BASE_POINTER_REGS;
-	  if (XEXP (x,0) == frame_pointer_rtx
-	      || XEXP (x,0) == arg_pointer_rtx)
-	    r = BASE_POINTER_REGS;
-	}
-      else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
-	r = POINTER_Y_REGS;
-    }
-  else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
-           && REG_P (XEXP (x, 0))
-           && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
-               : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
-    {
-      r = POINTER_REGS;
-    }
-  if (TARGET_ALL_DEBUG)
+  bool ok = false;
+
+  switch (GET_CODE (x))
     {
-      fprintf (stderr, "   ret = %c\n", r + '0');
+    case REG:
+      ok = avr_reg_ok_for_addr (x, strict);
+      if (strict
+          && DImode == mode
+          && REG_X == REGNO (x))
+        {
+          ok = false;
+        }
+      break;
+
+    case POST_INC:
+    case PRE_DEC:
+      ok = avr_reg_ok_for_addr (XEXP (x, 0), strict);
+      break;
+
+    case SYMBOL_REF:
+    case CONST_INT:
+    case CONST:
+      ok = true;
+      break;
+      
+    case PLUS:
+      {
+        rtx op0 = XEXP (x, 0);
+        rtx op1 = XEXP (x, 1);
+            
+        if (REG_P (op0)
+            && CONST_INT_P (op1))
+          {
+            ok = (avr_reg_ok_for_addr (op0, strict)
+                  && INTVAL (op1) >= 0
+                  && INTVAL (op1) <= MAX_LD_OFFSET (mode));
+            
+            if (strict
+                && REG_X == REGNO (op0))
+              {
+                ok = false;
+              }
+          }
+        break;
+      }
+      
+    default:
+      break;
     }
-  return r == NO_REGS ? 0 : (int)r;
-}
 
+  return ok;
+}
+ 
 /* Attempts to replace X with a valid
    memory address for an operand of mode MODE  */
 
@@ -6118,27 +6128,74 @@ jump_over_one_insn_p (rtx insn, rtx dest
 int
 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
 {
-  /* Disallow QImode in stack pointer regs.  */
-  if ((regno == REG_SP || regno == (REG_SP + 1)) && mode == QImode)
-    return 0;
+  /* Any GENERAL_REGS register can hold 8-bit values.  */
+  /* FIXME:  8-bit values must not be disallowed for R28 or R29.
+     Disallowing QI et al. in these registers might lead to code like
+         (set (subreg:QI (reg:HI 28) n) ...)
+     which will result in wrong code because reload does not handle
+     SUBREGs of hard regsisters like this.  This could be fixed in reload.
+     However, it appears that fixing reload is not wanted by reload people.  */
+  
+  if (GET_MODE_SIZE (mode) == 1)
+     return 1;
 
-  /* The only thing that can go into registers r28:r29 is a Pmode.  */
-  if (regno == REG_Y && mode == Pmode)
-    return 1;
+   /* All modes larger than 8 bits should start in an even register.  */
+   
+  return regno % 2 == 0;
+}
 
-  /* Otherwise disallow all regno/mode combinations that span r28:r29.  */
-  if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
-    return 0;
 
-  if (mode == QImode)
-    return 1;
+/* Worker function for `MODE_CODE_BASE_REG_CLASS'.  */
 
-  /* Modes larger than QImode occupy consecutive registers.  */
-  if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
-    return 0;
+reg_class_t
+avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+                              RTX_CODE outer_code, RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  reg_class_t rclass = BASE_POINTER_REGS;
+  
+  switch (outer_code)
+    {
+    case MEM:
+    case POST_INC:
+    case PRE_DEC:
+      rclass = POINTER_REGS;
+      break;
+      
+    default:
+      break;
+    }
+  
+  return rclass;
+}
+
+
+/* Worker function for `REGNO_MODE_CODE_OK_FOR_BASE_P'.  */
+
+bool
+avr_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
+                                   RTX_CODE outer_code, RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  bool ok;
+  
+  switch (outer_code)
+    {
+    case PLUS:
+      ok = regno == REG_Z || regno == REG_Y;
+      break;
+      
+    case MEM: /* plain reg */
+    case POST_INC:
+    case PRE_DEC:
+      ok = regno == REG_Z || regno == REG_Y || regno == REG_X;
+      break;
+      
+    default:
+      ok = false;
+      break;
+      
+    }
 
-  /* All modes larger than QImode should start in an even register.  */
-  return !(regno & 1);
+  return ok;
 }
 
 const char *
@@ -6410,13 +6467,23 @@ avr_hard_regno_scratch_ok (unsigned int
       && !df_regs_ever_live_p (regno))
     return false;
 
+  /* Don't allow hard registers that might be part of the frame pointer.
+     Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
+     and don't care for a frame pointer that spans more than one register.  */
+
+  if ((!reload_completed || frame_pointer_needed)
+      && (regno == REG_Y || regno == REG_Y + 1))
+    {
+      return false;
+    }
+
   return true;
 }
 
 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
 
 int
-avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+avr_hard_regno_rename_ok (unsigned int old_reg,
 			  unsigned int new_reg)
 {
   /* Interrupt functions can only use registers that have already been
@@ -6427,6 +6494,17 @@ avr_hard_regno_rename_ok (unsigned int o
       && !df_regs_ever_live_p (new_reg))
     return 0;
 
+  /* Don't allow hard registers that might be part of the frame pointer.
+     Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
+     and don't care for a frame pointer that spans more than one register.  */
+
+  if ((!reload_completed || frame_pointer_needed)
+      && (old_reg == REG_Y || old_reg == REG_Y + 1
+          || new_reg == REG_Y || new_reg == REG_Y + 1))
+    {
+      return 0;
+    }
+  
   return 1;
 }
 
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 175811)
+++ config/avr/avr.h	(working copy)
@@ -292,21 +292,13 @@ enum reg_class {
 
 #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
 
-#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
+#define MODE_CODE_BASE_REG_CLASS(mode, outer_code, index_code)  \
+  avr_mode_code_base_reg_class (mode, outer_code, index_code)
 
 #define INDEX_REG_CLASS NO_REGS
 
-#define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER		\
-				 && ((r) == REG_X			\
-				     || (r) == REG_Y			\
-				     || (r) == REG_Z			\
-				     || (r) == ARG_POINTER_REGNUM))	\
-				|| (reg_renumber			\
-				    && (reg_renumber[r] == REG_X	\
-					|| reg_renumber[r] == REG_Y	\
-					|| reg_renumber[r] == REG_Z	\
-					|| (reg_renumber[r]		\
-					    == ARG_POINTER_REGNUM))))
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, outer_code, index_code) \
+  avr_regno_mode_code_ok_for_base_p (num, mode, outer_code, index_code) 
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
 
@@ -369,16 +361,11 @@ extern int avr_reg_order[];
 
 #define MAX_REGS_PER_ADDRESS 1
 
-#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
-  (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
 /* LEGITIMIZE_RELOAD_ADDRESS will allow register R26/27 to be used, where it
    is no worse than normal base pointers R28/29 and R30/31. For example:
    If base offset is greater than 63 bytes or for R++ or --R addressing.  */
    
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)    \
+#define _LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)    \
 do {									    \
   if (1&&(GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC))	    \
     {									    \

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