diff options
author | Paul Brook <pbrook@gcc.gnu.org> | 2008-03-11 17:43:22 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2008-03-11 17:43:22 +0000 |
commit | ec6237e4403c864d94378d7c6bd96a01ff2bc06e (patch) | |
tree | 9aab21af74f13d71b320c1bcf209e001e2f18eeb /gcc | |
parent | 2f6025a15b2eed2f15eb1a997330f097e4814641 (diff) | |
download | gcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.zip gcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.tar.gz gcc-ec6237e4403c864d94378d7c6bd96a01ff2bc06e.tar.bz2 |
arm.c (use_return_insn): Check TARGET_APCS_FRAME.
2008-03-11 Paul Brook <paul@codesourcery.com>
Vladimir Prus <vladimir@codesourcery.com>
* config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME.
(arm_compute_save_reg0_reg12_mask): Always
check if register 11 must be saved. Always safe hard frame pointer
when frame_pointer_needeed.
(arm_compute_save_reg_mask): Save IP and PC
only with apcs frames.
(arm_output_epilogue): Adjust Thumb2 codepath to
be also invoked and work for ARM non-apcs frames.
(arm_expand_prologue): Don't bother saving IP
for non-apcs frame, since it's not clobbered by
prologue code. Implement non-apcs frame
layout.
From-SVN: r133117
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 105 |
2 files changed, 86 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b7f9d7..c3fb00a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2008-03-11 Paul Brook <paul@codesourcery.com> + Vladimir Prus <vladimir@codesourcery.com> + + * config/arm/arm.c (use_return_insn): Check TARGET_APCS_FRAME. + (arm_compute_save_reg0_reg12_mask): Always + check if register 11 must be saved. Always safe hard frame pointer + when frame_pointer_needeed. + (arm_compute_save_reg_mask): Save IP and PC + only with apcs frames. + (arm_output_epilogue): Adjust Thumb2 codepath to + be also invoked and work for ARM non-apcs frames. + (arm_expand_prologue): Don't bother saving IP + for non-apcs frame, since it's not clobbered by + prologue code. Implement non-apcs frame + layout. + 2008-03-11 Paolo Bonzini <bonzini@gnu.org> PR rtl-optimization/35281 @@ -6,9 +22,9 @@ 2008-03-11 Paolo Bonzini <bonzini@gnu.org> - * langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete. - * langhooks.h (struct lang_hooks): Delete clear_binding_stack member. - * toplev.c (compile_file): Don't call it. + * langhooks-def.h (LANG_HOOKS_CLEAR_BINDING_STACK): Delete. + * langhooks.h (struct lang_hooks): Delete clear_binding_stack member. + * toplev.c (compile_file): Don't call it. 2008-03-11 Uros Bizjak <ubizjak@gmail.com> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index bddb0e2..531dd1fe 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1662,7 +1662,8 @@ use_return_insn (int iscond, rtx sibling) || current_function_calls_alloca /* Or if there is a stack adjustment. However, if the stack pointer is saved on the stack, we can use a pre-incrementing stack load. */ - || !(stack_adjust == 0 || (frame_pointer_needed && stack_adjust == 4))) + || !(stack_adjust == 0 || (TARGET_APCS_FRAME && frame_pointer_needed + && stack_adjust == 4))) return 0; saved_int_regs = arm_compute_save_reg_mask (); @@ -10706,25 +10707,14 @@ arm_compute_save_reg0_reg12_mask (void) } else { - /* In arm mode we handle r11 (FP) as a special case. */ - unsigned last_reg = TARGET_ARM ? 10 : 11; - /* In the normal case we only need to save those registers which are call saved and which are used by this function. */ - for (reg = 0; reg <= last_reg; reg++) + for (reg = 0; reg <= 11; reg++) if (df_regs_ever_live_p (reg) && ! call_used_regs[reg]) save_reg_mask |= (1 << reg); /* Handle the frame pointer as a special case. */ - if (! TARGET_APCS_FRAME - && ! frame_pointer_needed - && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM) - && ! call_used_regs[HARD_FRAME_POINTER_REGNUM]) - save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM; - else if (! TARGET_APCS_FRAME - && ! frame_pointer_needed - && df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM) - && ! call_used_regs[HARD_FRAME_POINTER_REGNUM]) + if (frame_pointer_needed) save_reg_mask |= 1 << HARD_FRAME_POINTER_REGNUM; /* If we aren't loading the PIC register, @@ -10775,7 +10765,7 @@ arm_compute_save_reg_mask (void) /* If we are creating a stack frame, then we must save the frame pointer, IP (which will hold the old stack pointer), LR and the PC. */ - if (frame_pointer_needed && TARGET_ARM) + if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM) save_reg_mask |= (1 << ARM_HARD_FRAME_POINTER_REGNUM) | (1 << IP_REGNUM) @@ -11306,7 +11296,7 @@ arm_output_epilogue (rtx sibling) if (saved_regs_mask & (1 << reg)) floats_offset += 4; - if (frame_pointer_needed && TARGET_ARM) + if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM) { /* This variable is for the Virtual Frame Pointer, not VFP regs. */ int vfp_offset = offsets->frame; @@ -11452,32 +11442,60 @@ arm_output_epilogue (rtx sibling) } else { + /* This branch is executed for ARM mode (non-apcs frames) and + Thumb-2 mode. Frame layout is essentially the same for those + cases, except that in ARM mode frame pointer points to the + first saved register, while in Thumb-2 mode the frame pointer points + to the last saved register. + + It is possible to make frame pointer point to last saved + register in both cases, and remove some conditionals below. + That means that fp setup in prologue would be just "mov fp, sp" + and sp restore in epilogue would be just "mov sp, fp", whereas + now we have to use add/sub in those cases. However, the value + of that would be marginal, as both mov and add/sub are 32-bit + in ARM mode, and it would require extra conditionals + in arm_expand_prologue to distingish ARM-apcs-frame case + (where frame pointer is required to point at first register) + and ARM-non-apcs-frame. Therefore, such change is postponed + until real need arise. */ HOST_WIDE_INT amount; int rfe; /* Restore stack pointer if necessary. */ - if (frame_pointer_needed) - { - /* For Thumb-2 restore sp from the frame pointer. - Operand restrictions mean we have to increment FP, then copy - to SP. */ - amount = offsets->locals_base - offsets->saved_regs; - operands[0] = hard_frame_pointer_rtx; - } - else + if (TARGET_ARM && frame_pointer_needed) { operands[0] = stack_pointer_rtx; - amount = offsets->outgoing_args - offsets->saved_regs; + operands[1] = hard_frame_pointer_rtx; + + operands[2] = GEN_INT (offsets->frame - offsets->saved_regs); + output_add_immediate (operands); } - - if (amount) + else { - operands[1] = operands[0]; - operands[2] = GEN_INT (amount); - output_add_immediate (operands); + if (frame_pointer_needed) + { + /* For Thumb-2 restore sp from the frame pointer. + Operand restrictions mean we have to incrememnt FP, then copy + to SP. */ + amount = offsets->locals_base - offsets->saved_regs; + operands[0] = hard_frame_pointer_rtx; + } + else + { + operands[0] = stack_pointer_rtx; + amount = offsets->outgoing_args - offsets->saved_regs; + } + + if (amount) + { + operands[1] = operands[0]; + operands[2] = GEN_INT (amount); + output_add_immediate (operands); + } + if (frame_pointer_needed) + asm_fprintf (f, "\tmov\t%r, %r\n", + SP_REGNUM, HARD_FRAME_POINTER_REGNUM); } - if (frame_pointer_needed) - asm_fprintf (f, "\tmov\t%r, %r\n", - SP_REGNUM, HARD_FRAME_POINTER_REGNUM); if (arm_fpu_arch == FPUTYPE_FPA_EMU2) { @@ -12320,7 +12338,10 @@ arm_expand_prologue (void) emit_insn (gen_movsi (stack_pointer_rtx, r1)); } - if (frame_pointer_needed && TARGET_ARM) + /* For APCS frames, if IP register is clobbered + when creating frame, save that register in a special + way. */ + if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM) { if (IS_INTERRUPT (func_type)) { @@ -12419,13 +12440,13 @@ arm_expand_prologue (void) } /* If this is an interrupt service routine, and the link register - is going to be pushed, and we are not creating a stack frame, - (which would involve an extra push of IP and a pop in the epilogue) + is going to be pushed, and we're not generating extra + push of IP (needed when frame is needed and frame layout if apcs), subtracting four from LR now will mean that the function return can be done with a single instruction. */ if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ) && (live_regs_mask & (1 << LR_REGNUM)) != 0 - && ! frame_pointer_needed + && !(frame_pointer_needed && TARGET_APCS_FRAME) && TARGET_ARM) { rtx lr = gen_rtx_REG (SImode, LR_REGNUM); @@ -12446,6 +12467,7 @@ arm_expand_prologue (void) if (frame_pointer_needed && TARGET_ARM) { /* Create the new frame pointer. */ + if (TARGET_APCS_FRAME) { insn = GEN_INT (-(4 + args_to_push + fp_offset)); insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn)); @@ -12467,6 +12489,13 @@ arm_expand_prologue (void) emit_insn (gen_prologue_use (ip_rtx)); } } + else + { + insn = GEN_INT (saved_regs - 4); + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, insn)); + RTX_FRAME_RELATED_P (insn) = 1; + } } offsets = arm_get_frame_offsets (); |