diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2011-10-02 17:46:11 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2011-10-02 17:46:11 +0000 |
commit | d9b59f5634a62064c652b54dc1a9dc8710261a93 (patch) | |
tree | f4f721790d5f713ce0d49c08edba1191d96636be /gcc | |
parent | 31045a25f33215ed30bfc4f7166c461a2cc92094 (diff) | |
download | gcc-d9b59f5634a62064c652b54dc1a9dc8710261a93.zip gcc-d9b59f5634a62064c652b54dc1a9dc8710261a93.tar.gz gcc-d9b59f5634a62064c652b54dc1a9dc8710261a93.tar.bz2 |
mips.c (mips_frame_barrier): New function.
gcc/
* config/mips/mips.c (mips_frame_barrier): New function.
(mips_expand_prologue): Call it after allocating stack space.
(mips_deallocate_stack): New function.
(mips_expand_epilogue): Call mips_frame_barrier and
mips_deallocate_stack.
gcc/testsuite/
* gcc.target/mips/stack-1.c: New test.
From-SVN: r179432
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 94 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/stack-1.c | 11 |
4 files changed, 76 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b8197fa..5a30b57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2011-10-02 Richard Sandiford <rdsandiford@googlemail.com> + * config/mips/mips.c (mips_frame_barrier): New function. + (mips_expand_prologue): Call it after allocating stack space. + (mips_deallocate_stack): New function. + (mips_expand_epilogue): Call mips_frame_barrier and + mips_deallocate_stack. + +2011-10-02 Richard Sandiford <rdsandiford@googlemail.com> + PR target/49696 * config/mips/sync.md (sync_<optab>_12): Allow zero operands. (sync_old_<optab>_12, sync_new_<optab>_12, sync_nand_12): Likewise. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index d0b6b4c..ff72e28 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -9892,6 +9892,14 @@ mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, mips_end_function_definition (fnname); } +/* Emit an optimisation barrier for accesses to the current frame. */ + +static void +mips_frame_barrier (void) +{ + emit_clobber (gen_frame_mem (BLKmode, stack_pointer_rtx)); +} + /* Save register REG to MEM. Make the instruction frame-related. */ static void @@ -10035,6 +10043,7 @@ mips_expand_prologue (void) insn = mips16e_build_save_restore (false, &mask, &offset, nargs, step1); RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + mips_frame_barrier (); size -= step1; /* Check if we need to save other registers. */ @@ -10075,6 +10084,7 @@ mips_expand_prologue (void) insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-step1)); RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + mips_frame_barrier (); size -= step1; /* Start at the uppermost location for saving. */ @@ -10135,6 +10145,7 @@ mips_expand_prologue (void) stack_pointer_rtx, GEN_INT (-step1)); RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + mips_frame_barrier (); size -= step1; } mips_for_each_saved_acc (size, mips_save_reg); @@ -10175,6 +10186,7 @@ mips_expand_prologue (void) (gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, -size))); } + mips_frame_barrier (); } /* Set up the frame pointer, if we're using one. */ @@ -10315,6 +10327,35 @@ mips_restore_reg (rtx reg, rtx mem) mips_epilogue.cfa_restore_sp_offset); } +/* Emit code to set the stack pointer to BASE + OFFSET, given that + BASE + OFFSET is NEW_FRAME_SIZE bytes below the top of the frame. + BASE, if not the stack pointer, is available as a temporary. */ + +static void +mips_deallocate_stack (rtx base, rtx offset, HOST_WIDE_INT new_frame_size) +{ + if (base == stack_pointer_rtx && offset == const0_rtx) + return; + + mips_frame_barrier (); + if (offset == const0_rtx) + { + emit_move_insn (stack_pointer_rtx, base); + mips_epilogue_set_cfa (stack_pointer_rtx, new_frame_size); + } + else if (TARGET_MIPS16 && base != stack_pointer_rtx) + { + emit_insn (gen_add3_insn (base, base, offset)); + mips_epilogue_set_cfa (base, new_frame_size); + emit_move_insn (stack_pointer_rtx, base); + } + else + { + emit_insn (gen_add3_insn (stack_pointer_rtx, base, offset)); + mips_epilogue_set_cfa (stack_pointer_rtx, new_frame_size); + } +} + /* Emit any instructions needed before a return. */ void @@ -10341,7 +10382,7 @@ mips_expand_epilogue (bool sibcall_p) { const struct mips_frame_info *frame; HOST_WIDE_INT step1, step2; - rtx base, target, insn; + rtx base, adjust, insn; if (!sibcall_p && mips_can_use_return_insn ()) { @@ -10384,31 +10425,14 @@ mips_expand_epilogue (bool sibcall_p) step1 -= step2; } - /* Set TARGET to BASE + STEP1. */ - target = base; - if (step1 > 0) + /* Get an rtx for STEP1 that we can add to BASE. */ + adjust = GEN_INT (step1); + if (!SMALL_OPERAND (step1)) { - rtx adjust; - - /* Get an rtx for STEP1 that we can add to BASE. */ - adjust = GEN_INT (step1); - if (!SMALL_OPERAND (step1)) - { - mips_emit_move (MIPS_EPILOGUE_TEMP (Pmode), adjust); - adjust = MIPS_EPILOGUE_TEMP (Pmode); - } - - /* Normal mode code can copy the result straight into $sp. */ - if (!TARGET_MIPS16) - target = stack_pointer_rtx; - - emit_insn (gen_add3_insn (target, base, adjust)); - mips_epilogue_set_cfa (target, step2); + mips_emit_move (MIPS_EPILOGUE_TEMP (Pmode), adjust); + adjust = MIPS_EPILOGUE_TEMP (Pmode); } - - /* Copy TARGET into the stack pointer. */ - if (target != stack_pointer_rtx) - mips_emit_move (stack_pointer_rtx, target); + mips_deallocate_stack (base, adjust, step2); /* If we're using addressing macros, $gp is implicitly used by all SYMBOL_REFs. We must emit a blockage insn before restoring $gp @@ -10437,6 +10461,7 @@ mips_expand_epilogue (bool sibcall_p) /* Restore the remaining registers and deallocate the final bit of the frame. */ + mips_frame_barrier (); emit_insn (restore); mips_epilogue_set_cfa (stack_pointer_rtx, 0); } @@ -10473,13 +10498,8 @@ mips_expand_epilogue (bool sibcall_p) offset -= UNITS_PER_WORD; /* If we don't use shoadow register set, we need to update SP. */ - if (!cfun->machine->use_shadow_register_set_p && step2 > 0) - { - emit_insn (gen_add3_insn (stack_pointer_rtx, - stack_pointer_rtx, - GEN_INT (step2))); - mips_epilogue_set_cfa (stack_pointer_rtx, 0); - } + if (!cfun->machine->use_shadow_register_set_p) + mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0); else /* The choice of position is somewhat arbitrary in this case. */ mips_epilogue_emit_cfa_restores (); @@ -10489,16 +10509,8 @@ mips_expand_epilogue (bool sibcall_p) gen_rtx_REG (SImode, K0_REG_NUM))); } else - { - /* Deallocate the final bit of the frame. */ - if (step2 > 0) - { - emit_insn (gen_add3_insn (stack_pointer_rtx, - stack_pointer_rtx, - GEN_INT (step2))); - mips_epilogue_set_cfa (stack_pointer_rtx, 0); - } - } + /* Deallocate the final bit of the frame. */ + mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0); } gcc_assert (!mips_epilogue.cfa_restores); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56a9cc1..f6829f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2011-10-02 Richard Sandiford <rdsandiford@googlemail.com> + * gcc.target/mips/stack-1.c: New test. + +2011-10-02 Richard Sandiford <rdsandiford@googlemail.com> + * gcc.dg/pr49696.c: New test. 2011-10-02 Jan Hubicka <jh@suse.cz> diff --git a/gcc/testsuite/gcc.target/mips/stack-1.c b/gcc/testsuite/gcc.target/mips/stack-1.c new file mode 100644 index 0000000..3d49545 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/stack-1.c @@ -0,0 +1,11 @@ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "addiu\t(\\\$sp,)?\\\$sp,\[1-9\]" } } */ +/* { dg-final { scan-assembler "\tlw\t" } } */ +/* { dg-final { scan-assembler-not "addiu\t(\\\$sp,)?\\\$sp,\[1-9\].*\tlw\t" } } */ + +int foo (int y) +{ + volatile int a = y; + volatile int *volatile b = &a; + return *b; +} |