From patchwork Mon Dec 5 16:53:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 86593 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp1581064qgi; Mon, 5 Dec 2016 08:54:25 -0800 (PST) X-Received: by 10.98.35.5 with SMTP id j5mr57841713pfj.91.1480956865822; Mon, 05 Dec 2016 08:54:25 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id e13si15232384pgf.220.2016.12.05.08.54.25 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Dec 2016 08:54:25 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-443489-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-443489-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-443489-patch=linaro.org@gcc.gnu.org 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:subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; q=dns; s=default; b=Vdp yRXSy78yIQS8XKd7VrNT4v9KyCUneh+D3WiZ8J8BTWfvqrXQEFdywp1j4Q9Y/O2x Nhh8g0ixQTrVsgoijhPMGEL7ZozS2MPvVfq4bIqK9DdVlTnQU6P4wLuM7xn7S8HY XgTp2y3G6d4NWip8E5J4HUvAIc613YIYnDh1mKKE= 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:subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=default; bh=VqhcRNw33 B4np1hLtA3XwHXVtXQ=; b=vw+yqxlKxVW/ABpr+DKRKQ8/zjESWj6QVAfZKuzqs It3u14LIjhfiLk908OjzsvFw25z9LJ3RYwZjG5E9dgI4p7S6ldkTt7jF4UpeoiLw w5Eje54CBAO42GEAnzvW67BGnhfzELRBklt8vZaoR98g4Wn44wexEw2NkrBRBjHB Ic= Received: (qmail 29380 invoked by alias); 5 Dec 2016 16:54:06 -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 29299 invoked by uid 89); 5 Dec 2016 16:54:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.4 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=no version=3.3.2 spammy=rt, thinko, ew, fo X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 05 Dec 2016 16:53:55 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 5F19D812EB for ; Mon, 5 Dec 2016 17:53:53 +0100 (CET) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Un1ZJbmoQzuM for ; Mon, 5 Dec 2016 17:53:53 +0100 (CET) Received: from polaris.localnet (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id 09203812E0 for ; Mon, 5 Dec 2016 17:53:53 +0100 (CET) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: Re: [SPARC] Disable U constraint with LRA Date: Mon, 05 Dec 2016 17:53:52 +0100 Message-ID: <3012293.QXQ48v4edW@polaris> User-Agent: KMail/4.14.10 (Linux/3.16.7-48-desktop; KDE/4.14.9; x86_64; ; ) In-Reply-To: <10524940.hq2ygGAiKI@polaris> References: <10524940.hq2ygGAiKI@polaris> MIME-Version: 1.0 > Fixed by disabling the relevant alternatives in the few patterns using the > constraint and replacing it with a simple r constraint. This yields a clean > C testsuite in 32-bit mode. There was a thinko in the patch: the U constraint cannot be just replaced with r as-is, because it is matched with the T constraint so, if the double-word register is not aligned, the double-word move needs to be split and this will require an offsetable memory reference, what T doesn't guarantee. This was generating an illegal instruction for ACATS cxac004 at -O and above. Fixed by the attached patch, which also overhauls the 3 series of double-word move splitters in 32-bit mode. Tested on SPARC/Solaris w/ and w/o -mlra in 32-bit mode, applied on the mainline. 2016-12-05 Eric Botcazou * config/sparc/sparc-protos.h (sparc_splitdi_legitimate): Rename to.. (sparc_split_reg_mem_legitimate): ...this. (sparc_split_reg_mem): Declare. (sparc_split_mem_reg): Likewise. (sparc_split_regreg_legitimate): Rename to... (sparc_split_reg_reg_legitimate): ...this. * config/sparc/sparc.c (sparc_splitdi_legitimate): Rename to... (sparc_split_reg_mem_legitimate): ...this. (sparc_split_reg_mem): New function. (sparc_split_mem_reg): Likewise. (sparc_split_regreg_legitimate): Rename to... (sparc_split_reg_reg_legitimate): ...this. (sparc_split_reg_reg): New function. * config/sparc/sparc.md (lra): Remove "none" value. (enabled): Adjust to above change. (*movdi_insn_sp32): Remove new (r,T) alternative and reorder others. (DImode splitters): Adjust to above renamings and use new functions. (*movdf_insn_sp32): Remove new (r,T) alternative and reorder others. (DFmode splitters): Adjust to above renamings and use new functions. (*mov_insn_sp64): Replace C with Z constraint and use W constraint in conjunction with e. (*mov_insn_sp32): Remove new (r,T) alternative, add (o,Y) alternative and reorder others. (VM64:mode splitters): Adjust to above renamings and use new functions. -- Eric Botcazou Index: config/sparc/sparc-protos.h =================================================================== --- config/sparc/sparc-protos.h (revision 243172) +++ config/sparc/sparc-protos.h (working copy) @@ -68,8 +68,11 @@ extern void sparc_emit_call_insn (rtx, r extern void sparc_defer_case_vector (rtx, rtx, int); extern bool sparc_expand_move (machine_mode, rtx *); extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx); -extern int sparc_splitdi_legitimate (rtx, rtx); -extern int sparc_split_regreg_legitimate (rtx, rtx); +extern int sparc_split_reg_mem_legitimate (rtx, rtx); +extern void sparc_split_reg_mem (rtx, rtx, machine_mode); +extern void sparc_split_mem_reg (rtx, rtx, machine_mode); +extern int sparc_split_reg_reg_legitimate (rtx, rtx); +extern void sparc_split_reg_reg (rtx, rtx, machine_mode); extern const char *output_ubranch (rtx, rtx_insn *); extern const char *output_cbranch (rtx, rtx, int, int, int, rtx_insn *); extern const char *output_return (rtx_insn *); Index: config/sparc/sparc.c =================================================================== --- config/sparc/sparc.c (revision 243172) +++ config/sparc/sparc.c (working copy) @@ -8484,46 +8484,82 @@ order_regs_for_local_alloc (void) } /* Return 1 if REG and MEM are legitimate enough to allow the various - mem<-->reg splits to be run. */ + MEM<-->REG splits to be run. */ int -sparc_splitdi_legitimate (rtx reg, rtx mem) +sparc_split_reg_mem_legitimate (rtx reg, rtx mem) { /* Punt if we are here by mistake. */ gcc_assert (reload_completed); /* We must have an offsettable memory reference. */ - if (! offsettable_memref_p (mem)) + if (!offsettable_memref_p (mem)) return 0; /* If we have legitimate args for ldd/std, we do not want the split to happen. */ - if ((REGNO (reg) % 2) == 0 - && mem_min_alignment (mem, 8)) + if ((REGNO (reg) % 2) == 0 && mem_min_alignment (mem, 8)) return 0; /* Success. */ return 1; } -/* Like sparc_splitdi_legitimate but for REG <--> REG moves. */ +/* Split a REG <-- MEM move into a pair of moves in MODE. */ + +void +sparc_split_reg_mem (rtx dest, rtx src, machine_mode mode) +{ + rtx high_part = gen_highpart (mode, dest); + rtx low_part = gen_lowpart (mode, dest); + rtx word0 = adjust_address (src, mode, 0); + rtx word1 = adjust_address (src, mode, 4); + + if (reg_overlap_mentioned_p (high_part, word1)) + { + emit_move_insn_1 (low_part, word1); + emit_move_insn_1 (high_part, word0); + } + else + { + emit_move_insn_1 (high_part, word0); + emit_move_insn_1 (low_part, word1); + } +} + +/* Split a MEM <-- REG move into a pair of moves in MODE. */ + +void +sparc_split_mem_reg (rtx dest, rtx src, machine_mode mode) +{ + rtx word0 = adjust_address (dest, mode, 0); + rtx word1 = adjust_address (dest, mode, 4); + rtx high_part = gen_highpart (mode, src); + rtx low_part = gen_lowpart (mode, src); + + emit_move_insn_1 (word0, high_part); + emit_move_insn_1 (word1, low_part); +} + +/* Like sparc_split_reg_mem_legitimate but for REG <--> REG moves. */ int -sparc_split_regreg_legitimate (rtx reg1, rtx reg2) +sparc_split_reg_reg_legitimate (rtx reg1, rtx reg2) { - int regno1, regno2; + /* Punt if we are here by mistake. */ + gcc_assert (reload_completed); if (GET_CODE (reg1) == SUBREG) reg1 = SUBREG_REG (reg1); if (GET_CODE (reg1) != REG) return 0; - regno1 = REGNO (reg1); + const int regno1 = REGNO (reg1); if (GET_CODE (reg2) == SUBREG) reg2 = SUBREG_REG (reg2); if (GET_CODE (reg2) != REG) return 0; - regno2 = REGNO (reg2); + const int regno2 = REGNO (reg2); if (SPARC_INT_REG_P (regno1) && SPARC_INT_REG_P (regno2)) return 1; @@ -8538,6 +8574,30 @@ sparc_split_regreg_legitimate (rtx reg1, return 0; } +/* Split a REG <--> REG move into a pair of moves in MODE. */ + +void +sparc_split_reg_reg (rtx dest, rtx src, machine_mode mode) +{ + rtx dest1 = gen_highpart (mode, dest); + rtx dest2 = gen_lowpart (mode, dest); + rtx src1 = gen_highpart (mode, src); + rtx src2 = gen_lowpart (mode, src); + + /* Now emit using the real source and destination we found, swapping + the order if we detect overlap. */ + if (reg_overlap_mentioned_p (dest1, src2)) + { + emit_move_insn_1 (dest2, src2); + emit_move_insn_1 (dest1, src1); + } + else + { + emit_move_insn_1 (dest1, src1); + emit_move_insn_1 (dest2, src2); + } +} + /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1. This makes them candidates for using ldd and std insns. Index: config/sparc/sparc.md =================================================================== --- config/sparc/sparc.md (revision 243221) +++ config/sparc/sparc.md (working copy) @@ -254,14 +254,12 @@ (define_attr "isa" "v7,v8,v9,sparclet" (define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3,vis4" (const_string "none")) -(define_attr "lra" "none,disabled,enabled" - (const_string "none")) +(define_attr "lra" "disabled,enabled" + (const_string "enabled")) (define_attr "enabled" "" (cond [(eq_attr "cpu_feature" "none") - (cond [(eq_attr "lra" "disabled") (symbol_ref "!TARGET_LRA") - (eq_attr "lra" "enabled") (symbol_ref "TARGET_LRA")] - (const_int 1)) + (cond [(eq_attr "lra" "disabled") (symbol_ref "!TARGET_LRA")] (const_int 1)) (eq_attr "cpu_feature" "fpu") (symbol_ref "TARGET_FPU") (eq_attr "cpu_feature" "fpunotv9") (symbol_ref "TARGET_FPU && !TARGET_V9") (eq_attr "cpu_feature" "v9") (symbol_ref "TARGET_V9") @@ -1707,25 +1705,23 @@ (define_expand "movdi" (define_insn "*movdi_insn_sp32" [(set (match_operand:DI 0 "nonimmediate_operand" - "=T,o,T,T,U,r,o,r,r,r,?T,?*f,?*f,?o,?*e,?*e, r,?*f,?*e,?W,b,b") + "=T,o,U,T,r,o,r,r,?*f,?T,?*f,?o,?*e,?*e, r,?*f,?*e,?W,*b,*b") (match_operand:DI 1 "input_operand" - " J,J,U,r,T,T,r,o,i,r,*f, T, o,*f, *e, *e,?*f, r, W,*e,J,P"))] + " J,J,T,U,o,r,i,r, T,*f, o,*f, *e, *e,?*f, r, W,*e, J, P"))] "TARGET_ARCH32 && (register_operand (operands[0], DImode) || register_or_zero_operand (operands[1], DImode))" "@ - stx\t%%g0, %0 + stx\t%r1, %0 # - std\t%1, %0 - std\t%1, %0 ldd\t%1, %0 + std\t%1, %0 ldd\t%1, %0 + std\t%1, %0 # # - # - # - std\t%1, %0 ldd\t%1, %0 + std\t%1, %0 # # fmovd\t%1, %0 @@ -1736,12 +1732,12 @@ (define_insn "*movdi_insn_sp32" std\t%1, %0 fzero\t%0 fone\t%0" - [(set_attr "type" "store,store,store,store,load,load,*,*,*,*,fpstore,fpload,*,*,fpmove,*,*,*,fpload,fpstore,visl,visl") - (set_attr "length" "*,2,*,*,*,*,2,2,2,2,*,*,2,2,*,2,2,2,*,*,*,*") - (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double") - (set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis") - (set_attr "v3pipe" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,true,true") - (set_attr "lra" "*,*,disabled,enabled,disabled,enabled,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) + [(set_attr "type" "store,*,load,store,load,store,*,*,fpload,fpstore,*,*,fpmove,*,*,*,fpload,fpstore,visl,visl") + (set_attr "length" "*,2,*,*,*,*,2,2,*,*,2,2,*,2,2,2,*,*,*,*") + (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double") + (set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis") + (set_attr "v3pipe" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,true,true") + (set_attr "lra" "*,*,disabled,disabled,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")]) (define_insn "*movdi_insn_sp64" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, r,*e,?*e,?*e,?W,b,b") @@ -1997,30 +1993,27 @@ (define_expand "reload_outdi" (define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "const_int_operand" ""))] - "TARGET_ARCH32 + "reload_completed + && TARGET_ARCH32 && ((GET_CODE (operands[0]) == REG && SPARC_INT_REG_P (REGNO (operands[0]))) || (GET_CODE (operands[0]) == SUBREG && GET_CODE (SUBREG_REG (operands[0])) == REG - && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0]))))) - && reload_completed" + && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))" [(clobber (const_int 0))] { - HOST_WIDE_INT low, high; + HOST_WIDE_INT low = trunc_int_for_mode (INTVAL (operands[1]), SImode); + HOST_WIDE_INT high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode); + rtx high_part = gen_highpart (SImode, operands[0]); + rtx low_part = gen_lowpart (SImode, operands[0]); - low = trunc_int_for_mode (INTVAL (operands[1]), SImode); - high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode); - emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high))); - - /* Slick... but this trick loses if this subreg constant part - can be done in one insn. */ - if (low == high - && !SPARC_SETHI32_P (high) - && !SPARC_SIMM13_P (high)) - emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), - gen_highpart (SImode, operands[0]))); + emit_move_insn_1 (high_part, GEN_INT (high)); + + /* Slick... but this loses if the constant can be done in one insn. */ + if (low == high && !SPARC_SETHI32_P (high) && !SPARC_SIMM13_P (high)) + emit_move_insn_1 (low_part, high_part); else - emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low))); + emit_move_insn_1 (low_part, GEN_INT (low)); DONE; }) @@ -2031,31 +2024,10 @@ (define_split "reload_completed && (!TARGET_V9 || (TARGET_ARCH32 - && sparc_split_regreg_legitimate (operands[0], operands[1])))" + && sparc_split_reg_reg_legitimate (operands[0], operands[1])))" [(clobber (const_int 0))] { - rtx set_dest = operands[0]; - rtx set_src = operands[1]; - rtx dest1, dest2; - rtx src1, src2; - - dest1 = gen_highpart (SImode, set_dest); - dest2 = gen_lowpart (SImode, set_dest); - src1 = gen_highpart (SImode, set_src); - src2 = gen_lowpart (SImode, set_src); - - /* Now emit using the real source and destination we found, swapping - the order if we detect overlap. */ - if (reg_overlap_mentioned_p (dest1, src2)) - { - emit_insn (gen_movsi (dest2, src2)); - emit_insn (gen_movsi (dest1, src1)); - } - else - { - emit_insn (gen_movsi (dest1, src1)); - emit_insn (gen_movsi (dest2, src2)); - } + sparc_split_reg_reg (operands[0], operands[1], SImode); DONE; }) @@ -2064,41 +2036,24 @@ (define_split (define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "memory_operand" ""))] - "(TARGET_ARCH32 - && reload_completed - && sparc_splitdi_legitimate (operands[0], operands[1]))" + "reload_completed + && TARGET_ARCH32 + && sparc_split_reg_mem_legitimate (operands[0], operands[1])" [(clobber (const_int 0))] { - rtx word0 = adjust_address (operands[1], SImode, 0); - rtx word1 = adjust_address (operands[1], SImode, 4); - rtx high_part = gen_highpart (SImode, operands[0]); - rtx low_part = gen_lowpart (SImode, operands[0]); - - if (reg_overlap_mentioned_p (high_part, word1)) - { - emit_insn (gen_movsi (low_part, word1)); - emit_insn (gen_movsi (high_part, word0)); - } - else - { - emit_insn (gen_movsi (high_part, word0)); - emit_insn (gen_movsi (low_part, word1)); - } + sparc_split_reg_mem (operands[0], operands[1], SImode); DONE; }) (define_split [(set (match_operand:DI 0 "memory_operand" "") (match_operand:DI 1 "register_operand" ""))] - "(TARGET_ARCH32 - && reload_completed - && sparc_splitdi_legitimate (operands[1], operands[0]))" + "reload_completed + && TARGET_ARCH32 + && sparc_split_reg_mem_legitimate (operands[1], operands[0])" [(clobber (const_int 0))] { - emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), - gen_highpart (SImode, operands[1]))); - emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), - gen_lowpart (SImode, operands[1]))); + sparc_split_mem_reg (operands[0], operands[1], SImode); DONE; }) @@ -2112,8 +2067,8 @@ (define_split && offsettable_memref_p (operands[0])" [(clobber (const_int 0))] { - emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx)); - emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx)); + emit_move_insn_1 (adjust_address (operands[0], SImode, 0), const0_rtx); + emit_move_insn_1 (adjust_address (operands[0], SImode, 4), const0_rtx); DONE; }) @@ -2381,13 +2336,15 @@ (define_expand "movdf" (define_insn "*movdf_insn_sp32" [(set (match_operand:DF 0 "nonimmediate_operand" - "=b,b,e,e,*r, f, e,T,W,U,r,T,T, f, *r, o,o") + "=T,o,b,b,e,e,*r, f, e,W,U,T, f,o, *r,*r, o") (match_operand:DF 1 "input_operand" - " G,C,e,e, f,*r,W#F,G,e,T,T,U,r,o#F,*roF,*rG,f"))] + " G,G,G,C,e,e, f,*r,W#F,e,T,U,o#F,f,*rF, o,*r"))] "TARGET_ARCH32 && (register_operand (operands[0], DFmode) || register_or_zero_or_all_ones_operand (operands[1], DFmode))" "@ + stx\t%r1, %0 + # fzero\t%0 fone\t%0 fmovd\t%1, %0 @@ -2395,22 +2352,20 @@ (define_insn "*movdf_insn_sp32" # # ldd\t%1, %0 - stx\t%r1, %0 std\t%1, %0 ldd\t%1, %0 - ldd\t%1, %0 - std\t%1, %0 std\t%1, %0 # # # - #" - [(set_attr "type" "visl,visl,fpmove,*,*,*,fpload,store,fpstore,load,load,store,store,*,*,*,*") - (set_attr "length" "*,*,*,2,2,2,*,*,*,*,*,*,*,2,2,2,2") - (set_attr "fptype" "double,double,double,*,*,*,*,*,*,*,*,*,*,*,*,*,*") - (set_attr "cpu_feature" "vis,vis,v9,fpunotv9,vis3,vis3,fpu,v9,fpu,*,*,*,*,fpu,*,*,fpu") - (set_attr "v3pipe" "true,true,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*") - (set_attr "lra" "*,*,*,*,*,*,*,*,*,disabled,enabled,disabled,enabled,*,*,*,*")]) + ldd\t%1, %0 + std\t%1, %0" + [(set_attr "type" "store,*,visl,visl,fpmove,*,*,*,fpload,fpstore,load,store,*,*,*,load,store") + (set_attr "length" "*,2,*,*,*,2,2,2,*,*,*,*,2,2,2,*,*") + (set_attr "fptype" "*,*,double,double,double,*,*,*,*,*,*,*,*,*,*,*,*") + (set_attr "cpu_feature" "v9,*,vis,vis,v9,fpunotv9,vis3,vis3,fpu,fpu,*,*,fpu,fpu,*,*,*") + (set_attr "v3pipe" "*,*,true,true,*,*,*,*,*,*,*,*,*,*,*,*,*") + (set_attr "lra" "*,*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")]) (define_insn "*movdf_insn_sp64" [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,*r, e, e,W, *r,*r, m,*r") @@ -2440,44 +2395,38 @@ (define_insn "*movdf_insn_sp64" (define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "const_double_operand" ""))] - "REG_P (operands[0]) + "reload_completed + && REG_P (operands[0]) && SPARC_INT_REG_P (REGNO (operands[0])) - && !const_zero_operand (operands[1], GET_MODE (operands[0])) - && reload_completed" + && !const_zero_operand (operands[1], GET_MODE (operands[0]))" [(clobber (const_int 0))] { operands[0] = gen_raw_REG (DImode, REGNO (operands[0])); if (TARGET_ARCH64) { - machine_mode mode = GET_MODE (operands[1]); - rtx tem = simplify_subreg (DImode, operands[1], mode, 0); + rtx tem = simplify_subreg (DImode, operands[1], DFmode, 0); emit_insn (gen_movdi (operands[0], tem)); } else { - machine_mode mode = GET_MODE (operands[1]); - rtx hi = simplify_subreg (SImode, operands[1], mode, 0); - rtx lo = simplify_subreg (SImode, operands[1], mode, 4); + rtx hi = simplify_subreg (SImode, operands[1], DFmode, 0); + rtx lo = simplify_subreg (SImode, operands[1], DFmode, 4); + rtx high_part = gen_highpart (SImode, operands[0]); + rtx low_part = gen_lowpart (SImode, operands[0]); gcc_assert (GET_CODE (hi) == CONST_INT); gcc_assert (GET_CODE (lo) == CONST_INT); - emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), hi)); + emit_move_insn_1 (high_part, hi); - /* Slick... but this trick loses if this subreg constant part - can be done in one insn. */ + /* Slick... but this loses if the constant can be done in one insn. */ if (lo == hi && !SPARC_SETHI32_P (INTVAL (hi)) && !SPARC_SIMM13_P (INTVAL (hi))) - { - emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), - gen_highpart (SImode, operands[0]))); - } + emit_move_insn_1 (low_part, high_part); else - { - emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), lo)); - } + emit_move_insn_1 (low_part, lo); } DONE; }) @@ -2489,35 +2438,31 @@ (define_split ;; register DFmode cases must be handled. (define_split [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "(!TARGET_V9 - || (TARGET_ARCH32 - && sparc_split_regreg_legitimate (operands[0], operands[1]))) - && reload_completed" + (match_operand:DF 1 "const_zero_operand" ""))] + "reload_completed + && TARGET_ARCH32 + && ((GET_CODE (operands[0]) == REG + && SPARC_INT_REG_P (REGNO (operands[0]))) + || (GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == REG + && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))" [(clobber (const_int 0))] { - rtx set_dest = operands[0]; - rtx set_src = operands[1]; - rtx dest1, dest2; - rtx src1, src2; - - dest1 = gen_highpart (SFmode, set_dest); - dest2 = gen_lowpart (SFmode, set_dest); - src1 = gen_highpart (SFmode, set_src); - src2 = gen_lowpart (SFmode, set_src); + emit_move_insn_1 (gen_highpart (SFmode, operands[0]), CONST0_RTX (SFmode)); + emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), CONST0_RTX (SFmode)); + DONE; +}) - /* Now emit using the real source and destination we found, swapping - the order if we detect overlap. */ - if (reg_overlap_mentioned_p (dest1, src2)) - { - emit_move_insn_1 (dest2, src2); - emit_move_insn_1 (dest1, src1); - } - else - { - emit_move_insn_1 (dest1, src1); - emit_move_insn_1 (dest2, src2); - } +(define_split + [(set (match_operand:DF 0 "register_operand" "") + (match_operand:DF 1 "register_operand" ""))] + "reload_completed + && (!TARGET_V9 + || (TARGET_ARCH32 + && sparc_split_reg_reg_legitimate (operands[0], operands[1])))" + [(clobber (const_int 0))] +{ + sparc_split_reg_reg (operands[0], operands[1], SFmode); DONE; }) @@ -2526,26 +2471,10 @@ (define_split (match_operand:DF 1 "memory_operand" ""))] "reload_completed && TARGET_ARCH32 - && (((REGNO (operands[0]) % 2) != 0) - || !mem_min_alignment (operands[1], 8)) - && offsettable_memref_p (operands[1])" + && sparc_split_reg_mem_legitimate (operands[0], operands[1])" [(clobber (const_int 0))] { - rtx word0, word1; - - word0 = adjust_address (operands[1], SFmode, 0); - word1 = adjust_address (operands[1], SFmode, 4); - - if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1)) - { - emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1); - emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0); - } - else - { - emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0); - emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1); - } + sparc_split_reg_mem (operands[0], operands[1], SFmode); DONE; }) @@ -2554,18 +2483,10 @@ (define_split (match_operand:DF 1 "register_operand" ""))] "reload_completed && TARGET_ARCH32 - && (((REGNO (operands[1]) % 2) != 0) - || !mem_min_alignment (operands[0], 8)) - && offsettable_memref_p (operands[0])" + && sparc_split_reg_mem_legitimate (operands[1], operands[0])" [(clobber (const_int 0))] { - rtx word0, word1; - - word0 = adjust_address (operands[0], SFmode, 0); - word1 = adjust_address (operands[0], SFmode, 4); - - emit_move_insn_1 (word0, gen_highpart (SFmode, operands[1])); - emit_move_insn_1 (word1, gen_lowpart (SFmode, operands[1])); + sparc_split_mem_reg (operands[0], operands[1], SFmode); DONE; }) @@ -2579,35 +2500,8 @@ (define_split && offsettable_memref_p (operands[0])" [(clobber (const_int 0))] { - rtx dest1, dest2; - - dest1 = adjust_address (operands[0], SFmode, 0); - dest2 = adjust_address (operands[0], SFmode, 4); - - emit_move_insn_1 (dest1, CONST0_RTX (SFmode)); - emit_move_insn_1 (dest2, CONST0_RTX (SFmode)); - DONE; -}) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "const_zero_operand" ""))] - "reload_completed - && TARGET_ARCH32 - && ((GET_CODE (operands[0]) == REG - && SPARC_INT_REG_P (REGNO (operands[0]))) - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))" - [(clobber (const_int 0))] -{ - rtx set_dest = operands[0]; - rtx dest1, dest2; - - dest1 = gen_highpart (SFmode, set_dest); - dest2 = gen_lowpart (SFmode, set_dest); - emit_move_insn_1 (dest1, CONST0_RTX (SFmode)); - emit_move_insn_1 (dest2, CONST0_RTX (SFmode)); + emit_move_insn_1 (adjust_address (operands[0], SFmode, 0), CONST0_RTX (SFmode)); + emit_move_insn_1 (adjust_address (operands[0], SFmode, 4), CONST0_RTX (SFmode)); DONE; }) @@ -8625,8 +8519,8 @@ (define_insn "*mov_insn" (set_attr "v3pipe" "true,true,true,*,*,*,*,*,*,true,true")]) (define_insn "*mov_insn_sp64" - [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,m,m,*r, m,*r, e,*r") - (match_operand:VM64 1 "input_operand" "Y,C,e,m,e,Y, m,*r, e,*r,*r"))] + [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,W,m,*r, m,*r, e,*r") + (match_operand:VM64 1 "input_operand" "Y,Z,e,W,e,Y, m,*r, e,*r,*r"))] "TARGET_VIS && TARGET_ARCH64 && (register_operand (operands[0], mode) @@ -8648,13 +8542,17 @@ (define_insn "*mov_insn_sp64" (set_attr "v3pipe" "true,true,true,*,*,*,*,*,*,*,*")]) (define_insn "*mov_insn_sp32" - [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,*r, f,e,m,m,U,r,T,T, o,*r") - (match_operand:VM64 1 "input_operand" "Y,C,e, f,*r,m,e,Y,T,T,U,r,*r,*r"))] + [(set (match_operand:VM64 0 "nonimmediate_operand" + "=T,o,e,e,e,*r, f,e,W,U,T,e,o,*r,*r, o") + (match_operand:VM64 1 "input_operand" + " Y,Y,Y,Z,e, f,*r,W,e,T,U,o,e,*r, o,*r"))] "TARGET_VIS && TARGET_ARCH32 && (register_operand (operands[0], mode) || register_or_zero_or_all_ones_operand (operands[1], mode))" "@ + stx\t%r1, %0 + # fzero\t%0 fone\t%0 fsrc2\t%1, %0 @@ -8662,71 +8560,70 @@ (define_insn "*mov_insn_sp32" # ldd\t%1, %0 std\t%1, %0 - stx\t%r1, %0 - ldd\t%1, %0 ldd\t%1, %0 std\t%1, %0 - std\t%1, %0 # - #" - [(set_attr "type" "visl,visl,vismv,*,*,fpload,fpstore,store,load,load,store,store,*,*") - (set_attr "length" "*,*,*,2,2,*,*,*,*,*,*,*,2,2") - (set_attr "cpu_feature" "vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*,*,*") - (set_attr "v3pipe" "true,true,true,*,*,*,*,*,*,*,*,*,*,*") - (set_attr "lra" "*,*,*,*,*,*,*,*,disabled,enabled,disabled,enabled,*,*")]) + # + # + ldd\t%1, %0 + std\t%1, %0" + [(set_attr "type" "store,*,visl,visl,vismv,*,*,fpload,fpstore,load,store,*,*,*,load,store") + (set_attr "length" "*,2,*,*,*,2,2,*,*,*,*,2,2,2,*,*") + (set_attr "cpu_feature" "*,*,vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*,*,*") + (set_attr "v3pipe" "*,*,true,true,true,*,*,*,*,*,*,*,*,*,*,*") + (set_attr "lra" "*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")]) (define_split - [(set (match_operand:VM64 0 "memory_operand" "") + [(set (match_operand:VM64 0 "register_operand" "") (match_operand:VM64 1 "register_operand" ""))] "reload_completed && TARGET_VIS && TARGET_ARCH32 - && (((REGNO (operands[1]) % 2) != 0) - || !mem_min_alignment (operands[0], 8)) - && offsettable_memref_p (operands[0])" + && sparc_split_reg_reg_legitimate (operands[0], operands[1])" [(clobber (const_int 0))] { - rtx word0, word1; - - word0 = adjust_address (operands[0], SImode, 0); - word1 = adjust_address (operands[0], SImode, 4); - - emit_move_insn_1 (word0, gen_highpart (SImode, operands[1])); - emit_move_insn_1 (word1, gen_lowpart (SImode, operands[1])); + sparc_split_reg_reg (operands[0], operands[1], SImode); DONE; }) (define_split [(set (match_operand:VM64 0 "register_operand" "") - (match_operand:VM64 1 "register_operand" ""))] + (match_operand:VM64 1 "memory_operand" ""))] "reload_completed && TARGET_VIS && TARGET_ARCH32 - && sparc_split_regreg_legitimate (operands[0], operands[1])" + && sparc_split_reg_mem_legitimate (operands[0], operands[1])" [(clobber (const_int 0))] { - rtx set_dest = operands[0]; - rtx set_src = operands[1]; - rtx dest1, dest2; - rtx src1, src2; + sparc_split_reg_mem (operands[0], operands[1], SImode); + DONE; +}) - dest1 = gen_highpart (SImode, set_dest); - dest2 = gen_lowpart (SImode, set_dest); - src1 = gen_highpart (SImode, set_src); - src2 = gen_lowpart (SImode, set_src); +(define_split + [(set (match_operand:VM64 0 "memory_operand" "") + (match_operand:VM64 1 "register_operand" ""))] + "reload_completed + && TARGET_VIS + && TARGET_ARCH32 + && sparc_split_reg_mem_legitimate (operands[1], operands[0])" + [(clobber (const_int 0))] +{ + sparc_split_mem_reg (operands[0], operands[1], SImode); + DONE; +}) - /* Now emit using the real source and destination we found, swapping - the order if we detect overlap. */ - if (reg_overlap_mentioned_p (dest1, src2)) - { - emit_insn (gen_movsi (dest2, src2)); - emit_insn (gen_movsi (dest1, src1)); - } - else - { - emit_insn (gen_movsi (dest1, src1)); - emit_insn (gen_movsi (dest2, src2)); - } +(define_split + [(set (match_operand:VM64 0 "memory_operand" "") + (match_operand:VM64 1 "const_zero_operand" ""))] + "reload_completed + && TARGET_VIS + && TARGET_ARCH32 + && !mem_min_alignment (operands[0], 8) + && offsettable_memref_p (operands[0])" + [(clobber (const_int 0))] +{ + emit_move_insn_1 (adjust_address (operands[0], SImode, 0), const0_rtx); + emit_move_insn_1 (adjust_address (operands[0], SImode, 4), const0_rtx); DONE; })