aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2011-10-02 17:46:11 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-10-02 17:46:11 +0000
commitd9b59f5634a62064c652b54dc1a9dc8710261a93 (patch)
treef4f721790d5f713ce0d49c08edba1191d96636be /gcc
parent31045a25f33215ed30bfc4f7166c461a2cc92094 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/config/mips/mips.c94
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/stack-1.c11
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;
+}