From patchwork Thu Sep 13 22:55:27 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 183759 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 C878B2C0084 for ; Fri, 14 Sep 2012 09:01:22 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1348182084; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:From:To:Subject:Date:User-Agent:MIME-Version:Message-Id: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=gMI4ptU 6YH9ttO1pJFp7oPJr39k=; b=BtDQ6x9HMKdljdrl535WGjShVAQx+FrNOnzVMxB 6YKnu+kqGguT29FeaAvbAeZpw0c2uUb+JtknPoCNWxf5tIs9s5Ge8D/rt/F9JzZB YpSgtWN8IONRBRI+UhKE2rzOATg2ZVx6xvPyAEkgPkRGUNDoLlUy1u7Nysz844h4 AJq4= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:From:To:Subject:Date:User-Agent:MIME-Version:Message-Id:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=BDGMK8ruqXDuHsYKZxWffL9NVprnBNgmzHTkK0Vw7K3kZsXQH3kXWB4B9PvBh6 HJ7Jjrk2TuMtctS990XvTcM7GU/d8iW0ApPT5Ab1djkKZZ+BB9wRNglrHtlaLeAQ r8ICLUDEu8T+6pnxwYC0DcKVchLpGjhyX6d13OeEpK1D4=; Received: (qmail 17659 invoked by alias); 13 Sep 2012 23:01:01 -0000 Received: (qmail 17632 invoked by uid 22791); 13 Sep 2012 23:00:57 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 13 Sep 2012 23:00:40 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id BCA48290052 for ; Fri, 14 Sep 2012 01:00:49 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id X0JLFzjgSYDi for ; Fri, 14 Sep 2012 01:00:49 +0200 (CEST) Received: from hermes.site (ADijon-552-1-57-16.w92-138.abo.wanadoo.fr [92.138.176.16]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 882A3290008 for ; Fri, 14 Sep 2012 01:00:49 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [SPARC] Implement TImode support Date: Fri, 14 Sep 2012 00:55:27 +0200 User-Agent: KMail/1.13.5 (Linux/2.6.34.10-0.6-desktop; KDE/4.4.4; x86_64; ; ) MIME-Version: 1.0 Message-Id: <201209140055.27433.ebotcazou@adacore.com> 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 Now that TImode support is enabled on SPARC 64-bit, let's implement it. :-) This is modeled on the TFmode support and, consequently, inherits its relative verbosity. A future cleanup could simplify it a little and unify it with the TFmode support, as e.g. for Alpha. Bootstrapped/regtested on SPARC/Solaris and SPARC64/Solaris, applied on the mainline. 2012-09-13 Eric Botcazou * config/sparc/predicates.md (input_operand): Do not consider TImode constants as 1-instruction integer constants. Use register_or_zero_operand instead of register_operand and tidy up. * config/sparc/sparc.md (movti): New expander. (movti_insn_sp64): New instruction. (movti_insn_sp64_hq): Likewise. (TImode splitters): New splitters. * config/sparc/sparc.c (sparc_expand_move) : New case. (sparc_legitimate_address_p): Return 0 for REG+REG in TImode. * config/sparc/sparc-protos.h (arith_double_4096_operand): Delete. (arith_4096_operand): Likewise. (zero_operand): Likewise. (fp_zero_operand): Likewise. (reg_or_0_operand): Likewise. Index: config/sparc/predicates.md =================================================================== --- config/sparc/predicates.md (revision 191198) +++ config/sparc/predicates.md (working copy) @@ -357,7 +357,7 @@ (define_predicate "arith_double_operand" (define_predicate "arith_add_operand" (ior (match_operand 0 "arith_operand") (match_operand 0 "const_4096_operand"))) - + ;; Return true if OP is suitable as second double operand for add/sub. (define_predicate "arith_double_add_operand" (match_code "const_int,const_double,reg,subreg") @@ -427,6 +427,7 @@ (define_predicate "input_operand" /* Allow any 1-instruction integer constant. */ if (mclass == MODE_INT + && mode != TImode && (small_int_operand (op, mode) || const_high_operand (op, mode))) return true; @@ -440,12 +441,10 @@ (define_predicate "input_operand" if (mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE) return true; - if (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR - && (const_zero_operand (op, mode) - || const_all_ones_operand (op, mode))) + if (mclass == MODE_VECTOR_INT && const_all_ones_operand (op, mode)) return true; - if (register_operand (op, mode)) + if (register_or_zero_operand (op, mode)) return true; /* If this is a SUBREG, look inside so that we handle paradoxical ones. */ Index: config/sparc/sparc.md =================================================================== --- config/sparc/sparc.md (revision 191198) +++ config/sparc/sparc.md (working copy) @@ -2034,6 +2034,164 @@ (define_split DONE; }) +(define_expand "movti" + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "general_operand" ""))] + "TARGET_ARCH64" +{ + if (sparc_expand_move (TImode, operands)) + DONE; +}) + +;; We need to prevent reload from splitting TImode moves, because it +;; might decide to overwrite a pointer with the value it points to. +;; In that case we have to do the loads in the appropriate order so +;; that the pointer is not destroyed too early. + +(define_insn "*movti_insn_sp64" + [(set (match_operand:TI 0 "nonimmediate_operand" "=r , o,?*e,?o,b") + (match_operand:TI 1 "input_operand" "roJ,rJ, eo, e,J"))] + "TARGET_ARCH64 + && ! TARGET_HARD_QUAD + && (register_operand (operands[0], TImode) + || register_or_zero_operand (operands[1], TImode))" + "#" + [(set_attr "length" "2,2,2,2,2") + (set_attr "cpu_feature" "*,*,fpu,fpu,vis")]) + +(define_insn "*movti_insn_sp64_hq" + [(set (match_operand:TI 0 "nonimmediate_operand" "=r , o,?*e,?*e,?m,b") + (match_operand:TI 1 "input_operand" "roJ,rJ, e, m, e,J"))] + "TARGET_ARCH64 + && TARGET_HARD_QUAD + && (register_operand (operands[0], TImode) + || register_or_zero_operand (operands[1], TImode))" + "@ + # + # + fmovq\t%1, %0 + ldq\t%1, %0 + stq\t%1, %0 + #" + [(set_attr "type" "*,*,fpmove,fpload,fpstore,*") + (set_attr "length" "2,2,*,*,*,2")]) + +;; Now all the splits to handle multi-insn TI mode moves. +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (match_operand:TI 1 "register_operand" ""))] + "reload_completed + && ((TARGET_FPU + && ! TARGET_HARD_QUAD) + || (! fp_register_operand (operands[0], TImode) + && ! fp_register_operand (operands[1], TImode)))" + [(clobber (const_int 0))] +{ + rtx set_dest = operands[0]; + rtx set_src = operands[1]; + rtx dest1, dest2; + rtx src1, src2; + + dest1 = gen_highpart (DImode, set_dest); + dest2 = gen_lowpart (DImode, set_dest); + src1 = gen_highpart (DImode, set_src); + src2 = gen_lowpart (DImode, 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_movdi (dest2, src2)); + emit_insn (gen_movdi (dest1, src1)); + } + else + { + emit_insn (gen_movdi (dest1, src1)); + emit_insn (gen_movdi (dest2, src2)); + } + DONE; +}) + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "const_zero_operand" ""))] + "reload_completed" + [(clobber (const_int 0))] +{ + rtx set_dest = operands[0]; + rtx dest1, dest2; + + switch (GET_CODE (set_dest)) + { + case REG: + dest1 = gen_highpart (DImode, set_dest); + dest2 = gen_lowpart (DImode, set_dest); + break; + case MEM: + dest1 = adjust_address (set_dest, DImode, 0); + dest2 = adjust_address (set_dest, DImode, 8); + break; + default: + gcc_unreachable (); + } + + emit_insn (gen_movdi (dest1, const0_rtx)); + emit_insn (gen_movdi (dest2, const0_rtx)); + DONE; +}) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (match_operand:TI 1 "memory_operand" ""))] + "reload_completed + && offsettable_memref_p (operands[1]) + && (! TARGET_HARD_QUAD + || ! fp_register_operand (operands[0], TImode))" + [(clobber (const_int 0))] +{ + rtx word0 = adjust_address (operands[1], DImode, 0); + rtx word1 = adjust_address (operands[1], DImode, 8); + rtx set_dest, dest1, dest2; + + set_dest = operands[0]; + + dest1 = gen_highpart (DImode, set_dest); + dest2 = gen_lowpart (DImode, set_dest); + + /* Now output, ordering such that we don't clobber any registers + mentioned in the address. */ + if (reg_overlap_mentioned_p (dest1, word1)) + + { + emit_insn (gen_movdi (dest2, word1)); + emit_insn (gen_movdi (dest1, word0)); + } + else + { + emit_insn (gen_movdi (dest1, word0)); + emit_insn (gen_movdi (dest2, word1)); + } + DONE; +}) + +(define_split + [(set (match_operand:TI 0 "memory_operand" "") + (match_operand:TI 1 "register_operand" ""))] + "reload_completed + && offsettable_memref_p (operands[0]) + && (! TARGET_HARD_QUAD + || ! fp_register_operand (operands[1], TImode))" + [(clobber (const_int 0))] +{ + rtx set_src = operands[1]; + + emit_insn (gen_movdi (adjust_address (operands[0], DImode, 0), + gen_highpart (DImode, set_src))); + emit_insn (gen_movdi (adjust_address (operands[0], DImode, 8), + gen_lowpart (DImode, set_src))); + DONE; +}) + ;; Floating point move instructions @@ -2477,7 +2635,7 @@ (define_split dest2 = adjust_address (set_dest, DFmode, 8); break; default: - gcc_unreachable (); + gcc_unreachable (); } emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode))); Index: config/sparc/sparc-protos.h =================================================================== --- config/sparc/sparc-protos.h (revision 191198) +++ config/sparc/sparc-protos.h (working copy) @@ -82,11 +82,6 @@ extern const char *output_probe_stack_ra extern bool emit_scc_insn (rtx []); extern void emit_conditional_branch_insn (rtx []); extern int mems_ok_for_ldd_peep (rtx, rtx, rtx); -extern int arith_double_4096_operand (rtx, enum machine_mode); -extern int arith_4096_operand (rtx, enum machine_mode); -extern int zero_operand (rtx, enum machine_mode); -extern int fp_zero_operand (rtx, enum machine_mode); -extern int reg_or_0_operand (rtx, enum machine_mode); extern int empty_delay_slot (rtx); extern int eligible_for_return_delay (rtx); extern int eligible_for_sibcall_delay (rtx); Index: config/sparc/sparc.c =================================================================== --- config/sparc/sparc.c (revision 191198) +++ config/sparc/sparc.c (working copy) @@ -1465,6 +1465,18 @@ sparc_expand_move (enum machine_mode mod sparc_emit_set_const64 (operands[0], operands[1]); return true; + case TImode: + { + rtx high, low; + /* TImode isn't available in 32-bit mode. */ + split_double (operands[1], &high, &low); + emit_insn (gen_movdi (operand_subword (operands[0], 0, 0, TImode), + high)); + emit_insn (gen_movdi (operand_subword (operands[0], 1, 0, TImode), + low)); + } + return true; + default: gcc_unreachable (); } @@ -3492,6 +3504,10 @@ sparc_legitimate_address_p (enum machine && ! (TARGET_ARCH64 && TARGET_HARD_QUAD)) return 0; + /* Likewise for TImode, but in all cases. */ + if (mode == TImode) + return 0; + /* We prohibit REG + REG on ARCH32 if not optimizing for DFmode/DImode because then mem_min_alignment is likely to be zero after reload and the forced split would lack a matching splitter