From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18063 invoked by alias); 7 Jul 2011 09:25:34 -0000 Received: (qmail 18018 invoked by uid 22791); 7 Jul 2011 09:25:31 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,TW_HR,TW_LQ,TW_OV,TW_RQ,TW_VH,TW_VQ X-Spam-Check-By: sourceware.org Received: from mo-p00-ob.rzone.de (HELO mo-p00-ob.rzone.de) (81.169.146.162) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 07 Jul 2011 09:25:13 +0000 X-RZG-AUTH: :LXoWVUeid/7A29J/hMvvT2k715jHQaJercGObUOFkj18odoYNahU4Q== X-RZG-CLASS-ID: mo00 Received: from [192.168.0.22] (business-188-111-022-002.static.arcor-ip.net [188.111.22.2]) by smtp.strato.de (cohen mo60) (RZmta 26.0) with ESMTPA id x0119bn6789lJH ; Thu, 7 Jul 2011 11:25:07 +0200 (MEST) Message-ID: <4E157B72.1000304@gjlay.de> Date: Thu, 07 Jul 2011 09:59:00 -0000 From: Georg-Johann Lay User-Agent: Thunderbird 2.0.0.24 (X11/20100302) MIME-Version: 1.0 To: Denis Chertykov CC: Richard Henderson , gcc-patches@gcc.gnu.org, Anatoly Sokolov , "Eric B. Weddington" Subject: Re: [Patch, AVR]: Fix PR46779 References: <4DF0FAB5.6070704@gjlay.de> <4DF11D20.4030907@gjlay.de> <4DF1ED76.4030507@gjlay.de> <4DF650B7.3030705@gjlay.de> <4DF73490.2080709@gjlay.de> <4DF7D2B5.1090708@gjlay.de> <4DF8ED42.1030706@redhat.com> <4DF918A9.4070003@gjlay.de> <4DF92AEA.4000906@redhat.com> <4DF93B17.8020008@redhat.com> <4E03B658.8020509@redhat.com> <4E078F93.7060901@gjlay.de> <4E084291.4030300@gjlay.de> In-Reply-To: Content-Type: multipart/mixed; boundary="------------000701010807040907090904" X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-07/txt/msg00438.txt.bz2 This is a multi-part message in MIME format. --------------000701010807040907090904 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Content-length: 1858 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 --------------000701010807040907090904 Content-Type: text/x-patch; name="new-addr-v4.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="new-addr-v4.diff" Content-length: 21751 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 "rotl3" - [(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" [(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)) \ { \ --------------000701010807040907090904--