diff options
author | Jiong Wang <jiong.wang@arm.com> | 2014-07-23 16:22:17 +0000 |
---|---|---|
committer | Marcus Shawcroft <mshawcroft@gcc.gnu.org> | 2014-07-23 16:22:17 +0000 |
commit | 8ed2fc62d4a8bf8dfd2ec080bdfd4b8119d490eb (patch) | |
tree | 5f7f11561d7ffb962cfca05cc962dedad94445da /gcc/config/aarch64 | |
parent | 0ec74a1ee358ee14658ea251d5d885863764c4a9 (diff) | |
download | gcc-8ed2fc62d4a8bf8dfd2ec080bdfd4b8119d490eb.zip gcc-8ed2fc62d4a8bf8dfd2ec080bdfd4b8119d490eb.tar.gz gcc-8ed2fc62d4a8bf8dfd2ec080bdfd4b8119d490eb.tar.bz2 |
[AArch64] Split save restore path.
From-SVN: r212956
Diffstat (limited to 'gcc/config/aarch64')
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 104 |
1 files changed, 69 insertions, 35 deletions
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index e3a0c57..7e267dd 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1951,13 +1951,9 @@ aarch64_gen_load_pair (enum machine_mode mode, rtx reg1, rtx mem1, rtx reg2, } -/* offset from the stack pointer of where the saves and - restore's have to happen. */ static void -aarch64_save_or_restore_callee_saves (enum machine_mode mode, - HOST_WIDE_INT start_offset, - unsigned start, unsigned limit, - bool restore) +aarch64_save_callee_saves (enum machine_mode mode, HOST_WIDE_INT start_offset, + unsigned start, unsigned limit) { rtx insn; rtx (*gen_mem_ref) (enum machine_mode, rtx) = (frame_pointer_needed @@ -1988,18 +1984,10 @@ aarch64_save_or_restore_callee_saves (enum machine_mode mode, rtx mem2; offset = start_offset + cfun->machine->frame.reg_offset[regno2]; - mem2 = gen_mem_ref (mode, - plus_constant (Pmode, stack_pointer_rtx, offset)); - if (restore == false) - insn = emit_insn (aarch64_gen_store_pair (mode, mem, reg, mem2, - reg2)); - else - { - insn = emit_insn (aarch64_gen_load_pair (mode, reg, mem, reg2, - mem2)); - add_reg_note (insn, REG_CFA_RESTORE, reg); - add_reg_note (insn, REG_CFA_RESTORE, reg2); - } + mem2 = gen_mem_ref (mode, plus_constant (Pmode, stack_pointer_rtx, + offset)); + insn = emit_insn (aarch64_gen_store_pair (mode, mem, reg, mem2, + reg2)); /* The first part of a frame-related parallel insn is always assumed to be relevant to the frame @@ -2009,15 +1997,64 @@ aarch64_save_or_restore_callee_saves (enum machine_mode mode, regno = regno2; } else + insn = emit_move_insn (mem, reg); + + RTX_FRAME_RELATED_P (insn) = 1; + } +} + +static void +aarch64_restore_callee_saves (enum machine_mode mode, + HOST_WIDE_INT start_offset, unsigned start, + unsigned limit) +{ + rtx insn; + rtx base_rtx = stack_pointer_rtx; + rtx (*gen_mem_ref) (enum machine_mode, rtx) = (frame_pointer_needed + ? gen_frame_mem : gen_rtx_MEM); + unsigned regno; + unsigned regno2; + HOST_WIDE_INT offset; + + for (regno = aarch64_next_callee_save (start, limit); + regno <= limit; + regno = aarch64_next_callee_save (regno + 1, limit)) + { + rtx reg = gen_rtx_REG (mode, regno); + rtx mem; + + offset = start_offset + cfun->machine->frame.reg_offset[regno]; + mem = gen_mem_ref (mode, plus_constant (Pmode, base_rtx, offset)); + + regno2 = aarch64_next_callee_save (regno + 1, limit); + + if (regno2 <= limit + && ((cfun->machine->frame.reg_offset[regno] + UNITS_PER_WORD) + == cfun->machine->frame.reg_offset[regno2])) { - if (restore == false) - insn = emit_move_insn (mem, reg); - else - { - insn = emit_move_insn (reg, mem); - add_reg_note (insn, REG_CFA_RESTORE, reg); - } + rtx reg2 = gen_rtx_REG (mode, regno2); + rtx mem2; + + offset = start_offset + cfun->machine->frame.reg_offset[regno2]; + mem2 = gen_mem_ref (mode, plus_constant (Pmode, base_rtx, offset)); + insn = emit_insn (aarch64_gen_load_pair (mode, reg, mem, reg2, + mem2)); + add_reg_note (insn, REG_CFA_RESTORE, reg); + add_reg_note (insn, REG_CFA_RESTORE, reg2); + + /* The first part of a frame-related parallel insn is + always assumed to be relevant to the frame + calculations; subsequent parts, are only + frame-related if explicitly marked. */ + RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1; + regno = regno2; } + else + { + insn = emit_move_insn (reg, mem); + add_reg_note (insn, REG_CFA_RESTORE, reg); + } + RTX_FRAME_RELATED_P (insn) = 1; } } @@ -2212,11 +2249,10 @@ aarch64_expand_prologue (void) RTX_FRAME_RELATED_P (insn) = 1; } - aarch64_save_or_restore_callee_saves (DImode, fp_offset, R0_REGNUM, - frame_pointer_needed - ? R28_REGNUM : R30_REGNUM, false); - aarch64_save_or_restore_callee_saves (DFmode, fp_offset, V0_REGNUM, - V31_REGNUM, false); + aarch64_save_callee_saves (DImode, fp_offset, R0_REGNUM, + frame_pointer_needed + ? R28_REGNUM : R30_REGNUM); + aarch64_save_callee_saves (DFmode, fp_offset, V0_REGNUM, V31_REGNUM); } /* when offset >= 512, @@ -2287,11 +2323,9 @@ aarch64_expand_epilogue (bool for_sibcall) cfa_reg = stack_pointer_rtx; } - aarch64_save_or_restore_callee_saves (DImode, fp_offset, R0_REGNUM, - frame_pointer_needed - ? R28_REGNUM : R30_REGNUM, true); - aarch64_save_or_restore_callee_saves (DFmode, fp_offset, V0_REGNUM, - V31_REGNUM, true); + aarch64_restore_callee_saves (DImode, fp_offset, R0_REGNUM, + frame_pointer_needed ? R28_REGNUM : R30_REGNUM); + aarch64_restore_callee_saves (DFmode, fp_offset, V0_REGNUM, V31_REGNUM); /* Restore the frame pointer and lr if the frame pointer is needed. */ if (offset > 0) |