From f90b51f1ff42f7bfe45855d1f5f240cbe89f8a2c Mon Sep 17 00:00:00 2001 From: rearnsha Date: Sat, 20 Aug 2005 10:31:42 +0000 Subject: [PATCH] * arm.h (arm_stack_offsets): Add locals_base field. * arm.c (arm_get_frame_offsets): Compute it. (thumb_compute_initial_elimination offset): Make the Thumb frame pointer point to the base of the local variables. (thumb_expand_prologue): Update accordingly. (thumb_expand_epilogue): Likewise. * arm.md (thumb_movhi_clobber): Make this insn a define_expand. Change mode of clobbered scratch to DImode. Handle a case that's known to need this. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@103301 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 ++++++++++ gcc/config/arm/arm.c | 69 +++++++++++++++++++++++++++++++++------------------ gcc/config/arm/arm.h | 1 + gcc/config/arm/arm.md | 20 ++++++++++----- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 949087ecc77..795baf1f304 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-08-20 Richard Earnshaw + + * arm.h (arm_stack_offsets): Add locals_base field. + * arm.c (arm_get_frame_offsets): Compute it. + (thumb_compute_initial_elimination offset): Make the Thumb frame + pointer point to the base of the local variables. + (thumb_expand_prologue): Update accordingly. + (thumb_expand_epilogue): Likewise. + + * arm.md (thumb_movhi_clobber): Make this insn a define_expand. Change + mode of clobbered scratch to DImode. Handle a case that's known to + need this. + 2005-08-19 David Edelsohn * config/rs6000/rs6000.md (gt0): Delete. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 0235c53b08e..9037838d8cb 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -9992,7 +9992,7 @@ thumb_force_lr_save (void) | | \ | | local | | variables - | | / + locals base pointer -> | | / -- | | \ | | outgoing @@ -10109,8 +10109,9 @@ arm_get_frame_offsets (void) && (offsets->soft_frame & 7)) offsets->soft_frame += 4; - offsets->outgoing_args = offsets->soft_frame + frame_size - + current_function_outgoing_args_size; + offsets->locals_base = offsets->soft_frame + frame_size; + offsets->outgoing_args = (offsets->locals_base + + current_function_outgoing_args_size); if (ARM_DOUBLEWORD_ALIGN) { @@ -13158,8 +13159,10 @@ arm_init_expanders (void) } -/* Like arm_compute_initial_elimination offset. Simpler because - THUMB_HARD_FRAME_POINTER isn't actually the ABI specified frame pointer. */ +/* Like arm_compute_initial_elimination offset. Simpler because there + isn't an ABI specified frame pointer for Thumb. Instead, we set it + to point at the base of the local variables after static stack + space for a function has been allocated. */ HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) @@ -13179,10 +13182,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) case FRAME_POINTER_REGNUM: return offsets->soft_frame - offsets->saved_args; - case THUMB_HARD_FRAME_POINTER_REGNUM: case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->saved_args; + case THUMB_HARD_FRAME_POINTER_REGNUM: + return offsets->locals_base - offsets->saved_args; + default: gcc_unreachable (); } @@ -13194,10 +13199,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) case STACK_POINTER_REGNUM: return offsets->outgoing_args - offsets->soft_frame; - case THUMB_HARD_FRAME_POINTER_REGNUM: case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->soft_frame; + case THUMB_HARD_FRAME_POINTER_REGNUM: + return offsets->locals_base - offsets->soft_frame; + default: gcc_unreachable (); } @@ -13239,18 +13246,11 @@ thumb_expand_prologue (void) if (flag_pic) arm_load_pic_register (live_regs_mask); - offsets = arm_get_frame_offsets (); - - if (frame_pointer_needed) - { - insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, - stack_pointer_rtx)); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (CALLER_INTERWORKING_SLOT_SIZE > 0) + if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0) emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM), stack_pointer_rtx); + offsets = arm_get_frame_offsets (); amount = offsets->outgoing_args - offsets->saved_regs; if (amount) { @@ -13336,12 +13336,29 @@ thumb_expand_prologue (void) REG_NOTES (insn)); } } - /* If the frame pointer is needed, emit a special barrier that - will prevent the scheduler from moving stores to the frame - before the stack adjustment. */ - if (frame_pointer_needed) - emit_insn (gen_stack_tie (stack_pointer_rtx, - hard_frame_pointer_rtx)); + } + + if (frame_pointer_needed) + { + amount = offsets->outgoing_args - offsets->locals_base; + + if (amount < 1024) + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, GEN_INT (amount))); + else + { + emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount))); + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + hard_frame_pointer_rtx, + stack_pointer_rtx)); + dwarf = gen_rtx_SET (SImode, hard_frame_pointer_rtx, + plus_constant (stack_pointer_rtx, amount)); + RTX_FRAME_RELATED_P (dwarf) = 1; + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, + REG_NOTES (insn)); + } + + RTX_FRAME_RELATED_P (insn) = 1; } if (current_function_profile || !TARGET_SCHED_PROLOG) @@ -13373,8 +13390,12 @@ thumb_expand_epilogue (void) amount = offsets->outgoing_args - offsets->saved_regs; if (frame_pointer_needed) - emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); - else if (amount) + { + emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); + amount = offsets->locals_base - offsets->saved_regs; + } + + if (amount) { if (amount < 512) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index a434d4f6f55..64b5e373d3c 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1476,6 +1476,7 @@ typedef struct arm_stack_offsets GTY(()) int frame; /* ARM_HARD_FRAME_POINTER_REGNUM. */ int saved_regs; int soft_frame; /* FRAME_POINTER_REGNUM. */ + int locals_base; /* THUMB_HARD_FRAME_POINTER_REGNUM. */ int outgoing_args; /* STACK_POINTER_REGNUM. */ } arm_stack_offsets; diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index eaa7d51c106..3bc62de65e9 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4951,13 +4951,21 @@ [(set_attr "predicable" "yes")] ) -(define_insn "thumb_movhi_clobber" - [(set (match_operand:HI 0 "memory_operand" "=m") - (match_operand:HI 1 "register_operand" "l")) - (clobber (match_operand:SI 2 "register_operand" "=&l"))] +(define_expand "thumb_movhi_clobber" + [(set (match_operand:HI 0 "memory_operand" "") + (match_operand:HI 1 "register_operand" "")) + (clobber (match_operand:DI 2 "register_operand" ""))] "TARGET_THUMB" - "* - gcc_unreachable ();" + " + if (strict_memory_address_p (HImode, XEXP (operands[0], 0)) + && REGNO (operands[1]) <= LAST_LO_REGNUM) + { + emit_insn (gen_movhi (operands[0], operands[1])); + DONE; + } + /* XXX Fixme, need to handle other cases here as well. */ + gcc_unreachable (); + " ) ;; We use a DImode scratch because we may occasionally need an additional -- 2.11.4.GIT