From patchwork Mon May 21 05:14:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 160313 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 CD069B6EF1 for ; Mon, 21 May 2012 15:14:32 +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=1338182074; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Subject:Message-ID: Mail-Followup-To:References:MIME-Version:Content-Type: Content-Disposition:In-Reply-To:User-Agent:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=ntgynIj0DN19zgaR42RBu+eDBqA=; b=KAHNN0pG5ZxbD1wMuZCC3qtThJ7Bu7+kDxYkADIf2NKseoD1Lpsy3CWM+JLbDy +jyTOYxyyFCvzbfZdFZaCOkFr1wnEx8p3JKNHyEd5Ohta76T4GxJnQ/SXEyZXjEB OC+b2+MnSPkRzimZB5oHKVA8YmP5wsVG9BFSy6Eq5qh+k= 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:Received:Date:From:To:Subject:Message-ID:Mail-Followup-To:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=tcDgiYNC/R90zPaTsP3y/snMQRltA2CdsTjZDVR2HFJ7mSS0r9iWAurEXCe7X7 UKPxL8vnmwuP1b3Ogs/uEggs+vkpqaDmJYenKsC4D2q0dMntPLWLnI0KBT1Uo8Vi yP97CRPnUSmU0E+SYPEFHTjmv0gti4Q2giL579e2mioIw=; Received: (qmail 19870 invoked by alias); 21 May 2012 05:14:26 -0000 Received: (qmail 19847 invoked by uid 22791); 21 May 2012 05:14:23 -0000 X-SWARE-Spam-Status: No, hits=-4.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE X-Spam-Check-By: sourceware.org Received: from mail-pz0-f47.google.com (HELO mail-pz0-f47.google.com) (209.85.210.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 21 May 2012 05:14:08 +0000 Received: by dalh21 with SMTP id h21so6175821dal.20 for ; Sun, 20 May 2012 22:14:08 -0700 (PDT) Received: by 10.68.203.98 with SMTP id kp2mr64976619pbc.19.1337577248229; Sun, 20 May 2012 22:14:08 -0700 (PDT) Received: from bubble.grove.modra.org ([115.187.252.19]) by mx.google.com with ESMTPS id pj5sm21859916pbb.51.2012.05.20.22.14.05 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 20 May 2012 22:14:07 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 47CFEEA039C; Mon, 21 May 2012 14:44:02 +0930 (CST) Date: Mon, 21 May 2012 14:44:02 +0930 From: Alan Modra To: David Edelsohn , gcc-patches@gcc.gnu.org Subject: [RS6000] out-of-line save/restore conditions Message-ID: <20120521051402.GE3285@bubble.grove.modra.org> Mail-Followup-To: David Edelsohn , gcc-patches@gcc.gnu.org References: <37BF2514-EA22-4DE4-8B77-53A6B63DE48C@adacore.com> <20120508103239.GO17181@bubble.grove.modra.org> <20120521024804.GD3285@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120521024804.GD3285@bubble.grove.modra.org> User-Agent: Mutt/1.5.21 (2010-09-15) 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 Currently, powerpc-linux gcc -Os -mno-multiple uses out-of-linux gpr save and restore functions when saving/restoring just one gpr. That's quite silly since the function call requires more instructions and is slower than an inline save/restore. The only case where it might win is when no fprs are restored and the restore function can tear down the frame and exit (also loading up lr on ppc64). I guess that's how GP_SAVE_INLINE came to be like it is, ie. it's optimised for the common case using ldm in the prologue and no fprs. Still, it isn't difficult to choose the best combination in all cases, but it does mean different logic is needed for restores. I could have implemented GP_RESTORE_INLINE and FP_RESORE_INLINE macros but it seemed simpler to just move everything into the one place the macros are invoked. AIX and Darwin register cutoff doesn't change with this patch. This patch also enables out-of-line restores in cases that were previously disabled due to using inline saves. Bootstrapped and regression tested powerpc-linux. OK to apply? * aix.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete. * darwin.h (FP_SAVE_INLINE, GP_SAVE_INLINE): Delete. * sysv4.h (FP_SAVE_INLINE, GP_SAVE_INLINE, V_SAVE_INLINE): Delete. * config/rs6000/rs6000.c (V_SAVE_INLINE): Delete. (rs6000_savres_strategy): Reimplement GP/FP/V_SAVE_INLINE logic. For ELF targets, use out-of-line restores for -Os and any number of regs if the restore exits, and out-of-line gp save for two or more regs. Use save_reg_p to test for holes in reg restore set. Replace "#if" with "if". Index: gcc/config/rs6000/aix.h =================================================================== --- gcc/config/rs6000/aix.h (revision 187699) +++ gcc/config/rs6000/aix.h (working copy) @@ -207,11 +207,6 @@ { "link_syscalls", LINK_SYSCALLS_SPEC }, \ { "link_libg", LINK_LIBG_SPEC } -/* Define cutoff for using external functions to save floating point. */ -#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63) -/* And similarly for general purpose registers. */ -#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32) - #define PROFILE_HOOK(LABEL) output_profile_hook (LABEL) /* No version of AIX fully supports AltiVec or 64-bit instructions in Index: gcc/config/rs6000/darwin.h =================================================================== --- gcc/config/rs6000/darwin.h (revision 187699) +++ gcc/config/rs6000/darwin.h (working copy) @@ -173,16 +173,6 @@ (RS6000_ALIGN (crtl->outgoing_args_size, 16) \ + (STACK_POINTER_OFFSET)) -/* Define cutoff for using out-of-line functions to save registers. - Currently on Darwin, we implement FP and GPR out-of-line-saves plus the - special routine for 'save everything'. */ - -#undef FP_SAVE_INLINE -#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 60 && (FIRST_REG) < 64) - -#undef GP_SAVE_INLINE -#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 29 && (FIRST_REG) < 32) - /* Darwin uses a function call if everything needs to be saved/restored. */ #undef WORLD_SAVE_P Index: gcc/config/rs6000/sysv4.h =================================================================== --- gcc/config/rs6000/sysv4.h (revision 187699) +++ gcc/config/rs6000/sysv4.h (working copy) @@ -243,19 +243,6 @@ #define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN) #define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN) -/* Define cutoff for using external functions to save floating point. - When optimizing for size, use external functions when profitable. */ -#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 \ - || (FIRST_REG) == 63 \ - || !optimize_size) - -/* And similarly for general purpose registers. */ -#define GP_SAVE_INLINE(FIRST_REG) (!optimize_size) - -/* And vector registers. */ -#define V_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == LAST_ALTIVEC_REGNO \ - || !optimize_size) - /* Put jump tables in read-only memory, rather than in .text. */ #define JUMP_TABLES_IN_TEXT_SECTION 0 Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 187699) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -17443,10 +17294,6 @@ REST_INLINE_VRS = 0x200 }; -#ifndef V_SAVE_INLINE -#define V_SAVE_INLINE(FIRST_REG) 1 -#endif - static int rs6000_savres_strategy (rs6000_stack_t *info, bool using_static_chain_p) @@ -17468,7 +17315,6 @@ | SAVE_INLINE_VRS | REST_INLINE_VRS); if (info->first_fp_reg_save == 64 - || FP_SAVE_INLINE (info->first_fp_reg_save) /* The out-of-line FP routines use double-precision stores; we can't use those routines if we don't have such stores. */ || (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT) @@ -17476,26 +17322,80 @@ strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; if (info->first_gp_reg_save == 32 - || GP_SAVE_INLINE (info->first_gp_reg_save) || (!(strategy & SAVRES_MULTIPLE) && global_regs_p (info->first_gp_reg_save, 32))) strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1 - || V_SAVE_INLINE (info->first_altivec_reg_save) || global_regs_p (info->first_altivec_reg_save, LAST_ALTIVEC_REGNO + 1)) strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS; + /* Define cutoff for using out-of-line functions to save registers. */ + if (DEFAULT_ABI == ABI_V4 || TARGET_ELF) + { + if (!optimize_size) + { + strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; + strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; + strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS; + } + else + { + /* Prefer out-of-line restore if it will exit. */ + if (info->first_fp_reg_save > 61) + strategy |= SAVE_INLINE_FPRS; + if (info->first_gp_reg_save > 29) + { + if (info->first_fp_reg_save == 64) + strategy |= SAVE_INLINE_GPRS; + else + strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; + } + if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO) + strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS; + } + } + else if (DEFAULT_ABI == ABI_DARWIN) + { + if (info->first_fp_reg_save > 60) + strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; + if (info->first_gp_reg_save > 29) + strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; + strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS; + } + else + { + gcc_checking_assert (DEFAULT_ABI == ABI_AIX); + if (info->first_fp_reg_save > 61) + strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; + strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; + strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS; + } + /* Don't bother to try to save things out-of-line if r11 is occupied by the static chain. It would require too much fiddling and the static chain is rarely used anyway. FPRs are saved w.r.t the stack pointer on Darwin, and AIX uses r1 or r12. */ if (using_static_chain_p && DEFAULT_ABI != ABI_AIX) - strategy |= ((DEFAULT_ABI == ABI_DARWIN - ? 0 : SAVE_INLINE_FPRS | REST_INLINE_FPRS) + strategy |= ((DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS) | SAVE_INLINE_GPRS | SAVE_INLINE_VRS | REST_INLINE_VRS); + /* We can only use the out-of-line routines to restore if we've + saved all the registers from first_fp_reg_save in the prologue. + Otherwise, we risk loading garbage. */ + if ((strategy & (SAVE_INLINE_FPRS | REST_INLINE_FPRS)) == SAVE_INLINE_FPRS) + { + int i; + + for (i = info->first_fp_reg_save; i < 64; i++) + if (!save_reg_p (i)) + { + strategy |= REST_INLINE_FPRS; + break; + } + } + /* If we are going to use store multiple, then don't even bother with the out-of-line routines, since the store-multiple instruction will always be smaller. */ @@ -17525,13 +17426,6 @@ || info->first_fp_reg_save != 64)) strategy |= REST_INLINE_GPRS; - /* We can only use load multiple or the out-of-line routines to - restore if we've used store multiple or out-of-line routines - in the prologue, i.e. if we've saved all the registers from - first_gp_reg_save. Otherwise, we risk loading garbage. */ - if ((strategy & (SAVE_INLINE_GPRS | SAVRES_MULTIPLE)) == SAVE_INLINE_GPRS) - strategy |= REST_INLINE_GPRS; - /* Saving CR interferes with the exit routines used on the SPE, so just punt here. */ if (TARGET_SPE_ABI @@ -17539,19 +17433,34 @@ && info->cr_save_p) strategy |= REST_INLINE_GPRS; -#if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD) - if (TARGET_64BIT) + /* We can only use load multiple or the out-of-line routines to + restore if we've used store multiple or out-of-line routines + in the prologue, i.e. if we've saved all the registers from + first_gp_reg_save. Otherwise, we risk loading garbage. */ + if ((strategy & (SAVE_INLINE_GPRS | REST_INLINE_GPRS | SAVRES_MULTIPLE)) + == SAVE_INLINE_GPRS) { + int i; + + for (i = info->first_gp_reg_save; i < 32; i++) + if (!save_reg_p (i)) + { + strategy |= REST_INLINE_GPRS; + break; + } + } + + if (TARGET_ELF && TARGET_64BIT) + { if (!(strategy & SAVE_INLINE_FPRS)) strategy |= SAVE_NOINLINE_FPRS_SAVES_LR; else if (!(strategy & SAVE_INLINE_GPRS) && info->first_fp_reg_save == 64) strategy |= SAVE_NOINLINE_GPRS_SAVES_LR; } -#else - if (TARGET_AIX && !(strategy & REST_INLINE_FPRS)) + else if (TARGET_AIX && !(strategy & REST_INLINE_FPRS)) strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR; -#endif + if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS)) strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;