From patchwork Tue Sep 17 21:01:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 275541 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ABD8B2C00CA for ; Wed, 18 Sep 2013 07:01:18 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :message-id:from:to:subject; q=dns; s=default; b=LYLmpTMdlfsO1Ml Wd9O0BdET3LkNtYiPSoUQeTyeMfibFqHVkywnMYrjXUU8H5pDilLsi1MCMV7LToi TGUDvITmgmGODEtZUTS0iJFXuTwjz6Eqo5qqWXVGEl0xS0daidPGytDPyaWqwko2 sLUaggWtiBMlhcB3YLg7yKZyoCpY= 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:date :message-id:from:to:subject; s=default; bh=GQLNKUbzNFB0lhIalyCAB s5lx5c=; b=qtHueqWioWnPHh9d4f+xbptbRStLStlJbhCZ4AkAZ5O4t/oqEdrC9 Hy46z2bixem1bE2yNIgQywAHdNrECNlXiBYfI0ZbY8B6Gf7p+CA6hIbfDpU70raK 5bQkPrBRdsHpAsRzb3FaqYR5Qshce3AZfUTgwvkO8v3zvQS+jL4+Tg= Received: (qmail 8565 invoked by alias); 17 Sep 2013 21:01:11 -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 8553 invoked by uid 89); 17 Sep 2013 21:01:11 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 17 Sep 2013 21:01:11 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.2 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r8HL17vT020305 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 17 Sep 2013 17:01:07 -0400 Received: from greed.delorie.com (ovpn-113-20.phx2.redhat.com [10.3.113.20]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r8HL16O8019838 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 17 Sep 2013 17:01:06 -0400 Received: from greed.delorie.com (greed.delorie.com [127.0.0.1]) by greed.delorie.com (8.14.4/8.14.4) with ESMTP id r8HL157s009171 for ; Tue, 17 Sep 2013 17:01:05 -0400 Received: (from dj@localhost) by greed.delorie.com (8.14.4/8.14.4/Submit) id r8HL15Tb009170; Tue, 17 Sep 2013 17:01:05 -0400 Date: Tue, 17 Sep 2013 17:01:05 -0400 Message-Id: <201309172101.r8HL15Tb009170@greed.delorie.com> From: DJ Delorie To: gcc-patches@gcc.gnu.org Subject: [rl78] fix far address optimizations X-IsSubscribed: yes Track both parts of far addresses so they don't get optimized away. Committed. * config/rl78/constraints.md: For each W* constraint, rename to C* and create a W* constraint that checks for an optional ES: prefix pattern also. * config/rl78/rl78.md (UNS_ES_ADDR): New. (es_addr): New. Used to wrap far addresses. * config/rl78/rl78-protos.h (rl78_es_addr): New. (rl78_es_base): New. * config/rl78/rl78.c (rl78_as_legitimate_address): Accept "unspec" wrapped far addresses. (rl78_print_operand_1): Unwrap far addresses before processing. (rl78_lo16): Wrap far addresses in unspecs. (rl78_es_addr): New. (rl78_es_base): New. (insn_ok_now): Check for not-yet-wrapped far addresses. (transcode_memory_rtx): Properly re-wrap far addresses. Index: config/rl78/constraints.md =================================================================== --- config/rl78/constraints.md (revision 202665) +++ config/rl78/constraints.md (working copy) @@ -200,103 +200,155 @@ (define_register_constraint "Zint" "INT_REGS" "The interrupt registers.") ; All the memory addressing schemes the RL78 supports ; of the form W {register} {bytes of offset} ; or W {register} {register} +; Additionally, the Cxx forms are the same as the Wxx forms, but without +; the ES: override. ; absolute address -(define_memory_constraint "Wab" +(define_memory_constraint "Cab" "[addr]" (and (match_code "mem") (ior (match_test "CONSTANT_P (XEXP (op, 0))") (match_test "GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF")) ) ) +(define_memory_constraint "Wab" + "es:[addr]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cab (rl78_es_base (op)) + || satisfies_constraint_Cab (op)") + ) -(define_memory_constraint "Wbc" +(define_memory_constraint "Cbc" "word16[BC]" (and (match_code "mem") (ior (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) == BC_REG")) (and (match_code "plus" "0") (and (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == BC_REG")) (match_test "uword_operand (XEXP (XEXP (op, 0), 1), VOIDmode)")))) ) ) +(define_memory_constraint "Wbc" + "es:word16[BC]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cbc (rl78_es_base (op)) + || satisfies_constraint_Cbc (op)") + ) -(define_memory_constraint "Wde" +(define_memory_constraint "Cde" "[DE]" (and (match_code "mem") (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) == DE_REG"))) ) +(define_memory_constraint "Wde" + "es:[DE]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cde (rl78_es_base (op)) + || satisfies_constraint_Cde (op)") + ) -(define_memory_constraint "Wca" +(define_memory_constraint "Cca" "[AX..HL] for calls" (and (match_code "mem") (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) <= HL_REG"))) ) +(define_memory_constraint "Wca" + "es:[AX..HL] for calls" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cca (rl78_es_base (op)) + || satisfies_constraint_Cca (op)") + ) -(define_memory_constraint "Wcv" +(define_memory_constraint "Ccv" "[AX..HL,r8-r23] for calls" (and (match_code "mem") (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) < 24"))) ) +(define_memory_constraint "Wcv" + "es:[AX..HL,r8-r23] for calls" + (match_test "rl78_es_addr (op) && satisfies_constraint_Ccv (rl78_es_base (op)) + || satisfies_constraint_Ccv (op)") + ) -(define_memory_constraint "Wd2" +(define_memory_constraint "Cd2" "word16[DE]" (and (match_code "mem") (ior (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) == DE_REG")) (and (match_code "plus" "0") (and (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == DE_REG")) (match_test "uword_operand (XEXP (XEXP (op, 0), 1), VOIDmode)")))) ) ) +(define_memory_constraint "Wd2" + "es:word16[DE]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cd2 (rl78_es_base (op)) + || satisfies_constraint_Cd2 (op)") + ) -(define_memory_constraint "Whl" +(define_memory_constraint "Chl" "[HL]" (and (match_code "mem") (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) == HL_REG"))) ) +(define_memory_constraint "Whl" + "es:[HL]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Chl (rl78_es_base (op)) + || satisfies_constraint_Chl (op)") + ) -(define_memory_constraint "Wh1" +(define_memory_constraint "Ch1" "byte8[HL]" (and (match_code "mem") (and (match_code "plus" "0") (and (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == HL_REG")) (match_test "ubyte_operand (XEXP (XEXP (op, 0), 1), VOIDmode)")))) ) +(define_memory_constraint "Wh1" + "es:byte8[HL]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Ch1 (rl78_es_base (op)) + || satisfies_constraint_Ch1 (op)") + ) -(define_memory_constraint "Whb" +(define_memory_constraint "Chb" "[HL+B]" (and (match_code "mem") (match_test "rl78_hl_b_c_addr_p (XEXP (op, 0))")) ) +(define_memory_constraint "Whb" + "es:[HL+B]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Chb (rl78_es_base (op)) + || satisfies_constraint_Chb (op)") + ) -(define_memory_constraint "Ws1" +(define_memory_constraint "Cs1" "word8[SP]" (and (match_code "mem") (ior (and (match_code "reg" "0") (match_test "REGNO (XEXP (op, 0)) == SP_REG")) (and (match_code "plus" "0") (and (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")) (match_test "ubyte_operand (XEXP (XEXP (op, 0), 1), VOIDmode)")))) ) ) +(define_memory_constraint "Ws1" + "es:word8[SP]" + (match_test "rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op)) + || satisfies_constraint_Cs1 (op)") + ) (define_memory_constraint "Wfr" "ES/CS far pointer" (and (match_code "mem") (match_test "rl78_far_p (op)")) ) Index: config/rl78/rl78-protos.h =================================================================== --- config/rl78/rl78-protos.h (revision 202665) +++ config/rl78/rl78-protos.h (working copy) @@ -39,6 +39,9 @@ enum reg_class rl78_mode_code_base_reg_c bool rl78_peep_movhi_p (rtx *); bool rl78_real_insns_ok (void); void rl78_register_pragmas (void); bool rl78_regno_mode_code_ok_for_base_p (int, enum machine_mode, addr_space_t, int, int); void rl78_setup_peep_movhi (rtx *); bool rl78_virt_insns_ok (void); + +bool rl78_es_addr (rtx); +rtx rl78_es_base (rtx); Index: config/rl78/rl78.md =================================================================== --- config/rl78/rl78.md (revision 202665) +++ config/rl78/rl78.md (working copy) @@ -42,12 +42,13 @@ (UNS_PROLOG 1) (UNS_EPILOG 1) (UNS_RETI 2) (UNS_RETB 3) (UNS_SET_RB 10) + (UNS_ES_ADDR 11) (UNS_TRAMPOLINE_INIT 20) (UNS_TRAMPOLINE_UNINIT 21) (UNS_NONLOCAL_GOTO 22) ]) @@ -429,6 +430,14 @@ nop ; Additional nop for MAC movw ax, !0xf00e0 ; MDCL movw %H0, ax ; end of mulsi macro" [(set_attr "valloc" "macax")] ) + +(define_expand "es_addr" + [(unspec:SI [(reg:QI ES_REG) + (match_operand:HI 0 "" "") + ] UNS_ES_ADDR)] + "" + "" +) Index: config/rl78/rl78.c =================================================================== --- config/rl78/rl78.c (revision 202665) +++ config/rl78/rl78.c (working copy) @@ -855,12 +855,16 @@ rl78_is_legitimate_constant (enum machin bool rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED) { rtx base, index, addend; + if (GET_CODE (x) == UNSPEC + && XINT (x, 1) == UNS_ES_ADDR) + x = XVECEXP (x, 0, 1); + if (as == ADDR_SPACE_GENERIC && GET_MODE (x) == SImode) return false; if (! characterize_address (x, &base, &index, &addend)) return false; @@ -1287,13 +1291,16 @@ rl78_print_operand_1 (FILE * file, rtx o case MEM: if (letter == 'A') rl78_print_operand_1 (file, XEXP (op, 0), letter); else { if (rl78_far_p (op)) - fprintf (file, "es:"); + { + fprintf (file, "es:"); + op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1)); + } if (letter == 'H') { op = adjust_address (op, HImode, 2); letter = 0; } if (letter == 'h') @@ -1844,12 +1851,14 @@ During devirtualization, a simple regist would be better to run a full CSE/propogation pass on it through, or re-run regmove, but that has not yet been attempted. */ #define DEBUG_ALLOC 0 +#define OP(x) (*recog_data.operand_loc[x]) + /* This array is used to hold knowledge about the contents of the real registers (A ... H), the memory-based registers (r8 ... r31) and the first NUM_STACK_LOCS words on the stack. We use this to avoid generating redundant move instructions. A value in the range 0 .. 31 indicates register A .. r31. @@ -2069,19 +2078,45 @@ already_contains (rtx loc, rtx value) if (GET_MODE (loc) == HImode) return content_memory [index + 1] == val + 1; return true; } +bool +rl78_es_addr (rtx addr) +{ + if (GET_CODE (addr) == MEM) + addr = XEXP (addr, 0); + if (GET_CODE (addr) != UNSPEC) + return false; + if (XINT (addr, 1) != UNS_ES_ADDR) + return false; + return true; +} + +rtx +rl78_es_base (rtx addr) +{ + if (GET_CODE (addr) == MEM) + addr = XEXP (addr, 0); + addr = XVECEXP (addr, 0, 1); + if (GET_CODE (addr) == CONST + && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT) + addr = XEXP (XEXP (addr, 0), 0); + /* Mode doesn't matter here. */ + return gen_rtx_MEM (HImode, addr); +} + /* Rescans an insn to see if it's recognized again. This is done carefully to ensure that all the constraint information is accurate for the newly matched insn. */ static bool insn_ok_now (rtx insn) { rtx pattern = PATTERN (insn); + int i; INSN_CODE (insn) = -1; if (recog (pattern, insn, 0) > -1) { extract_insn (insn); @@ -2092,12 +2127,20 @@ insn_ok_now (rtx insn) debug_rtx (insn); fprintf (stderr, "\033[0m"); #endif if (SET_P (pattern)) record_content (SET_DEST (pattern), SET_SRC (pattern)); + /* We need to detect far addresses that haven't been + converted to es/lo16 format. */ + for (i=0; i= 8 @@ -2192,20 +2233,26 @@ EM2 (int line ATTRIBUTE_UNUSED, rtx r) #define EM(x) EM2 (__LINE__, x) /* Return a suitable RTX for the low half of a __far address. */ static rtx rl78_lo16 (rtx addr) { + rtx r; + if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST) { - rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0)); + r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0)); r = gen_rtx_CONST (HImode, r); - return r; } - return rl78_subreg (HImode, addr, SImode, 0); + else + r = rl78_subreg (HImode, addr, SImode, 0); + + r = gen_es_addr (r); + + return r; } /* Return a suitable RTX for the high half's lower byte of a __far address. */ static rtx rl78_hi8 (rtx addr) { @@ -2303,12 +2350,13 @@ gen_and_emit_move (rtx to, rtx from, rtx return M. Any needed insns are emitted before BEFORE. */ static rtx transcode_memory_rtx (rtx m, rtx newbase, rtx before) { rtx base, index, addendr; int addend = 0; + int need_es = 0; if (! MEM_P (m)) return m; if (GET_MODE (XEXP (m, 0)) == SImode) { @@ -2319,12 +2367,13 @@ transcode_memory_rtx (rtx m, rtx newbase #endif emit_insn_before (EM (gen_movqi (A, seg)), before); emit_insn_before (EM (gen_movqi_es (A)), before); record_content (A, NULL_RTX); m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0))); + need_es = 1; } characterize_address (XEXP (m, 0), & base, & index, & addendr); gcc_assert (index == NULL_RTX); #if DEBUG_ALLOC @@ -2378,13 +2427,16 @@ transcode_memory_rtx (rtx m, rtx newbase } #if DEBUG_ALLOC fprintf (stderr, "\033[33m"); debug_rtx (m); #endif - m = change_address (m, GET_MODE (m), base); + if (need_es) + m = change_address (m, GET_MODE (m), gen_es_addr (base)); + else + m = change_address (m, GET_MODE (m), base); #if DEBUG_ALLOC debug_rtx (m); fprintf (stderr, "\033[0m"); #endif return m; }