From 31d689474b82a3c269af959070c9ad2d0cbba1eb Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 18 Feb 2001 07:27:59 +0000 Subject: [PATCH] pa.c (hppa_expand_prologue): Simplify code storing return pointer. * pa.c (hppa_expand_prologue): Simplify code storing return pointer. For large (>=8k) frames with a post_store, adjust stack pointer by 8k-64 first rather than by 64. When testing with VAL_14_BITS_P, always use the actual value rather than the value negated. Add blockage to prevent scheduling of spills before stack frame has been created. (hppa_expand_epilogue): Simplify code loading return pointer. Allow a slightly larger range for merge_sp_adjust_with_load case. When testing with VAL_14_BITS_P, always use the actual value. From-SVN: r39826 --- gcc/ChangeLog | 10 ++ gcc/config/pa/pa.c | 231 +++++++++++++++++++++------------------------ 2 files changed, 116 insertions(+), 125 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aab26f60784..c9ea2ef35d8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2001-02-18 Alan Modra + * pa.c (hppa_expand_prologue): Simplify code storing return + pointer. For large (>=8k) frames with a post_store, adjust stack + pointer by 8k-64 first rather than by 64. When testing with + VAL_14_BITS_P, always use the actual value rather than the value + negated. Add blockage to prevent scheduling of spills before + stack frame has been created. + (hppa_expand_epilogue): Simplify code loading return pointer. + Allow a slightly larger range for merge_sp_adjust_with_load case. + When testing with VAL_14_BITS_P, always use the actual value. + * pa.c (pa_adjust_insn_length): Check that block move pattern is a set before looking at operands. diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 07c0ad60fbe..08cc435f248 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -2989,70 +2989,75 @@ hppa_expand_prologue() /* Save RP first. The calling conventions manual states RP will always be stored into the caller's frame at sp-20 or sp - 16 depending on which ABI is in use. */ - if ((regs_ever_live[2] || profile_flag) && TARGET_64BIT) - store_reg (2, -16, STACK_POINTER_REGNUM); - - if ((regs_ever_live[2] || profile_flag) && ! TARGET_64BIT) - store_reg (2, -20, STACK_POINTER_REGNUM); + if (regs_ever_live[2] || profile_flag) + store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM); /* Allocate the local frame and set up the frame pointer if needed. */ - if (actual_fsize) - { - if (frame_pointer_needed) - { - /* Copy the old frame pointer temporarily into %r1. Set up the - new stack pointer, then store away the saved old frame pointer - into the stack at sp+actual_fsize and at the same time update - the stack pointer by actual_fsize bytes. Two versions, first - handles small (<8k) frames. The second handles large (>8k) - frames. */ - emit_move_insn (tmpreg, frame_pointer_rtx); - emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - if (VAL_14_BITS_P (actual_fsize)) - emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, size_rtx)); - else - { - /* It is incorrect to store the saved frame pointer at *sp, - then increment sp (writes beyond the current stack boundary). - - So instead use stwm to store at *sp and post-increment the - stack pointer as an atomic operation. Then increment sp to - finish allocating the new frame. */ - emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, - GEN_INT (64))); + if (actual_fsize != 0) + { + if (frame_pointer_needed) + { + /* Copy the old frame pointer temporarily into %r1. Set up the + new stack pointer, then store away the saved old frame pointer + into the stack at sp+actual_fsize and at the same time update + the stack pointer by actual_fsize bytes. Two versions, first + handles small (<8k) frames. The second handles large (>=8k) + frames. */ + emit_move_insn (tmpreg, frame_pointer_rtx); + emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + if (VAL_14_BITS_P (actual_fsize)) + emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, size_rtx)); + else + { + /* It is incorrect to store the saved frame pointer at *sp, + then increment sp (writes beyond the current stack boundary). + + So instead use stwm to store at *sp and post-increment the + stack pointer as an atomic operation. Then increment sp to + finish allocating the new frame. */ + int adjust1 = 8192 - 64; + int adjust2 = actual_fsize - adjust1; + rtx delta = GEN_INT (adjust1); + emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, delta)); + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + adjust2); + } + /* Prevent register spills from being scheduled before the + stack pointer is raised. Necessary as we will be storing + registers using the frame pointer as a base register, and + we happen to set fp before raising sp. */ + emit_insn (gen_blockage ()); + } + /* no frame pointer needed. */ + else + { + /* In some cases we can perform the first callee register save + and allocating the stack frame at the same time. If so, just + make a note of it and defer allocating the frame until saving + the callee registers. */ + if (VAL_14_BITS_P (actual_fsize) + && local_fsize == 0 + && ! profile_flag + && ! flag_pic) + merge_sp_adjust_with_store = 1; + /* Can not optimize. Adjust the stack frame by actual_fsize + bytes. */ + else set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, - actual_fsize - 64); - } - } - /* no frame pointer needed. */ - else - { - /* In some cases we can perform the first callee register save - and allocating the stack frame at the same time. If so, just - make a note of it and defer allocating the frame until saving - the callee registers. */ - if (VAL_14_BITS_P (-actual_fsize) - && local_fsize == 0 - && ! profile_flag - && ! flag_pic) - merge_sp_adjust_with_store = 1; - /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */ - else if (actual_fsize != 0) - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - actual_fsize); - } - } + actual_fsize); + } - /* The hppa calling conventions say that %r19, the pic offset - register, is saved at sp - 32 (in this function's frame) when - generating PIC code. FIXME: What is the correct thing to do - for functions which make no calls and allocate no frame? Do - we need to allocate a frame, or can we just omit the save? For - now we'll just omit the save. */ - if (actual_fsize != 0 && flag_pic && !TARGET_64BIT) - store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM); + /* The hppa calling conventions say that %r19, the pic offset + register, is saved at sp - 32 (in this function's frame) + when generating PIC code. FIXME: What is the correct thing + to do for functions which make no calls and allocate no + frame? Do we need to allocate a frame, or can we just omit + the save? For now we'll just omit the save. */ + if (flag_pic && !TARGET_64BIT) + store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM); + } /* Profiling code. @@ -3226,8 +3231,9 @@ void hppa_expand_epilogue () { rtx tmpreg; - int offset,i; - int merge_sp_adjust_with_load = 0; + int offset, i; + int merge_sp_adjust_with_load = 0; + int ret_off = 0; /* We will use this often. */ tmpreg = gen_rtx_REG (word_mode, 1); @@ -3235,23 +3241,24 @@ hppa_expand_epilogue () /* Try to restore RP early to avoid load/use interlocks when RP gets used in the return (bv) instruction. This appears to still be necessary even when we schedule the prologue and epilogue. */ - if (frame_pointer_needed - && !TARGET_64BIT - && (regs_ever_live [2] || profile_flag)) - load_reg (2, -20, FRAME_POINTER_REGNUM); - else if (TARGET_64BIT && frame_pointer_needed - && (regs_ever_live[2] || profile_flag)) - load_reg (2, -16, FRAME_POINTER_REGNUM); - else if (TARGET_64BIT - && ! frame_pointer_needed - && (regs_ever_live[2] || profile_flag) - && VAL_14_BITS_P (actual_fsize + 20)) - load_reg (2, - (actual_fsize + 16), STACK_POINTER_REGNUM); - /* No frame pointer, and stack is smaller than 8k. */ - else if (! frame_pointer_needed - && VAL_14_BITS_P (actual_fsize + 20) - && (regs_ever_live[2] || profile_flag)) - load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM); + if (regs_ever_live [2] || profile_flag) + { + ret_off = TARGET_64BIT ? -16 : -20; + if (frame_pointer_needed) + { + load_reg (2, ret_off, FRAME_POINTER_REGNUM); + ret_off = 0; + } + else + { + /* No frame pointer, and stack is smaller than 8k. */ + if (VAL_14_BITS_P (ret_off - actual_fsize)) + { + load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM); + ret_off = 0; + } + } + } /* General register restores. */ if (frame_pointer_needed) @@ -3272,9 +3279,9 @@ hppa_expand_epilogue () /* Only for the first load. merge_sp_adjust_with_load holds the register load with which we will merge the sp adjustment. */ - if (VAL_14_BITS_P (actual_fsize + 20) + if (merge_sp_adjust_with_load == 0 && local_fsize == 0 - && ! merge_sp_adjust_with_load) + && VAL_14_BITS_P (-actual_fsize)) merge_sp_adjust_with_load = i; else load_reg (i, offset, STACK_POINTER_REGNUM); @@ -3314,47 +3321,10 @@ hppa_expand_epilogue () This is necessary as we must not cut the stack back before all the restores are finished. */ emit_insn (gen_blockage ()); - /* No frame pointer, but we have a stack greater than 8k. We restore - %r2 very late in this case. (All other cases are restored as early - as possible.) */ - if (! frame_pointer_needed - && ! VAL_14_BITS_P (actual_fsize + 20) - && ! TARGET_64BIT - && (regs_ever_live[2] || profile_flag)) - { - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - - actual_fsize); - - /* This used to try and be clever by not depending on the value in - %r30 and instead use the value held in %r1 (so that the 2nd insn - which sets %r30 could be put in the delay slot of the return insn). - - That won't work since if the stack is exactly 8k set_reg_plus_d - doesn't set %r1, just %r30. */ - load_reg (2, - 20, STACK_POINTER_REGNUM); - } - else if (! frame_pointer_needed - && ! VAL_14_BITS_P (actual_fsize + 20) - && TARGET_64BIT - && (regs_ever_live[2] || profile_flag)) - { - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - - actual_fsize); - - /* This used to try and be clever by not depending on the value in - %r30 and instead use the value held in %r1 (so that the 2nd insn - which sets %r30 could be put in the delay slot of the return insn). - - That won't work since if the stack is exactly 8k set_reg_plus_d - doesn't set %r1, just %r30. */ - load_reg (2, - 16, STACK_POINTER_REGNUM); - } /* Reset stack pointer (and possibly frame pointer). The stack pointer is initially set to fp + 64 to avoid a race condition. */ - else if (frame_pointer_needed) + if (frame_pointer_needed) { set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); emit_insn (gen_pre_load (frame_pointer_rtx, @@ -3362,14 +3332,25 @@ hppa_expand_epilogue () GEN_INT (-64))); } /* If we were deferring a callee register restore, do it now. */ - else if (! frame_pointer_needed && merge_sp_adjust_with_load) - emit_insn (gen_pre_load (gen_rtx_REG (word_mode, merge_sp_adjust_with_load), - stack_pointer_rtx, - GEN_INT (- actual_fsize))); + else if (merge_sp_adjust_with_load) + { + rtx delta = GEN_INT (-actual_fsize); + emit_insn (gen_pre_load (gen_rtx_REG (word_mode, + merge_sp_adjust_with_load), + stack_pointer_rtx, + delta)); + } else if (actual_fsize != 0) - set_reg_plus_d (STACK_POINTER_REGNUM, - STACK_POINTER_REGNUM, - - actual_fsize); + { + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + - actual_fsize); + } + + /* If we haven't restored %r2 yet (no frame pointer, and a stack + frame greater than 8k), do so now. */ + if (ret_off != 0) + load_reg (2, ret_off, STACK_POINTER_REGNUM); } /* Set up a callee saved register for the pic offset table register. */ -- 2.30.2