From patchwork Mon Jan 10 20:31:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 78217 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 7CD1FB7110 for ; Tue, 11 Jan 2011 07:35:21 +1100 (EST) Received: (qmail 20924 invoked by alias); 10 Jan 2011 20:33:15 -0000 Received: (qmail 20358 invoked by uid 22791); 10 Jan 2011 20:32:55 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, TW_XF X-Spam-Check-By: sourceware.org Received: from b.mail.sonic.net (HELO b.mail.sonic.net) (64.142.19.5) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 10 Jan 2011 20:32:36 +0000 Received: from are.twiddle.net (are.twiddle.net [75.101.38.216]) by b.mail.sonic.net (8.13.8.Beta0-Sonic/8.13.7) with ESMTP id p0AKWXKU032619 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 10 Jan 2011 12:32:34 -0800 Received: from anchor.twiddle.home (anchor.twiddle.home [172.31.0.4]) by are.twiddle.net (8.14.4/8.14.4) with ESMTP id p0AKWXGS006781; Mon, 10 Jan 2011 12:32:33 -0800 Received: from anchor.twiddle.home (localhost.localdomain [127.0.0.1]) by anchor.twiddle.home (8.14.4/8.14.4) with ESMTP id p0AKWVSa019705; Mon, 10 Jan 2011 12:32:31 -0800 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id p0AKWUkV019704; Mon, 10 Jan 2011 12:32:30 -0800 From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: nickc@redhat.com, law@redhat.com, Richard Henderson Subject: [PATCH 14/28] mn10300: Cleanup legitimate addresses Date: Mon, 10 Jan 2011 12:31:43 -0800 Message-Id: <1294691517-19580-15-git-send-email-rth@redhat.com> In-Reply-To: <1294691517-19580-1-git-send-email-rth@redhat.com> References: <1294691517-19580-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org From: Richard Henderson Allow REG+REG and POST_MODIFY addressing for AM33. Fix AM33 base and index register classes. Remove a bunch of register class combinations that aren't really useful after this cleanup. --- gcc/config/mn10300/mn10300-protos.h | 2 + gcc/config/mn10300/mn10300.c | 157 ++++++++++++++++++++++++----------- gcc/config/mn10300/mn10300.h | 85 ++++++++----------- 3 files changed, 147 insertions(+), 97 deletions(-) diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h index 37968ff..d0ce1b3 100644 --- a/gcc/config/mn10300/mn10300-protos.h +++ b/gcc/config/mn10300/mn10300-protos.h @@ -26,6 +26,7 @@ #ifdef RTX_CODE extern rtx mn10300_legitimize_pic_address (rtx, rtx); extern int mn10300_legitimate_pic_operand_p (rtx); +extern rtx mn10300_legitimize_reload_address (rtx, Mmode, int, int, int); extern bool mn10300_function_value_regno_p (const unsigned int); extern int mn10300_get_live_callee_saved_regs (void); extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode); @@ -40,6 +41,7 @@ extern int mn10300_store_multiple_operation (rtx, Mmode); extern int mn10300_symbolic_operand (rtx, Mmode); #endif /* RTX_CODE */ +extern bool mn10300_regno_in_class_p (unsigned, int, bool); extern int mn10300_can_use_return_insn (void); extern void mn10300_expand_prologue (void); extern void mn10300_expand_epilogue (void); diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 78b5b5d..32fb57d 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -489,26 +489,38 @@ mn10300_print_operand_address (FILE *file, rtx addr) switch (GET_CODE (addr)) { case POST_INC: - mn10300_print_operand_address (file, XEXP (addr, 0)); + mn10300_print_operand (file, XEXP (addr, 0), 0); fputc ('+', file); break; + + case POST_MODIFY: + mn10300_print_operand (file, XEXP (addr, 0), 0); + fputc ('+', file); + fputc (',', file); + mn10300_print_operand (file, XEXP (addr, 1), 0); + break; + case REG: mn10300_print_operand (file, addr, 0); break; case PLUS: { - rtx base, index; - if (REG_P (XEXP (addr, 0)) - && REG_OK_FOR_BASE_P (XEXP (addr, 0))) - base = XEXP (addr, 0), index = XEXP (addr, 1); - else if (REG_P (XEXP (addr, 1)) - && REG_OK_FOR_BASE_P (XEXP (addr, 1))) - base = XEXP (addr, 1), index = XEXP (addr, 0); - else - gcc_unreachable (); + rtx base = XEXP (addr, 0); + rtx index = XEXP (addr, 1); + + if (REG_P (index) && !REG_OK_FOR_INDEX_P (index)) + { + rtx x = base; + base = index; + index = x; + + gcc_assert (REG_P (index) && REG_OK_FOR_INDEX_P (index)); + } + gcc_assert (REG_OK_FOR_BASE_P (base)); + mn10300_print_operand (file, index, 0); fputc (',', file); - mn10300_print_operand (file, base, 0);; + mn10300_print_operand (file, base, 0); break; } case SYMBOL_REF: @@ -1389,8 +1401,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, if (in_p && rclass != SP_REGS && rclass != SP_OR_ADDRESS_REGS - && rclass != SP_OR_EXTENDED_REGS - && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS + && rclass != SP_OR_GENERAL_REGS && GET_CODE (x) == PLUS && (XEXP (x, 0) == stack_pointer_rtx || XEXP (x, 1) == stack_pointer_rtx)) @@ -1416,7 +1427,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, addr = XEXP (x, 0); if (addr && CONSTANT_ADDRESS_P (addr)) - return DATA_OR_EXTENDED_REGS; + return GENERAL_REGS; } /* Otherwise assume no secondary reloads are needed. */ @@ -1948,51 +1959,99 @@ mn10300_legitimate_pic_operand_p (rtx x) static bool mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) { - if (CONSTANT_ADDRESS_P (x) - && (! flag_pic || mn10300_legitimate_pic_operand_p (x))) - return TRUE; + rtx base, index; + + if (CONSTANT_ADDRESS_P (x)) + return !flag_pic || mn10300_legitimate_pic_operand_p (x); if (RTX_OK_FOR_BASE_P (x, strict)) - return TRUE; + return true; - if (TARGET_AM33 - && GET_CODE (x) == POST_INC - && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict) - && (mode == SImode || mode == SFmode || mode == HImode)) - return TRUE; + if (TARGET_AM33 && (mode == SImode || mode == SFmode || mode == HImode)) + { + if (GET_CODE (x) == POST_INC) + return RTX_OK_FOR_BASE_P (XEXP (x, 0), strict); + if (GET_CODE (x) == POST_MODIFY) + return (RTX_OK_FOR_BASE_P (XEXP (x, 0), strict) + && CONSTANT_ADDRESS_P (XEXP (x, 1))); + } - if (GET_CODE (x) == PLUS) + if (GET_CODE (x) != PLUS) + return false; + + base = XEXP (x, 0); + index = XEXP (x, 1); + + if (!REG_P (base)) + return false; + if (REG_P (index)) { - rtx base = 0, index = 0; + /* ??? Without AM33 generalized (Ri,Rn) addressing, reg+reg + addressing is hard to satisfy. */ + if (!TARGET_AM33) + return false; - if (REG_P (XEXP (x, 0)) - && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict)) - { - base = XEXP (x, 0); - index = XEXP (x, 1); - } + return (REGNO_GENERAL_P (REGNO (base), strict) + && REGNO_GENERAL_P (REGNO (index), strict)); + } - if (REG_P (XEXP (x, 1)) - && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict)) - { - base = XEXP (x, 1); - index = XEXP (x, 0); - } + if (!REGNO_STRICT_OK_FOR_BASE_P (REGNO (base), strict)) + return false; - if (base != 0 && index != 0) - { - if (CONST_INT_P (index)) - return TRUE; - if (GET_CODE (index) == CONST - && GET_CODE (XEXP (index, 0)) != PLUS - && (! flag_pic - || (mn10300_legitimate_pic_operand_p (index) - && GET_MODE_SIZE (mode) == 4))) - return TRUE; - } + if (CONST_INT_P (index)) + return IN_RANGE (INTVAL (index), -1 - 0x7fffffff, 0x7fffffff); + + if (CONSTANT_ADDRESS_P (index)) + return !flag_pic || mn10300_legitimate_pic_operand_p (index); + + return false; +} + +bool +mn10300_regno_in_class_p (unsigned regno, int rclass, bool strict) +{ + if (regno >= FIRST_PSEUDO_REGISTER) + { + if (!strict) + return true; + if (!reg_renumber) + return false; + regno = reg_renumber[regno]; + } + return TEST_HARD_REG_BIT (reg_class_contents[rclass], regno); +} + +rtx +mn10300_legitimize_reload_address (rtx x, + enum machine_mode mode ATTRIBUTE_UNUSED, + int opnum, int type, + int ind_levels ATTRIBUTE_UNUSED) +{ + bool any_change = false; + + /* See above re disabling reg+reg addressing for MN103. */ + if (!TARGET_AM33) + return NULL_RTX; + + if (GET_CODE (x) != PLUS) + return NULL_RTX; + + if (XEXP (x, 0) == stack_pointer_rtx) + { + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type) type); + any_change = true; + } + if (XEXP (x, 1) == stack_pointer_rtx) + { + push_reload (XEXP (x, 1), NULL_RTX, &XEXP (x, 1), NULL, + GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type) type); + any_change = true; } - return FALSE; + return any_change ? x : NULL_RTX; } /* Used by LEGITIMATE_CONSTANT_P(). Returns TRUE if X is a valid diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h index 4fe0c48..7a6f1a8 100644 --- a/gcc/config/mn10300/mn10300.h +++ b/gcc/config/mn10300/mn10300.h @@ -261,12 +261,9 @@ extern enum processor_type mn10300_tune_cpu; enum reg_class { - NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, - DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS, - EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS, - SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS, - FP_REGS, FP_ACC_REGS, CC_REGS, - GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES + NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, SP_OR_ADDRESS_REGS, + EXTENDED_REGS, FP_REGS, FP_ACC_REGS, CC_REGS, + GENERAL_REGS, SP_OR_GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES @@ -274,13 +271,9 @@ enum reg_class /* Give names of register classes as strings for dump file. */ #define REG_CLASS_NAMES \ -{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \ - "SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \ - "EXTENDED_REGS", \ - "DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \ - "SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \ - "FP_REGS", "FP_ACC_REGS", "CC_REGS", \ - "GENERAL_REGS", "ALL_REGS", "LIM_REGS" \ +{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", "SP_REGS", "SP_OR_ADDRESS_REGS", \ + "EXTENDED_REGS", "FP_REGS", "FP_ACC_REGS", "CC_REGS", \ + "GENERAL_REGS", "SP_OR_GENERAL_REGS", "ALL_REGS", "LIM_REGS" \ } /* Define which registers fit in which classes. @@ -292,17 +285,13 @@ enum reg_class { 0x0000000f, 0 }, /* DATA_REGS */ \ { 0x000001f0, 0 }, /* ADDRESS_REGS */ \ { 0x00000200, 0 }, /* SP_REGS */ \ - { 0x000001ff, 0 }, /* DATA_OR_ADDRESS_REGS */ \ { 0x000003f0, 0 }, /* SP_OR_ADDRESS_REGS */ \ { 0x0003fc00, 0 }, /* EXTENDED_REGS */ \ - { 0x0003fc0f, 0 }, /* DATA_OR_EXTENDED_REGS */ \ - { 0x0003fdf0, 0 }, /* ADDRESS_OR_EXTENDED_REGS */ \ - { 0x0003fe00, 0 }, /* SP_OR_EXTENDED_REGS */ \ - { 0x0003fff0, 0 }, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \ { 0xfffc0000, 0x3ffff },/* FP_REGS */ \ { 0x03fc0000, 0 }, /* FP_ACC_REGS */ \ { 0x00000000, 0x80000 },/* CC_REGS */ \ { 0x0003fdff, 0 }, /* GENERAL_REGS */ \ + { 0x0003ffff, 0 }, /* SP_OR_GENERAL_REGS */ \ { 0xffffffff, 0xfffff } /* ALL_REGS */ \ } @@ -334,8 +323,10 @@ enum reg_class NO_REGS) /* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS -#define BASE_REG_CLASS SP_OR_ADDRESS_REGS +#define INDEX_REG_CLASS \ + (TARGET_AM33 ? GENERAL_REGS : DATA_REGS) +#define BASE_REG_CLASS \ + (TARGET_AM33 ? SP_OR_GENERAL_REGS : SP_OR_ADDRESS_REGS) /* Macros to check register numbers against specific register classes. */ @@ -364,50 +355,31 @@ enum reg_class # define REG_STRICT 1 #endif -# define REGNO_IN_RANGE_P(regno,min,max,strict) \ - (IN_RANGE ((regno), (min), (max)) \ - || ((strict) \ - ? (reg_renumber \ - && reg_renumber[(regno)] >= (min) \ - && reg_renumber[(regno)] <= (max)) \ - : (regno) >= FIRST_PSEUDO_REGISTER)) - #define REGNO_DATA_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_DATA_REGNUM, LAST_DATA_REGNUM, \ - (strict))) + mn10300_regno_in_class_p (regno, DATA_REGS, strict) #define REGNO_ADDRESS_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_ADDRESS_REGNUM, LAST_ADDRESS_REGNUM, \ - (strict))) -#define REGNO_SP_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, \ - (strict))) + mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict) #define REGNO_EXTENDED_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_EXTENDED_REGNUM, LAST_EXTENDED_REGNUM, \ - (strict))) -#define REGNO_AM33_P(regno, strict) \ - (REGNO_DATA_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)) \ - || REGNO_EXTENDED_P ((regno), (strict))) -#define REGNO_FP_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM, (strict))) + mn10300_regno_in_class_p (regno, EXTENDED_REGS, strict) +#define REGNO_GENERAL_P(regno, strict) \ + mn10300_regno_in_class_p (regno, GENERAL_REGS, strict) #define REGNO_STRICT_OK_FOR_BASE_P(regno, strict) \ - (REGNO_SP_P ((regno), (strict)) \ - || REGNO_ADDRESS_P ((regno), (strict)) \ - || REGNO_EXTENDED_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, BASE_REG_CLASS, strict) #define REGNO_OK_FOR_BASE_P(regno) \ (REGNO_STRICT_OK_FOR_BASE_P ((regno), REG_STRICT)) #define REG_OK_FOR_BASE_P(X) \ (REGNO_OK_FOR_BASE_P (REGNO (X))) #define REGNO_STRICT_OK_FOR_BIT_BASE_P(regno, strict) \ - (REGNO_SP_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict) #define REGNO_OK_FOR_BIT_BASE_P(regno) \ (REGNO_STRICT_OK_FOR_BIT_BASE_P ((regno), REG_STRICT)) #define REG_OK_FOR_BIT_BASE_P(X) \ (REGNO_OK_FOR_BIT_BASE_P (REGNO (X))) #define REGNO_STRICT_OK_FOR_INDEX_P(regno, strict) \ - (REGNO_DATA_P ((regno), (strict)) || REGNO_EXTENDED_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, INDEX_REG_CLASS, strict) #define REGNO_OK_FOR_INDEX_P(regno) \ (REGNO_STRICT_OK_FOR_INDEX_P ((regno), REG_STRICT)) #define REG_OK_FOR_INDEX_P(X) \ @@ -557,7 +529,15 @@ struct cum_arg #define MAX_REGS_PER_ADDRESS 2 -#define HAVE_POST_INCREMENT (TARGET_AM33) +/* We have post-increments. */ +#define HAVE_POST_INCREMENT TARGET_AM33 +#define HAVE_POST_MODIFY_DISP TARGET_AM33 + +/* ... But we don't want to use them for block moves. Small offsets are + just as effective, at least for inline block move sizes, and appears + to produce cleaner code. */ +#define USE_LOAD_POST_INCREMENT(M) 0 +#define USE_STORE_POST_INCREMENT(M) 0 /* Accept either REG or SUBREG where a register is valid. */ @@ -568,6 +548,15 @@ struct cum_arg && REGNO_STRICT_OK_FOR_BASE_P (REGNO (SUBREG_REG (X)), \ (strict)))) +#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \ +do { \ + rtx new_x = mn10300_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \ + if (new_x) \ + { \ + X = new_x; \ + goto WIN; \ + } \ +} while (0) /* Nonzero if the constant value X is a legitimate general operand.