From patchwork Sat Mar 29 01:07:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Suchanek X-Patchwork-Id: 334917 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6A85814008E for ; Sat, 29 Mar 2014 12:07:58 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type :content-transfer-encoding:mime-version; q=dns; s=default; b=xiL FoZzE3rmYyKsVM+D+tqIghY9oZP6xQIJ6gX2iZUFKg6O78uMSxeLstTdSiHvOBO1 TeNBzSI/TUMqbaodZTr+5/wZ7g06y2rk2++mJL9FYa8KKL+4+jgNCghqpTsfxaPh oWTnI9d2QOMQpFlihmAkPL7hDEridnYFS0bkpF2k= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type :content-transfer-encoding:mime-version; s=default; bh=ynRW7Swct gs6bVsACrvZOs3fM8M=; b=qlhQxSFywameIlwN4Q1s7LwnXegAOCt1QWEj7zx/+ jCZXgvLRRRA7H3WCqjlyq6xDh/boGf2wI6e8E4cXCba4Wt1v7zXUUZj/qLAd0PSW tUl6HAj9sjOn3UHnhZRnqALyit2o0ludieCUWy2knsyTTxxJdurlGWwT4445rSAi +4= Received: (qmail 32219 invoked by alias); 29 Mar 2014 01:07:50 -0000 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 Received: (qmail 32209 invoked by uid 89); 29 Mar 2014 01:07:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=BAYES_40, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.89.28.114) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 29 Mar 2014 01:07:44 +0000 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 528A35AA68034; Sat, 29 Mar 2014 01:07:36 +0000 (GMT) Received: from KLMAIL02.kl.imgtec.org (192.168.5.97) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.181.6; Sat, 29 Mar 2014 01:07:40 +0000 Received: from KLMAIL01.kl.imgtec.org ([192.168.5.35]) by klmail02.kl.imgtec.org ([192.168.5.97]) with mapi id 14.03.0181.006; Sat, 29 Mar 2014 01:07:40 +0000 From: Robert Suchanek To: "gcc-patches@gcc.gnu.org" CC: "vmakarov@redhat.com" , "rdsandiford@googlemail.com" Subject: [RFC][PATCH][MIPS] Patch to enable LRA for MIPS backend Date: Sat, 29 Mar 2014 01:07:40 +0000 Message-ID: MIME-Version: 1.0 Hi All, This patch enables LRA by default for MIPS. The classic reload is still available and can be enabled via -mreload switch. All regression are fixed, with one exception described below. There was a necessary change in the LRA core as I believe there was a genuine unhandled case in LRA when processing addresses. It is specific to MIPS16 as store/load[unsigned] halfword/byte instructions cannot access the stack pointer directly. Potentially, it can affect other architectures if they have similar limitation. One of the problems showed an RTL that contained $frame as the base register (without any offset, simple move) but LRA temporarily eliminated it to $sp before calling the target hook to validate the address. The backend rejected it because of the mode and $sp. Then, LRA tried to emit base+disp but ICEd because there never was any displacement. Another testcase, revealed offset not being used and unnecessary 'add' instructions were inserted preventing the use of offsets. Marking an insn with STACK_POINTER_REGNUM as valid was not an option as LRA would generate an insn with $sp and fail during coherency check. The patch attempts to reload $sp into a register and re-validate the address with offset (if there is one). If this fails it sticks to the original plan inserting base+disp. The generated code optimized for size is fairly acceptable. CSiBE shows a slight advantage of LRA over the reload for MIPS16 with some minor regression for mips32*, mips64*, on average less than 0.5%. The code size improvements are being investigated. The patch has been tested on the following variations: - cross-tested mips-mti-elf, mips-mti-linux-gnu (languages=c,c++): {-mips32,-mips32r2}{-EL,-EB}{-mhard-float,-msoft-float}{-mno-mips16,-mips16} -mips64r2 -mabi=n32 {-mhard-float,-msoft-float} -mips64r2 -mabi=64 {-mhard-float,-msoft-float} - bootstrapped and regtested x86_84-unknown-linux-gnu (all languages) There are two known DejaGNU failures on mips64 with mabi=64, namely, m{add,sub}-8 tests because of the subtleties in LRA costing model but it's not a correctness issue. The *mul_{add,sub}_si patterns are tuned explicitly for LRA and all failures have been resolved with m{add,sub}-* except the above. By saying failures I mean the differences between tests ran with/without -mreload switch. A number of failures already existed on ToT at the time of testing. The patch is intended for Stage 1. As for the legal part, the company-wide copyright assignment is in process. Regards, Robert testsuite/ChangeLog: 2014-03-26 Robert Suchanek * lra-constraints.c (base_to_reg): New function. (process_address): Use new function. * rtlanal.c (get_base_term): Add CONSTANT_P (*inner). * config/mips/constraints.md ("d"): BASE_REG_CLASS replaced by ADDR_REG_CLASS. * config/mips/mips.c (mips_regno_mode_ok_for_base_p): Remove use !strict_p for MIPS16. (mips_register_priority): New function that implements the target hook TARGET_REGISTER_PRIORITY. (mips_spill_class): Likewise for TARGET_SPILL_CLASS (mips_lra_p): Likewise for TARGET_LRA_P. * config/mips/mips.h (reg_class): Add M16F_REGS and SPILL_REGS classes. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Likewise. (BASE_REG_CLASS): Use M16F_REGS. (ADDR_REG_CLASS): Define. (IRA_HARD_REGNO_ADD_COST_MULTIPLIER): Define. * config/mips/mips.md (*mul_acc_si, *mul_sub_si): Add alternative tuned for LRA. New set attribute to enable alternatives depending on the register allocator used. (*and3_mips16): Remove the load alternatives. (*lea64): Disable pattern for MIPS16. * config/mips/mips.opt (mreload): New option. --- gcc/config/mips/constraints.md | 2 +- gcc/config/mips/mips.c | 51 +++++++++++++++++- gcc/config/mips/mips.h | 17 +++++- gcc/config/mips/mips.md | 112 +++++++++++++++++++++++----------------- gcc/config/mips/mips.opt | 4 ++ gcc/lra-constraints.c | 44 +++++++++++++++- gcc/rtlanal.c | 3 +- 7 files changed, 181 insertions(+), 52 deletions(-) diff --git gcc/config/mips/constraints.md gcc/config/mips/constraints.md index 49e4895..3810ac3 100644 --- gcc/config/mips/constraints.md +++ gcc/config/mips/constraints.md @@ -19,7 +19,7 @@ ;; Register constraints -(define_register_constraint "d" "BASE_REG_CLASS" +(define_register_constraint "d" "ADDR_REG_CLASS" "An address register. This is equivalent to @code{r} unless generating MIPS16 code.") diff --git gcc/config/mips/mips.c gcc/config/mips/mips.c index 143169b..f27a801 100644 --- gcc/config/mips/mips.c +++ gcc/config/mips/mips.c @@ -2255,7 +2255,7 @@ mips_regno_mode_ok_for_base_p (int regno, enum machine_mode mode, All in all, it seems more consistent to only enforce this restriction during and after reload. */ if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM) - return !strict_p || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8; + return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8; return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno); } @@ -12114,6 +12114,32 @@ mips_register_move_cost (enum machine_mode mode, return 0; } +/* Return a register priority for hard reg REGNO. */ + +static int +mips_register_priority (int hard_regno) +{ + if (TARGET_MIPS16) + { + /* Treat MIPS16 registers with higher priority than other regs. */ + switch (hard_regno) + { + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 16: + case 17: + return 1; + default: + return 0; + } + } + return 0; +} + /* Implement TARGET_MEMORY_MOVE_COST. */ static int @@ -18897,6 +18923,22 @@ mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) *update = build2 (COMPOUND_EXPR, void_type_node, *update, atomic_feraiseexcept_call); } + +static reg_class_t +mips_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED) +{ + if (TARGET_MIPS16) + return SPILL_REGS; + return NO_REGS; +} + +static bool +mips_lra_p (void) +{ + return !TARGET_RELOAD; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -18960,6 +19002,8 @@ mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode #undef TARGET_REGISTER_MOVE_COST #define TARGET_REGISTER_MOVE_COST mips_register_move_cost +#undef TARGET_REGISTER_PRIORITY +#define TARGET_REGISTER_PRIORITY mips_register_priority #undef TARGET_MEMORY_MOVE_COST #define TARGET_MEMORY_MOVE_COST mips_memory_move_cost #undef TARGET_RTX_COSTS @@ -19134,6 +19178,11 @@ mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv +#undef TARGET_SPILL_CLASS +#define TARGET_SPILL_CLASS mips_spill_class +#undef TARGET_LRA_P +#define TARGET_LRA_P mips_lra_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-mips.h" diff --git gcc/config/mips/mips.h gcc/config/mips/mips.h index a786d4c..712008f 100644 --- gcc/config/mips/mips.h +++ gcc/config/mips/mips.h @@ -1871,10 +1871,12 @@ enum reg_class { NO_REGS, /* no registers in set */ M16_REGS, /* mips16 directly accessible registers */ + M16F_REGS, /* mips16 + frame */ T_REG, /* mips16 T register ($24) */ M16_T_REGS, /* mips16 registers plus T register */ PIC_FN_ADDR_REG, /* SVR4 PIC function address register */ V1_REG, /* Register $v1 ($3) used for TLS access. */ + SPILL_REGS, /* All but $sp and call preserved regs are in here */ LEA_REGS, /* Every GPR except $25 */ GR_REGS, /* integer registers */ FP_REGS, /* floating point registers */ @@ -1908,10 +1910,12 @@ enum reg_class { \ "NO_REGS", \ "M16_REGS", \ + "M16F_REGS", \ "T_REG", \ "M16_T_REGS", \ "PIC_FN_ADDR_REG", \ "V1_REG", \ + "SPILL_REGS", \ "LEA_REGS", \ "GR_REGS", \ "FP_REGS", \ @@ -1948,10 +1952,12 @@ enum reg_class { \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16_REGS */ \ + { 0x200300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16F_REGS */ \ { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* T_REG */ \ { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16_T_REGS */ \ { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* PIC_FN_ADDR_REG */ \ { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* V1_REG */ \ + { 0x0003fffc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* SPILL_REGS */ \ { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* LEA_REGS */ \ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* GR_REGS */ \ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* FP_REGS */ \ @@ -1984,7 +1990,9 @@ enum reg_class valid base register must belong. A base register is one used in an address which is the register value plus a displacement. */ -#define BASE_REG_CLASS (TARGET_MIPS16 ? M16_REGS : GR_REGS) +#define BASE_REG_CLASS (TARGET_MIPS16 ? M16F_REGS : GR_REGS) + +#define ADDR_REG_CLASS (TARGET_MIPS16 ? M16_REGS : GR_REGS) /* A macro whose definition is the name of the class to which a valid index register must belong. An index register is one used @@ -1994,6 +2002,13 @@ enum reg_class #define INDEX_REG_CLASS NO_REGS +/* Add costs to hard registers based on frequency. This helps to negate + some of the reduced cost associated with argument registers which + unfairly promotes their use and increases register pressure */ +#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(REGNO) \ + (TARGET_MIPS16 && optimize_size \ + ? ((REGNO) >= 4 && (REGNO) <= 7 ? 2 : 0) : 0) + /* We generally want to put call-clobbered registers ahead of call-saved ones. (IRA expects this.) */ diff --git gcc/config/mips/mips.md gcc/config/mips/mips.md index 1e3e9e6..ababd5e 100644 --- gcc/config/mips/mips.md +++ gcc/config/mips/mips.md @@ -1622,40 +1622,66 @@ ;; copy instructions. Reload therefore thinks that the second alternative ;; is two reloads more costly than the first. We add "*?*?" to the first ;; alternative as a counterweight. +;; +;; LRA simulates reload but the cost of reloading scratches is lower +;; than of the classic reload. For the time being, removing the counterweight +;; for LRA is more profitable. (define_insn "*mul_acc_si" - [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "register_operand" "d,d")) - (match_operand:SI 3 "register_operand" "0,d"))) - (clobber (match_scratch:SI 4 "=X,l")) - (clobber (match_scratch:SI 5 "=X,&d"))] + [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") + (match_operand:SI 2 "register_operand" "d,d,d")) + (match_operand:SI 3 "register_operand" "0,0,d"))) + (clobber (match_scratch:SI 4 "=X,X,l")) + (clobber (match_scratch:SI 5 "=X,X,&d"))] "GENERATE_MADD_MSUB && !TARGET_MIPS16" "@ madd\t%1,%2 + madd\t%1,%2 #" [(set_attr "type" "imadd") (set_attr "accum_in" "3") (set_attr "mode" "SI") - (set_attr "insn_count" "1,2")]) + (set_attr "insn_count" "1,1,2") + (set (attr "enabled") + (cond [(and (eq_attr "alternative" "0") + (match_test "TARGET_RELOAD")) + (const_string "yes") + (and (eq_attr "alternative" "1") + (match_test "!TARGET_RELOAD")) + (const_string "yes") + (eq_attr "alternative" "2") + (const_string "yes")] + (const_string "no")))]) ;; The same idea applies here. The middle alternative needs one less ;; clobber than the final alternative, so we add "*?" as a counterweight. (define_insn "*mul_acc_si_r3900" - [(set (match_operand:SI 0 "register_operand" "=l*?*?,d*?,d?") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") - (match_operand:SI 2 "register_operand" "d,d,d")) - (match_operand:SI 3 "register_operand" "0,l,d"))) - (clobber (match_scratch:SI 4 "=X,3,l")) - (clobber (match_scratch:SI 5 "=X,X,&d"))] + [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d*?,d?") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d,d") + (match_operand:SI 2 "register_operand" "d,d,d,d")) + (match_operand:SI 3 "register_operand" "0,0,l,d"))) + (clobber (match_scratch:SI 4 "=X,X,3,l")) + (clobber (match_scratch:SI 5 "=X,X,X,&d"))] "TARGET_MIPS3900 && !TARGET_MIPS16" "@ madd\t%1,%2 + madd\t%1,%2 madd\t%0,%1,%2 #" [(set_attr "type" "imadd") (set_attr "accum_in" "3") (set_attr "mode" "SI") - (set_attr "insn_count" "1,1,2")]) + (set_attr "insn_count" "1,1,1,2") + (set (attr "enabled") + (cond [(and (eq_attr "alternative" "0") + (match_test "TARGET_RELOAD")) + (const_string "yes") + (and (eq_attr "alternative" "1") + (match_test "!TARGET_RELOAD")) + (const_string "yes") + (eq_attr "alternative" "2,3") + (const_string "yes")] + (const_string "no")))]) ;; Split *mul_acc_si if both the source and destination accumulator ;; values are GPRs. @@ -1859,20 +1885,31 @@ ;; See the comment above *mul_add_si for details. (define_insn "*mul_sub_si" - [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?") - (minus:SI (match_operand:SI 1 "register_operand" "0,d") - (mult:SI (match_operand:SI 2 "register_operand" "d,d") - (match_operand:SI 3 "register_operand" "d,d")))) - (clobber (match_scratch:SI 4 "=X,l")) - (clobber (match_scratch:SI 5 "=X,&d"))] + [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?") + (minus:SI (match_operand:SI 1 "register_operand" "0,0,d") + (mult:SI (match_operand:SI 2 "register_operand" "d,d,d") + (match_operand:SI 3 "register_operand" "d,d,d")))) + (clobber (match_scratch:SI 4 "=X,X,l")) + (clobber (match_scratch:SI 5 "=X,X,&d"))] "GENERATE_MADD_MSUB" "@ msub\t%2,%3 + msub\t%2,%3 #" [(set_attr "type" "imadd") (set_attr "accum_in" "1") (set_attr "mode" "SI") - (set_attr "insn_count" "1,2")]) + (set_attr "insn_count" "1,1,2") + (set (attr "enabled") + (cond [(and (eq_attr "alternative" "0") + (match_test "TARGET_RELOAD")) + (const_string "yes") + (and (eq_attr "alternative" "1") + (match_test "!TARGET_RELOAD")) + (const_string "yes") + (eq_attr "alternative" "2") + (const_string "yes")] + (const_string "no")))]) ;; Split *mul_sub_si if both the source and destination accumulator ;; values are GPRs. @@ -2986,31 +3023,14 @@ (set_attr "mode" "")]) (define_insn "*and3_mips16" - [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d") - (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%W,W,W,d,0") - (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Yw,d")))] + [(set (match_operand:GPR 0 "register_operand" "=d,d") + (and:GPR (match_operand:GPR 1 "register_operand" "%d,0") + (match_operand:GPR 2 "and_operand" "Yw,d")))] "TARGET_MIPS16 && and_operands_ok (mode, operands[1], operands[2])" -{ - switch (which_alternative) - { - case 0: - operands[1] = gen_lowpart (QImode, operands[1]); - return "lbu\t%0,%1"; - case 1: - operands[1] = gen_lowpart (HImode, operands[1]); - return "lhu\t%0,%1"; - case 2: - operands[1] = gen_lowpart (SImode, operands[1]); - return "lwu\t%0,%1"; - case 3: - return "#"; - case 4: - return "and\t%0,%2"; - default: - gcc_unreachable (); - } -} - [(set_attr "move_type" "load,load,load,shift_shift,logical") + "@ + # + and\t%0,%2" + [(set_attr "move_type" "shift_shift,logical") (set_attr "mode" "")]) (define_expand "ior3" @@ -4139,7 +4159,7 @@ [(set (match_operand:DI 0 "register_operand" "=d") (match_operand:DI 1 "absolute_symbolic_operand" "")) (clobber (match_scratch:DI 2 "=&d"))] - "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" + "!TARGET_MIPS16 && TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" "#" "&& reload_completed" [(set (match_dup 0) (high:DI (match_dup 3))) diff --git gcc/config/mips/mips.opt gcc/config/mips/mips.opt index 6ee5398..a044031 100644 --- gcc/config/mips/mips.opt +++ gcc/config/mips/mips.opt @@ -380,6 +380,10 @@ msynci Target Report Mask(SYNCI) Use synci instruction to invalidate i-cache +mreload +Target Report Var(TARGET_RELOAD) +Use reload instead of lra + mtune= Target RejectNegative Joined Var(mips_tune_option) ToLower Enum(mips_arch_opt_value) -mtune=PROCESSOR Optimize the output for PROCESSOR diff --git gcc/lra-constraints.c gcc/lra-constraints.c index ba4d489..ab85495 100644 --- gcc/lra-constraints.c +++ gcc/lra-constraints.c @@ -2615,6 +2615,39 @@ valid_address_p (struct address_info *ad) return ok_p; } +/* Make reload base reg from address AD. */ +static rtx +base_to_reg (struct address_info *ad) +{ + enum reg_class cl; + int code = -1; + rtx new_inner = NULL_RTX; + rtx new_reg = NULL_RTX; + rtx insn; + rtx last_insn = get_last_insn(); + + lra_assert (ad->base == ad->base_term && ad->disp == ad->disp_term); + cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, + get_index_code (ad)); + new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, + cl, "base"); + new_inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, + ad->disp_term == NULL + ? gen_int_mode (0, ad->mode) + : *ad->disp_term); + if (!valid_address_p (ad->mode, new_inner, ad->as)) + return NULL_RTX; + insn = emit_insn (gen_rtx_SET (ad->mode, new_reg, *ad->base_term)); + code = recog_memoized (insn); + if (code < 0) + { + delete_insns_since (last_insn); + return NULL_RTX; + } + + return new_inner; +} + /* Make reload base reg + disp from address AD. Return the new pseudo. */ static rtx base_plus_disp_to_reg (struct address_info *ad) @@ -2818,6 +2851,8 @@ process_address (int nop, rtx *before, rtx *after) 3) the address is a frame address with an invalid offset. + 4) the address is a frame address with an invalid base. + All these cases involve a non-autoinc address, so there is no point revalidating other types. */ if (ad.autoinc_p || valid_address_p (&ad)) @@ -2899,14 +2934,19 @@ process_address (int nop, rtx *before, rtx *after) int regno; enum reg_class cl; rtx set, insns, last_insn; + /* Try to reload base into register only if the base is invalid + for the address but with valid offset, case (4) above. */ + start_sequence (); + new_reg = base_to_reg (&ad); + /* base + disp => new base, cases (1) and (3) above. */ /* Another option would be to reload the displacement into an index register. However, postreload has code to optimize address reloads that have the same base and different displacements, so reloading into an index register would not necessarily be a win. */ - start_sequence (); - new_reg = base_plus_disp_to_reg (&ad); + if (new_reg == NULL_RTX) + new_reg = base_plus_disp_to_reg (&ad); insns = get_insns (); last_insn = get_last_insn (); /* If we generated at least two insns, try last insn source as diff --git gcc/rtlanal.c gcc/rtlanal.c index 7a9efec..f699d17 100644 --- gcc/rtlanal.c +++ gcc/rtlanal.c @@ -5577,7 +5577,8 @@ get_base_term (rtx *inner) inner = strip_address_mutations (&XEXP (*inner, 0)); if (REG_P (*inner) || MEM_P (*inner) - || GET_CODE (*inner) == SUBREG) + || GET_CODE (*inner) == SUBREG + || CONSTANT_P (*inner)) return inner; return 0; }