From patchwork Mon Jan 10 20:31:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 78209 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 A5348B710C for ; Tue, 11 Jan 2011 07:34:22 +1100 (EST) Received: (qmail 20153 invoked by alias); 10 Jan 2011 20:32:50 -0000 Received: (qmail 19775 invoked by uid 22791); 10 Jan 2011 20:32:42 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE 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:33 +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 p0AKWVig032548 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 10 Jan 2011 12:32:31 -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 p0AKWVXd006778; Mon, 10 Jan 2011 12:32:31 -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 p0AKWSmw019701; Mon, 10 Jan 2011 12:32:29 -0800 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id p0AKWR4t019700; Mon, 10 Jan 2011 12:32:27 -0800 From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: nickc@redhat.com, law@redhat.com, Richard Henderson Subject: [PATCH 13/28] mn10300: cleanup secondary reloads Date: Mon, 10 Jan 2011 12:31:42 -0800 Message-Id: <1294691517-19580-14-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 Handles output reloads for QI/HImode properly; previously we were only handing input reloads properly. Handles reloads involving the stack pointer better; note that the AM33 allows copying SP to DATA_REGS as well as ADDRESS and EXTENDED. --- gcc/config/mn10300/mn10300-protos.h | 1 - gcc/config/mn10300/mn10300.c | 120 +++++++++++++++++++--------------- gcc/config/mn10300/mn10300.h | 3 - gcc/config/mn10300/mn10300.md | 60 ++++++++++------- 4 files changed, 102 insertions(+), 82 deletions(-) diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h index d6cf850..37968ff 100644 --- a/gcc/config/mn10300/mn10300-protos.h +++ b/gcc/config/mn10300/mn10300-protos.h @@ -35,7 +35,6 @@ extern Cstar mn10300_output_cmp (rtx, rtx); extern void mn10300_print_operand (FILE *, rtx, int); extern void mn10300_print_operand_address (FILE *, rtx); extern void mn10300_print_reg_list (FILE *, int); -extern Rclas mn10300_secondary_reload_class (Rclas, Mmode, rtx); extern Mmode mn10300_select_cc_mode (rtx); extern int mn10300_store_multiple_operation (rtx, Mmode); extern int mn10300_symbolic_operand (rtx, Mmode); diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 5f2d63b..78b5b5d 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -1321,7 +1321,7 @@ static reg_class_t mn10300_preferred_reload_class (rtx x, reg_class_t rclass) { if (x == stack_pointer_rtx && rclass != SP_REGS) - return ADDRESS_OR_EXTENDED_REGS; + return BASE_REG_CLASS; else if (MEM_P (x) || (REG_P (x) && !HARD_REGISTER_P (x)) @@ -1339,72 +1339,83 @@ static reg_class_t mn10300_preferred_output_reload_class (rtx x, reg_class_t rclass) { if (x == stack_pointer_rtx && rclass != SP_REGS) - return ADDRESS_OR_EXTENDED_REGS; - + return BASE_REG_CLASS; return rclass; } -/* What (if any) secondary registers are needed to move IN with mode - MODE into a register in register class RCLASS. - - We might be able to simplify this. */ +/* Implement TARGET_SECONDARY_RELOAD. */ -enum reg_class -mn10300_secondary_reload_class (enum reg_class rclass, enum machine_mode mode, - rtx in) +static reg_class_t +mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, + enum machine_mode mode, secondary_reload_info *sri) { - rtx inner = in; - - /* Strip off any SUBREG expressions from IN. Basically we want - to know if IN is a pseudo or (subreg (pseudo)) as those can - turn into MEMs during reload. */ - while (GET_CODE (inner) == SUBREG) - inner = SUBREG_REG (inner); - - /* Memory loads less than a full word wide can't have an - address or stack pointer destination. They must use - a data register as an intermediate register. */ - if ((MEM_P (in) - || (REG_P (inner) - && REGNO (inner) >= FIRST_PSEUDO_REGISTER)) - && (mode == QImode || mode == HImode) - && (rclass == ADDRESS_REGS || rclass == SP_REGS - || rclass == SP_OR_ADDRESS_REGS)) + enum reg_class rclass = (enum reg_class) rclass_i; + enum reg_class xclass = NO_REGS; + unsigned int xregno = INVALID_REGNUM; + + if (REG_P (x)) { - if (TARGET_AM33) - return DATA_OR_EXTENDED_REGS; - return DATA_REGS; + xregno = REGNO (x); + if (xregno >= FIRST_PSEUDO_REGISTER) + xregno = true_regnum (x); + if (xregno != INVALID_REGNUM) + xclass = REGNO_REG_CLASS (xregno); + } + + if (!TARGET_AM33) + { + /* Memory load/stores less than a full word wide can't have an + address or stack pointer destination. They must use a data + register as an intermediate register. */ + if (rclass != DATA_REGS + && (mode == QImode || mode == HImode) + && xclass == NO_REGS) + return DATA_REGS; + + /* We can only move SP to/from an address register. */ + if (in_p + && rclass == SP_REGS + && xclass != ADDRESS_REGS) + return ADDRESS_REGS; + if (!in_p + && xclass == SP_REGS + && rclass != ADDRESS_REGS + && rclass != SP_OR_ADDRESS_REGS) + return ADDRESS_REGS; } - /* We can't directly load sp + const_int into a data register; - we must use an address register as an intermediate. */ - if (rclass != SP_REGS - && rclass != ADDRESS_REGS + /* We can't directly load sp + const_int into a register; + we must use an address register as an scratch. */ + if (in_p + && rclass != SP_REGS && rclass != SP_OR_ADDRESS_REGS && rclass != SP_OR_EXTENDED_REGS - && rclass != ADDRESS_OR_EXTENDED_REGS && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS - && (in == stack_pointer_rtx - || (GET_CODE (in) == PLUS - && (XEXP (in, 0) == stack_pointer_rtx - || XEXP (in, 1) == stack_pointer_rtx)))) - return ADDRESS_REGS; + && GET_CODE (x) == PLUS + && (XEXP (x, 0) == stack_pointer_rtx + || XEXP (x, 1) == stack_pointer_rtx)) + { + sri->icode = CODE_FOR_reload_plus_sp_const; + return NO_REGS; + } + /* We can't load/store an FP register from a constant address. */ if (TARGET_AM33_2 - && rclass == FP_REGS) + && (rclass == FP_REGS || xclass == FP_REGS) + && (xclass == NO_REGS || rclass == NO_REGS)) { - /* We can't load directly into an FP register from a - constant address. */ - if (MEM_P (in) - && CONSTANT_ADDRESS_P (XEXP (in, 0))) - return DATA_OR_EXTENDED_REGS; + rtx addr = NULL; + + if (xregno >= FIRST_PSEUDO_REGISTER && xregno != INVALID_REGNUM) + { + addr = reg_equiv_mem [xregno]; + if (addr) + addr = XEXP (addr, 0); + } + else if (MEM_P (x)) + addr = XEXP (x, 0); - /* Handle case were a pseudo may not get a hard register - but has an equivalent memory location defined. */ - if (REG_P (inner) - && REGNO (inner) >= FIRST_PSEUDO_REGISTER - && reg_equiv_mem [REGNO (inner)] - && CONSTANT_ADDRESS_P (XEXP (reg_equiv_mem [REGNO (inner)], 0))) + if (addr && CONSTANT_ADDRESS_P (addr)) return DATA_OR_EXTENDED_REGS; } @@ -2720,7 +2731,10 @@ mn10300_conditional_register_usage (void) #undef TARGET_PREFERRED_RELOAD_CLASS #define TARGET_PREFERRED_RELOAD_CLASS mn10300_preferred_reload_class #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS -#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mn10300_preferred_output_reload_class +#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS \ + mn10300_preferred_output_reload_class +#undef TARGET_SECONDARY_RELOAD +#define TARGET_SECONDARY_RELOAD mn10300_secondary_reload #undef TARGET_TRAMPOLINE_INIT #define TARGET_TRAMPOLINE_INIT mn10300_trampoline_init diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h index f5f6416..4fe0c48 100644 --- a/gcc/config/mn10300/mn10300.h +++ b/gcc/config/mn10300/mn10300.h @@ -416,9 +416,6 @@ enum reg_class #define LIMIT_RELOAD_CLASS(MODE, CLASS) \ (!TARGET_AM33 && (MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS) -#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ - mn10300_secondary_reload_class(CLASS,MODE,IN) - /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 6e0e1a2..457b17a 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -274,42 +274,52 @@ ;; We use this to handle addition of two values when one operand is the ;; stack pointer and the other is a memory reference of some kind. Reload ;; does not handle them correctly without this expander. -(define_expand "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=a") +(define_expand "reload_plus_sp_const" + [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "impossible_plus_operand" "")) - (clobber (match_operand:SI 2 "register_operand" "=&r"))] + (clobber (match_operand:SI 2 "register_operand" "=&A"))] "" " { - gcc_assert (REGNO (operands[0]) != REGNO (operands[2])); + rtx dest, scratch, other; - if (XEXP (operands[1], 0) == stack_pointer_rtx) + dest = operands[0]; + scratch = operands[2]; + + other = XEXP (operands[1], 1); + if (other == stack_pointer_rtx) + other = XEXP (operands[1], 0); + + if (true_regnum (other) == true_regnum (dest)) { - if (GET_CODE (XEXP (operands[1], 1)) == SUBREG - && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 1))) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 1)))))) - emit_move_insn (operands[2], - gen_rtx_ZERO_EXTEND - (GET_MODE (XEXP (operands[1], 1)), - SUBREG_REG (XEXP (operands[1], 1)))); - else - emit_move_insn (operands[2], XEXP (operands[1], 1)); - emit_move_insn (operands[0], XEXP (operands[1], 0)); + gcc_assert (true_regnum (scratch) != true_regnum (dest)); + emit_move_insn (scratch, stack_pointer_rtx); + emit_insn (gen_addsi3 (dest, dest, scratch)); + } + else if (TARGET_AM33 || REGNO_REG_CLASS (true_regnum (dest)) == ADDRESS_REGS) + { + emit_move_insn (dest, stack_pointer_rtx); + if (other == stack_pointer_rtx) + emit_insn (gen_addsi3 (dest, dest, dest)); + else if (other != const0_rtx) + emit_insn (gen_addsi3 (dest, dest, other)); } else { - if (GET_CODE (XEXP (operands[1], 0)) == SUBREG - && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 0))) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 0)))))) - emit_move_insn (operands[2], - gen_rtx_ZERO_EXTEND - (GET_MODE (XEXP (operands[1], 0)), - SUBREG_REG (XEXP (operands[1], 0)))); + emit_move_insn (scratch, stack_pointer_rtx); + if (other == stack_pointer_rtx) + { + emit_move_insn (dest, scratch); + emit_insn (gen_addsi3 (dest, dest, dest)); + } + else if (other != const0_rtx) + { + emit_move_insn (dest, other); + emit_insn (gen_addsi3 (dest, dest, scratch)); + } else - emit_move_insn (operands[2], XEXP (operands[1], 0)); - emit_move_insn (operands[0], XEXP (operands[1], 1)); + emit_move_insn (dest, scratch); } - emit_insn (gen_addsi3 (operands[0], operands[0], operands[2])); DONE; }")