diff mbox

[MIPS] MIPS specific optimization for o32 ABI

Message ID 1438101523.19674.219.camel@ubuntu-sellcey
State New
Headers show

Commit Message

Steve Ellcey July 28, 2015, 4:38 p.m. UTC
This patch implements a MIPS o32 ABI specific optimization called frame
header optimization.  In the o32 ABI, routines allocate 16 bytes on the
stack before calling another routine.  This space is used by the callee
as space to write the register arguments to if their address is taken.
The n32 and n64 ABI's use the more common approach of copying register
arguments to local variables if their address is needed.

This optimization allows the callee to use that 16 bytes for other
purposes if it does not need it to write its arguments out to memory and
if it only needs 16 bytes of stack space (or less) for saving callee-saved
registers.

This can allow us to avoid having to allocate extra stack space in a routine
and to remove the stack pointer increment/decrement instructions from the 
prolog and epilogue which results in a small performance improvement.

This patch has been in the Mentor GCC toolchain for MIPS for a while and
gotten some testing there and I tested it on the top-of-tree GCC sources
with no regressions.

OK to checkin?

Steve Ellcey
sellcey@imgtec.com


2015-07-28  Steve Ellcey  <sellcey@imgtec.com>
	    Zoran Jovanovic  <zoran.jovanovic@imgtec.com>
	    Catherine Moore  <clm@codesourcery.com>
	    Tom de Vries  <tom@codesourcery.com>

	* config/mips/mips.opt (mframe-header-opt): New option.
	* config/mips/mips.c (struct mips_frame_info): Add
	skip_stack_frame_allocation_p field.
	(struct machine_function): Add callees_use_frame_header_p,
	uses_frame_header_p, and initial_total_size fields.
	(mips_frame_header_usage): New hash.
	(mips_find_if_frame_header_is_used): New Function.
	(mips_callee_use_frame_header): New Function.
	(mips_callees_use_frame_header_p): New Function.
	(mips_cfun_use_frame_header_p): New Function.
	(mips_get_updated_offset): New Function.
	(mips_skip_stack_frame_alloc): New Function.
	(mips_frame_header_update_insn): New Function.
	(mips_rest_of_frame_header_opt): New function.
	(mips_compute_frame_info): Add recalculate and frame arguments.
	(mips_frame_pointer_required): Add new args to
	mips_compute_frame_info call.
	(mips_initial_elimination_offset): Ditto.
	(mips_gp_expand_needed_p): New function factored out of
	mips_expand_ghost_gp_insns.
	(mips_expand_ghost_gp_insns): Use mips_gp_expand_needed_p.
	(mips_reorg): Use mips_rest_of_frame_header_opt.



2015-07-28  Steve Ellcey  <sellcey@imgtec.com>
	    Tom de Vries  <tom@codesourcery.com>

	* gcc.target/mips/fho-1.c: New test.
	* gcc.target/mips/fho-2.c: New test.
	* gcc.target/mips/mips.exp: Add -mframe-header-opt to
	mips_option_groups.

Comments

Joseph Myers July 31, 2015, 12:32 a.m. UTC | #1
New command-line options need documenting in invoke.texi.
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.target/mips/fho-1.c b/gcc/testsuite/gcc.target/mips/fho-1.c
new file mode 100644
index 0000000..e373da4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fho-1.c
@@ -0,0 +1,36 @@ 
+/* { dg-do compile } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-options "-mabi=32 -mframe-header-opt -fdump-rtl-mach" } */
+/* Testing -mframe-header-opt optimization option.  */
+
+NOCOMPRESSION int __attribute__((noinline))
+B (int x)
+{
+  return x + 3;
+}
+
+/* We are sure that B is not using its incoming stack frame so we can skip
+   its allocation.  */
+NOCOMPRESSION int __attribute__((noinline))
+A (int x)
+{
+  return B (x) + 2;
+}
+
+NOCOMPRESSION int
+main (void)
+{
+  int a;
+  void *volatile sp1, *volatile sp2;
+  register void *sp asm ("$sp");
+  sp1 = sp;
+  a = A (5);
+  sp2 = sp;
+  return !(a == 10 && sp1 == sp2);
+}
+
+/* { dg-final { scan-rtl-dump "Frame size reduced by frame header optimization" "mach" } } */
+
+/* For enabled targets, test that only one stack allocation is present, the one
+   in main.  The one in A should have been removed by -mframe-header-opt.  */
+/* { dg-final { scan-assembler-times "addiu\t\\\$sp,\\\$sp,-" 1 } } */
diff --git a/gcc/testsuite/gcc.target/mips/fho-2.c b/gcc/testsuite/gcc.target/mips/fho-2.c
new file mode 100644
index 0000000..d3599b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fho-2.c
@@ -0,0 +1,29 @@ 
+/* { dg-do run } */
+/* { dg-options "-mabi=32 -mframe-header-opt" } */
+/* Testing -mframe-header-opt optimization option.  */
+
+NOCOMPRESSION int __attribute__((noinline))
+B (int x)
+{
+  return x + 3;
+}
+
+/* We are sure that B is not using its incoming stack frame so we can skip
+   its allocation.  */
+NOCOMPRESSION int __attribute__((noinline))
+A (int x)
+{
+  return B (x) + 2;
+}
+
+NOCOMPRESSION int
+main (void)
+{
+  int a;
+  void *volatile sp1, *volatile sp2;
+  register void *sp asm ("$sp");
+  sp1 = sp;
+  a = A (5);
+  sp2 = sp;
+  return !(a == 10 && sp1 == sp2);
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index b3617e4..6e6450e 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -237,6 +237,7 @@  set mips_option_groups {
     fpu "-m(double|single)-float"
     forbid_cpu "forbid_cpu=.*"
     fp "-mfp(32|xx|64)"
+    frame_header_opt "-mframe-header-opt|-mno-frame-header-opt"
     gp "-mgp(32|64)"
     long "-mlong(32|64)"
     micromips "-mmicromips|-mno-micromips"