diff options
author | Jiong Wang <jiong.wang@arm.com> | 2014-07-24 14:41:49 +0000 |
---|---|---|
committer | Marcus Shawcroft <mshawcroft@gcc.gnu.org> | 2014-07-24 14:41:49 +0000 |
commit | c5e1f66e59f66083d9bc4229721aaae8d320c8dc (patch) | |
tree | 6e3f6e1bdbb3e244a4ca41941a6210dfaa4fa5ae /gcc/config/aarch64 | |
parent | ae13fce333f73741790fef665546290509220093 (diff) | |
download | gcc-c5e1f66e59f66083d9bc4229721aaae8d320c8dc.zip gcc-c5e1f66e59f66083d9bc4229721aaae8d320c8dc.tar.gz gcc-c5e1f66e59f66083d9bc4229721aaae8d320c8dc.tar.bz2 |
[AArch64] Optimize prologue when there is no frame pointer.
From-SVN: r212999
Diffstat (limited to 'gcc/config/aarch64')
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 163dfcd..76e6027 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1930,6 +1930,22 @@ aarch64_next_callee_save (unsigned regno, unsigned limit) return regno; } +static void +aarch64_pushwb_single_reg (enum machine_mode mode, unsigned regno, + HOST_WIDE_INT adjustment) + { + rtx base_rtx = stack_pointer_rtx; + rtx insn, reg, mem; + + reg = gen_rtx_REG (mode, regno); + mem = gen_rtx_PRE_MODIFY (Pmode, base_rtx, + plus_constant (Pmode, base_rtx, -adjustment)); + mem = gen_rtx_MEM (mode, mem); + + insn = emit_move_insn (mem, reg); + RTX_FRAME_RELATED_P (insn) = 1; +} + static rtx aarch64_gen_storewb_pair (enum machine_mode mode, rtx base, rtx reg, rtx reg2, HOST_WIDE_INT adjustment) @@ -2279,11 +2295,10 @@ aarch64_expand_prologue (void) { bool skip_wb = false; - /* Save the frame pointer and lr if the frame pointer is needed - first. Make the frame pointer point to the location of the - old frame pointer on the stack. */ if (frame_pointer_needed) { + skip_wb = true; + if (fp_offset) { insn = emit_insn (gen_add2_insn (stack_pointer_rtx, @@ -2291,12 +2306,11 @@ aarch64_expand_prologue (void) RTX_FRAME_RELATED_P (insn) = 1; aarch64_set_frame_expr (gen_rtx_SET (Pmode, stack_pointer_rtx, - gen_rtx_MINUS (Pmode, - stack_pointer_rtx, + gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (offset)))); aarch64_save_callee_saves (DImode, fp_offset, R29_REGNUM, - R30_REGNUM, skip_wb); + R30_REGNUM, false); } else aarch64_pushwb_pair_reg (DImode, R29_REGNUM, R30_REGNUM, offset); @@ -2314,20 +2328,36 @@ aarch64_expand_prologue (void) RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx)); - - aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R28_REGNUM, - skip_wb); } else { - insn = emit_insn (gen_add2_insn (stack_pointer_rtx, - GEN_INT (-offset))); - RTX_FRAME_RELATED_P (insn) = 1; + unsigned reg1 = cfun->machine->frame.wb_candidate1; + unsigned reg2 = cfun->machine->frame.wb_candidate2; - aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R30_REGNUM, - skip_wb); + if (fp_offset + || reg1 == FIRST_PSEUDO_REGISTER + || (reg2 == FIRST_PSEUDO_REGISTER + && offset >= 256)) + { + insn = emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-offset))); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + enum machine_mode mode1 = (reg1 <= R30_REGNUM) ? DImode : DFmode; + + skip_wb = true; + + if (reg2 == FIRST_PSEUDO_REGISTER) + aarch64_pushwb_single_reg (mode1, reg1, offset); + else + aarch64_pushwb_pair_reg (mode1, reg1, reg2, offset); + } } + aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, R30_REGNUM, + skip_wb); aarch64_save_callee_saves (DFmode, fp_offset, V0_REGNUM, V31_REGNUM, skip_wb); } |