* [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores. @ 2011-10-14 9:47 Iain Sandoe 2011-10-14 10:00 ` Mike Stump 0 siblings, 1 reply; 4+ messages in thread From: Iain Sandoe @ 2011-10-14 9:47 UTC (permalink / raw) To: GCC Patches; +Cc: Mike Stump [-- Attachment #1: Type: text/plain, Size: 1368 bytes --] we've been building the FPR routines for ages (for compatibility with system tools).. This implements their use and also the GPRs - the latter makes an appreciable reduction in code size, the former is neutral for non-fp intensive code but, for example, makes an appreciable reduction to the size of gnat1. this has been around my local tree for quite a few bootstrap/regtest cycles (incl. Ada and Java). OK for trunk? Iain gcc: * config/rs6000/t-darwin (LIB2FUNCS_STATIC_EXTRA): Move darwin- fpsave.asm from here to ... LIB2FUNCS_EXTRA. (LIB2FUNCS_EXTRA): Add darwin- gpsave.asm. (TARGET_LIBGCC2_CFLAGS): Ensure that fPIC and -pipe are inherited from config/t-darwin. * config/rs6000/darwin.h (FP_SAVE_INLINE): Adjust to enable. (GP_SAVE_INLINE): Likewise. (SAVE_FP_PREFIX, SAVE_FP_SUFFIX, RESTORE_FP_PREFIX, RESTORE_FP_SUFFIX): Set to empty strings. * config/rs6000/rs6000.c (rs6000_savres_strategy): Implement for Darwin. (debug_stack_info): Print savres_strategy. (rs6000_savres_routine_name): Implement for Darwin. (rs6000_make_savres_rtx): Adjust used register for Darwin. (rs6000_emit_prologue): Implement out-of-line saves for Darwin. (rs6000_output_function_prologue): Do not emit .extern for Mach-O targets. (rs6000_emit_epilogue): Implement out-of-line saves for Darwin. * config/rs6000/darwin-gpsave.asm: New file. [-- Attachment #2: 179962-ppc-ools-diff.txt --] [-- Type: text/plain, Size: 12684 bytes --] Index: gcc/config/rs6000/t-darwin =================================================================== --- gcc/config/rs6000/t-darwin (revision 179962) +++ gcc/config/rs6000/t-darwin (working copy) @@ -19,21 +19,21 @@ LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm \ $(srcdir)/config/darwin-64.c \ + $(srcdir)/config/rs6000/darwin-fpsave.asm \ + $(srcdir)/config/rs6000/darwin-gpsave.asm \ $(srcdir)/config/rs6000/darwin-world.asm LIB2FUNCS_STATIC_EXTRA = \ - $(srcdir)/config/rs6000/darwin-fpsave.asm \ $(srcdir)/config/rs6000/darwin-vecsave.asm -# The .asm files above are designed to run on all processors, -# even though they use AltiVec instructions. -Wa is used because -# -force_cpusubtype_ALL doesn't work with -dynamiclib. -# -# -pipe because there's an assembler bug, 4077127, which causes -# it to not properly process the first # directive, causing temporary -# file names to appear in stabs, causing the bootstrap to fail. Using -pipe -# works around this by not having any temporary file names. -TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10.4 +# The .asm files above are designed to run on all processors, even though +# they use AltiVec instructions. +# -Wa is used because -force_cpusubtype_ALL doesn't work with -dynamiclib. +# -mmacosx-version-min=10.4 is used to provide compatibility for code from +# earlier OSX versions. +TARGET_LIBGCC2_CFLAGS += -Wa,-force_cpusubtype_ALL -mmacosx-version-min=10.4 + darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h +darwin-gpsave.o: $(srcdir)/config/rs6000/darwin-asm.h darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h Index: gcc/config/rs6000/darwin.h =================================================================== --- gcc/config/rs6000/darwin.h (revision 179962) +++ gcc/config/rs6000/darwin.h (working copy) @@ -173,18 +173,27 @@ extern int darwin_emit_branch_islands; (RS6000_ALIGN (crtl->outgoing_args_size, 16) \ + (STACK_POINTER_OFFSET)) -/* Define cutoff for using external functions to save floating point. - Currently on Darwin, always use inline stores. */ +/* 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) < 64) +#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) < 32) +#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 #define WORLD_SAVE_P(INFO) ((INFO)->world_save_p) +/* We don't use these on Darwin, they are just place-holders. */ +#define SAVE_FP_PREFIX "" +#define SAVE_FP_SUFFIX "" +#define RESTORE_FP_PREFIX "" +#define RESTORE_FP_SUFFIX "" + /* The assembler wants the alternate register names, but without leading percent sign. */ #undef REGISTER_NAMES @@ -234,12 +243,6 @@ extern int darwin_emit_branch_islands; #undef ASM_COMMENT_START #define ASM_COMMENT_START ";" -/* FP save and restore routines. */ -#define SAVE_FP_PREFIX "._savef" -#define SAVE_FP_SUFFIX "" -#define RESTORE_FP_PREFIX "._restf" -#define RESTORE_FP_SUFFIX "" - /* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes using the "nop" instruction as padding. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 179962) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -18047,9 +18047,11 @@ rs6000_savres_strategy (rs6000_stack_t *info, /* 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. */ + static chain is rarely used anyway. FPRs are saved w.r.t the stack + pointer on Darwin. */ if (using_static_chain_p) - strategy |= SAVE_INLINE_FPRS | SAVE_INLINE_GPRS; + strategy |= (DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS) + | SAVE_INLINE_GPRS; /* If we are going to use store multiple, then don't even bother with the out-of-line routines, since the store-multiple @@ -18097,6 +18099,9 @@ rs6000_savres_strategy (rs6000_stack_t *info, 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; + return strategy; } @@ -18692,6 +18697,8 @@ debug_stack_info (rs6000_stack_t *info) if (info->reg_size != 4) fprintf (stderr, "\treg_size = %5d\n", info->reg_size); + fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy); + fprintf (stderr, "\n"); } @@ -19637,10 +19644,25 @@ rs6000_savres_routine_name (rs6000_stack_t *info, suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX; } } - else if (DEFAULT_ABI == ABI_DARWIN) - sorry ("out-of-line save/restore routines not supported on Darwin"); - sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix); + if (DEFAULT_ABI == ABI_DARWIN) + { + /* The Darwin approach is (slightly) different, in order to be + compatible with code generated by the system toolchain. There is a + single symbol for the start of save sequence, and the code here + embeds an offset into that code on the basis of the first register + to be saved. */ + prefix = savep ? "save" : "rest" ; + if (gpr) + sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31", + prefix, (lr ? "x" : ""), (regno == 13 ? "" : "+"), + (regno-13) * 4, prefix, regno); + else + sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31", + prefix, (regno == 14 ? "" : "+"), (regno-14) * 4, prefix, regno); + } + else + sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix); return savres_routine_name; } @@ -19739,7 +19761,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *info, bool savep, bool gpr, bool lr) { int i; - int offset, start_reg, end_reg, n_regs; + int offset, start_reg, end_reg, n_regs, use_reg; int reg_size = GET_MODE_SIZE (reg_mode); rtx sym; rtvec p; @@ -19760,11 +19782,12 @@ rs6000_make_savres_rtx (rs6000_stack_t *info, sym = rs6000_savres_routine_sym (info, savep, gpr, lr); RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym); + use_reg = DEFAULT_ABI == ABI_AIX ? (gpr && !lr ? 12 : 1) + : DEFAULT_ABI == ABI_DARWIN && !gpr ? 1 + : 11; RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, - gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11 - : gpr && !lr ? 12 - : 1)); + gen_rtx_REG (Pmode, use_reg)); for (i = 0; i < end_reg - start_reg; i++) { @@ -20207,8 +20230,21 @@ rs6000_emit_prologue (void) { rtx par; + if (DEFAULT_ABI == ABI_DARWIN) + { + rtx dest_reg = gen_rtx_REG (reg_mode, 11); + if (info->first_fp_reg_save == 64) + /* we only need a copy, no fprs were saved. */ + emit_move_insn (dest_reg, frame_reg_rtx); + else + { + rtx offset = GEN_INT (sp_offset + + (-8 * (64-info->first_fp_reg_save))); + emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset)); + } + } /* Need to adjust r11 (r12) if we saved any FPRs. */ - if (info->first_fp_reg_save != 64) + else if (info->first_fp_reg_save != 64) { rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX ? 12 : 11); @@ -20575,7 +20611,8 @@ rs6000_output_function_prologue (FILE *file, /* Write .extern for any function we will call to save and restore fp values. */ - if (info->first_fp_reg_save < 64) + if (info->first_fp_reg_save < 64 + && !TARGET_MACHO) { char *name; int regno = info->first_fp_reg_save - 32; @@ -21186,8 +21223,13 @@ rs6000_emit_epilogue (int sibcall) /* Emit stack reset code if we need it. */ if (can_use_exit) - rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, + { + rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, sp_offset, can_use_exit); + if (DEFAULT_ABI == ABI_DARWIN) + /* we only need a copy, no fprs were saved. */ + emit_move_insn (gen_rtx_REG (reg_mode, 11), frame_reg_rtx); + } else { emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX Index: gcc/config/rs6000/darwin-gpsave.asm =================================================================== --- gcc/config/rs6000/darwin-gpsave.asm (revision 0) +++ gcc/config/rs6000/darwin-gpsave.asm (revision 0) @@ -0,0 +1,118 @@ +/* This file contains the GPR save and restore routines for Darwin. + * + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * <http://www.gnu.org/licenses/>. + */ + +/* Contributed by Iain Sandoe <iains@gcc.gnu.org> */ + +/* Like their FP and VEC counterparts, these routines have only one externally + visible entry point. Calls have to be constructed as offsets from this. + (I.E. callers have to jump to "saveGPR+((x-13)*4" to save registers x..31). + + Each save/load instruction is 4 bytes long (for both m32 and m64 builds). + + The save/restores here are done w.r.t r11. + + restGPRx restores the link reg from the stack and returns to the saved + address. + + */ + +#include "darwin-asm.h" + + .text + .align 2 + + .private_extern saveGPR +saveGPR: + stg r13,(-19 * GPR_BYTES)(r11) + stg r14,(-18 * GPR_BYTES)(r11) + stg r15,(-17 * GPR_BYTES)(r11) + stg r16,(-16 * GPR_BYTES)(r11) + stg r17,(-15 * GPR_BYTES)(r11) + stg r18,(-14 * GPR_BYTES)(r11) + stg r19,(-13 * GPR_BYTES)(r11) + stg r20,(-12 * GPR_BYTES)(r11) + stg r21,(-11 * GPR_BYTES)(r11) + stg r22,(-10 * GPR_BYTES)(r11) + stg r23,( -9 * GPR_BYTES)(r11) + stg r24,( -8 * GPR_BYTES)(r11) + stg r25,( -7 * GPR_BYTES)(r11) + stg r26,( -6 * GPR_BYTES)(r11) + stg r27,( -5 * GPR_BYTES)(r11) + stg r28,( -4 * GPR_BYTES)(r11) + stg r29,( -3 * GPR_BYTES)(r11) + stg r30,( -2 * GPR_BYTES)(r11) + stg r31,( -1 * GPR_BYTES)(r11) + blr + +/* */ + + .private_extern restGPR +restGPR: + lg r13,(-19 * GPR_BYTES)(r11) + lg r14,(-18 * GPR_BYTES)(r11) + lg r15,(-17 * GPR_BYTES)(r11) + lg r16,(-16 * GPR_BYTES)(r11) + lg r17,(-15 * GPR_BYTES)(r11) + lg r18,(-14 * GPR_BYTES)(r11) + lg r19,(-13 * GPR_BYTES)(r11) + lg r20,(-12 * GPR_BYTES)(r11) + lg r21,(-11 * GPR_BYTES)(r11) + lg r22,(-10 * GPR_BYTES)(r11) + lg r23,( -9 * GPR_BYTES)(r11) + lg r24,( -8 * GPR_BYTES)(r11) + lg r25,( -7 * GPR_BYTES)(r11) + lg r26,( -6 * GPR_BYTES)(r11) + lg r27,( -5 * GPR_BYTES)(r11) + lg r28,( -4 * GPR_BYTES)(r11) + lg r29,( -3 * GPR_BYTES)(r11) + lg r30,( -2 * GPR_BYTES)(r11) + lg r31,( -1 * GPR_BYTES)(r11) + blr + + .private_extern restGPRx +restGPRx: + lg r13,(-19 * GPR_BYTES)(r11) + lg r14,(-18 * GPR_BYTES)(r11) + lg r15,(-17 * GPR_BYTES)(r11) + lg r16,(-16 * GPR_BYTES)(r11) + lg r17,(-15 * GPR_BYTES)(r11) + lg r18,(-14 * GPR_BYTES)(r11) + lg r19,(-13 * GPR_BYTES)(r11) + lg r20,(-12 * GPR_BYTES)(r11) + lg r21,(-11 * GPR_BYTES)(r11) + lg r22,(-10 * GPR_BYTES)(r11) + lg r23,( -9 * GPR_BYTES)(r11) + lg r24,( -8 * GPR_BYTES)(r11) + lg r25,( -7 * GPR_BYTES)(r11) + lg r26,( -6 * GPR_BYTES)(r11) + lg r27,( -5 * GPR_BYTES)(r11) + lg r28,( -4 * GPR_BYTES)(r11) + lg r29,( -3 * GPR_BYTES)(r11) + /* Like the FP restore, we start from the offset for r30 + thus a restore of only r31 is not going to work. */ + lg r0,SAVED_LR_OFFSET(r1) + lg r30,( -2 * GPR_BYTES)(r11) + mtlr r0 + lg r31,( -1 * GPR_BYTES)(r11) + blr [-- Attachment #3: Type: text/plain, Size: 3 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores. 2011-10-14 9:47 [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores Iain Sandoe @ 2011-10-14 10:00 ` Mike Stump 2011-10-28 11:04 ` Iain Sandoe 0 siblings, 1 reply; 4+ messages in thread From: Mike Stump @ 2011-10-14 10:00 UTC (permalink / raw) To: Iain Sandoe; +Cc: GCC Patches, Mike Stump On Oct 14, 2011, at 2:05 AM, Iain Sandoe wrote: > This implements their use and also the GPRs - the latter makes an appreciable reduction in code size, > OK for trunk? Ok. Watch for problems with async stack walking (hitting sample in Activity Monitor, or the walking done by CrashReporter)... that's the only thing I can think of that might be strange. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores. 2011-10-14 10:00 ` Mike Stump @ 2011-10-28 11:04 ` Iain Sandoe 2011-10-28 19:24 ` Mike Stump 0 siblings, 1 reply; 4+ messages in thread From: Iain Sandoe @ 2011-10-28 11:04 UTC (permalink / raw) To: Mike Stump; +Cc: GCC Patches, David Edelsohn [-- Attachment #1: Type: text/plain, Size: 1478 bytes --] On 14 Oct 2011, at 10:29, Mike Stump wrote: > On Oct 14, 2011, at 2:05 AM, Iain Sandoe wrote: >> This implements their use and also the GPRs - the latter makes an >> appreciable reduction in code size, > >> OK for trunk? > > Ok. Watch for problems with async stack walking (hitting sample in > Activity Monitor, or the walking done by CrashReporter)... that's > the only thing I can think of that might be strange. This has taken some time to apply because of various bootstrap issues (version applied is attached) In answer to your observation; I didn't expect problems with FPR saves because the vendor's tools implement those. To test what you suggested I built some code that dropped down a few stack levels (with saves of FPR/GPR) and then either aborts or spins on a sleep. The crashlogs from the abort() and the instrumentation samples from the sleep were OK. ==== During doing this (and checking crosses to aix and eabisim) I noticed the following in rs6000/sysv4.h: /* And similarly for general purpose registers. */ #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32 \ && !optimize_size) which gives rise to code (with -Os) like: main: mr 11,1 #, stwu 1,-504(1) #,, mflr 0 #, bl _savegpr_31 # lis 31,.LANCHOR0@ha # tmp137, which I doubt is what was intended .... ... copying David in case he feels that should be amended. cheers Iain [-- Attachment #2: 180609-darwinppc-ools-diff.txt --] [-- Type: text/plain, Size: 13899 bytes --] Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 180609) +++ gcc/ChangeLog (working copy) @@ -1,3 +1,23 @@ +2011-10-28 Iain Sandoe <iains@gcc.gnu.org> + + * config/rs6000/t-darwin (LIB2FUNCS_STATIC_EXTRA): + Move darwin-fpsave.asm from here to ... LIB2FUNCS_EXTRA. + (LIB2FUNCS_EXTRA): Add darwin-gpsave.asm. + (TARGET_LIBGCC2_CFLAGS): Ensure that fPIC and -pipe are inherited from + config/t-darwin. + * config/rs6000/darwin.h (FP_SAVE_INLINE): Adjust to enable. + (GP_SAVE_INLINE): Likewise. + (SAVE_FP_PREFIX, SAVE_FP_SUFFIX, RESTORE_FP_PREFIX, + RESTORE_FP_SUFFIX): Set to empty strings. + * config/rs6000/rs6000.c (rs6000_savres_strategy): Implement for Darwin. + (debug_stack_info): Print savres_strategy. + (rs6000_savres_routine_name): Implement for Darwin. + (rs6000_make_savres_rtx): Adjust used register for Darwin. + (rs6000_emit_prologue): Implement out-of-line saves for Darwin. + (rs6000_output_function_prologue): Don't emit .extern for Mach-O. + (rs6000_emit_epilogue): Implement out-of-line saves for Darwin. + * config/rs6000/darwin-gpsave.asm: New file. + 2011-10-28 Jakub Jelinek <jakub@redhat.com> * config/i386/sse.md (VI4SD_AVX2): Removed. Index: gcc/config/rs6000/t-darwin =================================================================== --- gcc/config/rs6000/t-darwin (revision 180609) +++ gcc/config/rs6000/t-darwin (working copy) @@ -19,21 +19,21 @@ LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm \ $(srcdir)/config/darwin-64.c \ + $(srcdir)/config/rs6000/darwin-fpsave.asm \ + $(srcdir)/config/rs6000/darwin-gpsave.asm \ $(srcdir)/config/rs6000/darwin-world.asm LIB2FUNCS_STATIC_EXTRA = \ - $(srcdir)/config/rs6000/darwin-fpsave.asm \ $(srcdir)/config/rs6000/darwin-vecsave.asm -# The .asm files above are designed to run on all processors, -# even though they use AltiVec instructions. -Wa is used because -# -force_cpusubtype_ALL doesn't work with -dynamiclib. -# -# -pipe because there's an assembler bug, 4077127, which causes -# it to not properly process the first # directive, causing temporary -# file names to appear in stabs, causing the bootstrap to fail. Using -pipe -# works around this by not having any temporary file names. -TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10.4 +# The .asm files above are designed to run on all processors, even though +# they use AltiVec instructions. +# -Wa is used because -force_cpusubtype_ALL doesn't work with -dynamiclib. +# -mmacosx-version-min=10.4 is used to provide compatibility for code from +# earlier OSX versions. +TARGET_LIBGCC2_CFLAGS += -Wa,-force_cpusubtype_ALL -mmacosx-version-min=10.4 + darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h +darwin-gpsave.o: $(srcdir)/config/rs6000/darwin-asm.h darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h Index: gcc/config/rs6000/darwin.h =================================================================== --- gcc/config/rs6000/darwin.h (revision 180609) +++ gcc/config/rs6000/darwin.h (working copy) @@ -173,18 +173,27 @@ extern int darwin_emit_branch_islands; (RS6000_ALIGN (crtl->outgoing_args_size, 16) \ + (STACK_POINTER_OFFSET)) -/* Define cutoff for using external functions to save floating point. - Currently on Darwin, always use inline stores. */ +/* 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) < 64) +#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) < 32) +#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 #define WORLD_SAVE_P(INFO) ((INFO)->world_save_p) +/* We don't use these on Darwin, they are just place-holders. */ +#define SAVE_FP_PREFIX "" +#define SAVE_FP_SUFFIX "" +#define RESTORE_FP_PREFIX "" +#define RESTORE_FP_SUFFIX "" + /* The assembler wants the alternate register names, but without leading percent sign. */ #undef REGISTER_NAMES @@ -234,12 +243,6 @@ extern int darwin_emit_branch_islands; #undef ASM_COMMENT_START #define ASM_COMMENT_START ";" -/* FP save and restore routines. */ -#define SAVE_FP_PREFIX "._savef" -#define SAVE_FP_SUFFIX "" -#define RESTORE_FP_PREFIX "._restf" -#define RESTORE_FP_SUFFIX "" - /* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes using the "nop" instruction as padding. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 180609) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -17983,9 +17983,11 @@ rs6000_savres_strategy (rs6000_stack_t *info, /* 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. */ + static chain is rarely used anyway. FPRs are saved w.r.t the stack + pointer on Darwin. */ if (using_static_chain_p) - strategy |= SAVE_INLINE_FPRS | SAVE_INLINE_GPRS; + strategy |= (DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS) + | SAVE_INLINE_GPRS; /* If we are going to use store multiple, then don't even bother with the out-of-line routines, since the store-multiple @@ -18033,6 +18035,9 @@ rs6000_savres_strategy (rs6000_stack_t *info, 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; + return strategy; } @@ -18628,6 +18633,8 @@ debug_stack_info (rs6000_stack_t *info) if (info->reg_size != 4) fprintf (stderr, "\treg_size = %5d\n", info->reg_size); + fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy); + fprintf (stderr, "\n"); } @@ -19573,10 +19580,25 @@ rs6000_savres_routine_name (rs6000_stack_t *info, suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX; } } - else if (DEFAULT_ABI == ABI_DARWIN) - sorry ("out-of-line save/restore routines not supported on Darwin"); - sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix); + if (DEFAULT_ABI == ABI_DARWIN) + { + /* The Darwin approach is (slightly) different, in order to be + compatible with code generated by the system toolchain. There is a + single symbol for the start of save sequence, and the code here + embeds an offset into that code on the basis of the first register + to be saved. */ + prefix = savep ? "save" : "rest" ; + if (gpr) + sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31", + prefix, (lr ? "x" : ""), (regno == 13 ? "" : "+"), + (regno-13) * 4, prefix, regno); + else + sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31", + prefix, (regno == 14 ? "" : "+"), (regno-14) * 4, prefix, regno); + } + else + sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix); return savres_routine_name; } @@ -19678,7 +19700,7 @@ rs6000_emit_savres_rtx (rs6000_stack_t *info, bool savep, bool gpr, bool lr) { int i; - int offset, start_reg, end_reg, n_regs; + int offset, start_reg, end_reg, n_regs, use_reg; int reg_size = GET_MODE_SIZE (reg_mode); rtx sym; rtvec p; @@ -19700,11 +19722,12 @@ rs6000_emit_savres_rtx (rs6000_stack_t *info, sym = rs6000_savres_routine_sym (info, savep, gpr, lr); RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym); + use_reg = DEFAULT_ABI == ABI_AIX ? (gpr && !lr ? 12 : 1) + : DEFAULT_ABI == ABI_DARWIN && !gpr ? 1 + : 11; RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, - gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11 - : gpr && !lr ? 12 - : 1)); + gen_rtx_REG (Pmode, use_reg)); for (i = 0; i < end_reg - start_reg; i++) { @@ -20148,8 +20171,21 @@ rs6000_emit_prologue (void) } else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline) { + if (DEFAULT_ABI == ABI_DARWIN) + { + rtx dest_reg = gen_rtx_REG (reg_mode, 11); + if (info->first_fp_reg_save == 64) + /* we only need a copy, no fprs were saved. */ + emit_move_insn (dest_reg, frame_reg_rtx); + else + { + rtx offset = GEN_INT (sp_offset + + (-8 * (64-info->first_fp_reg_save))); + emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset)); + } + } /* Need to adjust r11 (r12) if we saved any FPRs. */ - if (info->first_fp_reg_save != 64) + else if (info->first_fp_reg_save != 64) { rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX ? 12 : 11); @@ -20515,7 +20551,8 @@ rs6000_output_function_prologue (FILE *file, /* Write .extern for any function we will call to save and restore fp values. */ - if (info->first_fp_reg_save < 64) + if (info->first_fp_reg_save < 64 + && !TARGET_MACHO) { char *name; int regno = info->first_fp_reg_save - 32; @@ -21138,7 +21175,11 @@ rs6000_emit_epilogue (int sibcall) if (can_use_exit) { rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, - sp_offset, can_use_exit); + sp_offset, can_use_exit); + if (DEFAULT_ABI == ABI_DARWIN) + /* we only need a copy, no fprs were saved. */ + emit_move_insn (gen_rtx_REG (reg_mode, 11), frame_reg_rtx); + if (info->cr_save_p) rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple); } Index: gcc/config/rs6000/darwin-gpsave.asm =================================================================== --- gcc/config/rs6000/darwin-gpsave.asm (revision 0) +++ gcc/config/rs6000/darwin-gpsave.asm (revision 0) @@ -0,0 +1,118 @@ +/* This file contains the GPR save and restore routines for Darwin. + * + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * <http://www.gnu.org/licenses/>. + */ + +/* Contributed by Iain Sandoe <iains@gcc.gnu.org> */ + +/* Like their FP and VEC counterparts, these routines have only one externally + visible entry point. Calls have to be constructed as offsets from this. + (I.E. callers have to jump to "saveGPR+((x-13)*4" to save registers x..31). + + Each save/load instruction is 4 bytes long (for both m32 and m64 builds). + + The save/restores here are done w.r.t r11. + + restGPRx restores the link reg from the stack and returns to the saved + address. + + */ + +#include "darwin-asm.h" + + .text + .align 2 + + .private_extern saveGPR +saveGPR: + stg r13,(-19 * GPR_BYTES)(r11) + stg r14,(-18 * GPR_BYTES)(r11) + stg r15,(-17 * GPR_BYTES)(r11) + stg r16,(-16 * GPR_BYTES)(r11) + stg r17,(-15 * GPR_BYTES)(r11) + stg r18,(-14 * GPR_BYTES)(r11) + stg r19,(-13 * GPR_BYTES)(r11) + stg r20,(-12 * GPR_BYTES)(r11) + stg r21,(-11 * GPR_BYTES)(r11) + stg r22,(-10 * GPR_BYTES)(r11) + stg r23,( -9 * GPR_BYTES)(r11) + stg r24,( -8 * GPR_BYTES)(r11) + stg r25,( -7 * GPR_BYTES)(r11) + stg r26,( -6 * GPR_BYTES)(r11) + stg r27,( -5 * GPR_BYTES)(r11) + stg r28,( -4 * GPR_BYTES)(r11) + stg r29,( -3 * GPR_BYTES)(r11) + stg r30,( -2 * GPR_BYTES)(r11) + stg r31,( -1 * GPR_BYTES)(r11) + blr + +/* */ + + .private_extern restGPR +restGPR: + lg r13,(-19 * GPR_BYTES)(r11) + lg r14,(-18 * GPR_BYTES)(r11) + lg r15,(-17 * GPR_BYTES)(r11) + lg r16,(-16 * GPR_BYTES)(r11) + lg r17,(-15 * GPR_BYTES)(r11) + lg r18,(-14 * GPR_BYTES)(r11) + lg r19,(-13 * GPR_BYTES)(r11) + lg r20,(-12 * GPR_BYTES)(r11) + lg r21,(-11 * GPR_BYTES)(r11) + lg r22,(-10 * GPR_BYTES)(r11) + lg r23,( -9 * GPR_BYTES)(r11) + lg r24,( -8 * GPR_BYTES)(r11) + lg r25,( -7 * GPR_BYTES)(r11) + lg r26,( -6 * GPR_BYTES)(r11) + lg r27,( -5 * GPR_BYTES)(r11) + lg r28,( -4 * GPR_BYTES)(r11) + lg r29,( -3 * GPR_BYTES)(r11) + lg r30,( -2 * GPR_BYTES)(r11) + lg r31,( -1 * GPR_BYTES)(r11) + blr + + .private_extern restGPRx +restGPRx: + lg r13,(-19 * GPR_BYTES)(r11) + lg r14,(-18 * GPR_BYTES)(r11) + lg r15,(-17 * GPR_BYTES)(r11) + lg r16,(-16 * GPR_BYTES)(r11) + lg r17,(-15 * GPR_BYTES)(r11) + lg r18,(-14 * GPR_BYTES)(r11) + lg r19,(-13 * GPR_BYTES)(r11) + lg r20,(-12 * GPR_BYTES)(r11) + lg r21,(-11 * GPR_BYTES)(r11) + lg r22,(-10 * GPR_BYTES)(r11) + lg r23,( -9 * GPR_BYTES)(r11) + lg r24,( -8 * GPR_BYTES)(r11) + lg r25,( -7 * GPR_BYTES)(r11) + lg r26,( -6 * GPR_BYTES)(r11) + lg r27,( -5 * GPR_BYTES)(r11) + lg r28,( -4 * GPR_BYTES)(r11) + lg r29,( -3 * GPR_BYTES)(r11) + /* Like the FP restore, we start from the offset for r30 + thus a restore of only r31 is not going to work. */ + lg r0,SAVED_LR_OFFSET(r1) + lg r30,( -2 * GPR_BYTES)(r11) + mtlr r0 + lg r31,( -1 * GPR_BYTES)(r11) + blr [-- Attachment #3: Type: text/plain, Size: 3 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores. 2011-10-28 11:04 ` Iain Sandoe @ 2011-10-28 19:24 ` Mike Stump 0 siblings, 0 replies; 4+ messages in thread From: Mike Stump @ 2011-10-28 19:24 UTC (permalink / raw) To: Iain Sandoe; +Cc: Mike Stump, GCC Patches, David Edelsohn On Oct 28, 2011, at 3:40 AM, Iain Sandoe wrote: > To test what you suggested I built some code that dropped down a few stack levels (with saves of FPR/GPR) and then either aborts or spins on a sleep. Uhm, that's not enough, for async, you need to spawn threads that do the interesting stuff in those threads and then have the main code abort. ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-10-28 18:48 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-10-14 9:47 [Patch Darwin/PPC] implement out-of-line FPR/GPR saves/restores Iain Sandoe 2011-10-14 10:00 ` Mike Stump 2011-10-28 11:04 ` Iain Sandoe 2011-10-28 19:24 ` Mike Stump
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).