This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, AVR]: Fix PR46779
- From: Georg-Johann Lay <avr at gjlay dot de>
- To: Denis Chertykov <chertykov at gmail dot com>
- Cc: Richard Henderson <rth at redhat dot com>, gcc-patches at gcc dot gnu dot org, Anatoly Sokolov <aesok at post dot ru>, "Eric B. Weddington" <eric dot weddington at atmel dot com>
- Date: Thu, 07 Jul 2011 11:25:06 +0200
- Subject: Re: [Patch, AVR]: Fix PR46779
- References: <4DF0FAB5.6070704@gjlay.de> <BANLkTi=1v9KGgCL0V0+i=LOtbCh51FLm+A@mail.gmail.com> <4DF11D20.4030907@gjlay.de> <BANLkTi=VAo8UcLDsvBp5vWk3qaO5RQvAKg@mail.gmail.com> <4DF1ED76.4030507@gjlay.de> <BANLkTi=P0zopComgS6FDZ=cg3s9sDuKNHg@mail.gmail.com> <4DF650B7.3030705@gjlay.de> <BANLkTimPjxMw48oExFWLtDcdB=3nb_VH0g@mail.gmail.com> <4DF73490.2080709@gjlay.de> <BANLkTim=EZDDtSxpE0b0aU7wjcxynsyUqg@mail.gmail.com> <4DF7D2B5.1090708@gjlay.de> <4DF8ED42.1030706@redhat.com> <4DF918A9.4070003@gjlay.de> <4DF92AEA.4000906@redhat.com> <4DF93B17.8020008@redhat.com> <BANLkTimrSz4-0tTw-iai0g=6Ry-jQ+ydTQ@mail.gmail.com> <4E03B658.8020509@redhat.com> <BANLkTimiQLH+=0QJV8ELx+6s_NXKaKPv_g@mail.gmail.com> <4E078F93.7060901@gjlay.de> <BANLkTim3q=v5dc-ja6bHjvzVAtAf-PVy0g@mail.gmail.com> <4E084291.4030300@gjlay.de> <BANLkTikx_eDGT7KT+B_X0nTT0wAzYe7DBg@mail.gmail.com>
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)) \
{ \