On Wed, Aug 9, 2017 at 10:28 AM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Wed, Aug 9, 2017 at 8:26 AM, Andi Kleen <a...@firstfloor.org> wrote: >>> This must be much more specific. How does it impact: >>> >>> 1. LTO >>> 2. Function inlining. >>> 3. Partial function inlining. >>> 4. Shrink-wrapping. >>> >>> Any of them can impact function stack frame. >> >> It doesn't. It's just to get back to the previous state. >> >> Also these others already have explicit options to disable them. >> > > How about > > item -fkeep-frame-pointer > @opindex fkeep-frame-pointer > Keep the frame pointer in a register for functions. This option always > forces a new stack frame for all functions regardless of whether > @option{-fomit-frame-pointer} is enabled or not. Disabled by default. >
Here is the updated patch with -fkeep-frame-pointer. OK for trunk? -- H.J.
From 6f5b42bbe2baa7977dcbf388219dabcb4a6b546d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Sun, 6 Aug 2017 06:24:36 -0700 Subject: [PATCH] i386: Don't use frame pointer without stack access When there is no stack access, there is no need to use frame pointer even if -fno-omit-frame-pointer is used and caller's frame pointer is unchanged. A command-line option, -fkeep-frame-pointer, is added to always force a new stack frame. gcc/ PR target/81736 * common.opt (-fomit-frame-pointer): Override -fkeep-frame-pointer. (-fkeep-frame-pointer): New command-line option. * config/i386/i386.c (ix86_finalize_stack_realign_flags): Renamed to ... (ix86_finalize_stack_frame_flags): This. Also clear frame_pointer_needed if -fkeep-frame-pointer isn't used and ,-fno-omit-frame-pointer is used without stack access. (ix86_expand_prologue): Replace ix86_finalize_stack_realign_flags with ix86_finalize_stack_frame_flags. (ix86_expand_epilogue): Likewise. (ix86_expand_split_stack_prologue): Likewise. * doc/invoke.texi: Document -fkeep-frame-pointer. Update -fomit-frame-pointer. Add a note for -fno-omit-frame-pointer. * toplev.c (process_options): Disable -fomit-frame-pointer if -fkeep-frame-pointer is used. gcc/testsuite/ PR target/81736 * gcc.target/i386/pr81736-1a.c: New test. * gcc.target/i386/pr81736-1b.c: Likewise. * gcc.target/i386/pr81736-1c.c: Likewise. * gcc.target/i386/pr81736-1d.c: Likewise. * gcc.target/i386/pr81736-1e.c: Likewise. * gcc.target/i386/pr81736-1f.c: Likewise. * gcc.target/i386/pr81736-1g.c: Likewise. * gcc.target/i386/pr81736-2.c: Likewise. * gcc.target/i386/pr81736-3.c: Likewise. * gcc.target/i386/pr81736-4.c: Likewise. * gcc.target/i386/pr81736-5.c: Likewise. * gcc.target/i386/pr81736-6.c: Likewise. * gcc.target/i386/pr81736-7.c: Likewise. --- gcc/common.opt | 6 +++++- gcc/config/i386/i386.c | 24 +++++++++++++----------- gcc/doc/invoke.texi | 13 ++++++++++++- gcc/testsuite/gcc.target/i386/pr81736-1a.c | 13 +++++++++++++ gcc/testsuite/gcc.target/i386/pr81736-1b.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-1c.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-1d.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-1e.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-1f.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-1g.c | 7 +++++++ gcc/testsuite/gcc.target/i386/pr81736-2.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/pr81736-3.c | 11 +++++++++++ gcc/testsuite/gcc.target/i386/pr81736-4.c | 11 +++++++++++ gcc/testsuite/gcc.target/i386/pr81736-5.c | 20 ++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr81736-6.c | 16 ++++++++++++++++ gcc/testsuite/gcc.target/i386/pr81736-7.c | 13 +++++++++++++ gcc/toplev.c | 4 ++++ 17 files changed, 174 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1d.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1e.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1f.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-1g.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-5.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-6.c create mode 100644 gcc/testsuite/gcc.target/i386/pr81736-7.c diff --git a/gcc/common.opt b/gcc/common.opt index 1cb1c83d306..b73564d7145 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1881,9 +1881,13 @@ EnumValue Enum(offload_abi) String(lp64) Value(OFFLOAD_ABI_LP64) fomit-frame-pointer -Common Report Var(flag_omit_frame_pointer) Optimization +Common Report Var(flag_omit_frame_pointer) Negative(fkeep-frame-pointer) Optimization When possible do not generate stack frames. +fkeep-frame-pointer +Common Report Var(flag_keep_frame_pointer) Negative(fomit-frame-pointer) +Always force a new stack frame + fopt-info Common Report Var(flag_opt_info) Optimization Enable all optimization info dumps on stderr. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3f8519777f7..9c37e960dc8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -14179,10 +14179,11 @@ output_probe_stack_range (rtx reg, rtx end) return ""; } -/* Finalize stack_realign_needed flag, which will guide prologue/epilogue - to be generated in correct form. */ +/* Finalize stack_realign_needed and frame_pointer_needed flags, which + will guide prologue/epilogue to be generated in correct form. */ + static void -ix86_finalize_stack_realign_flags (void) +ix86_finalize_stack_frame_flags (void) { /* Check if stack realign is really needed after reload, and stores result in cfun */ @@ -14205,13 +14206,14 @@ ix86_finalize_stack_realign_flags (void) } /* If the only reason for frame_pointer_needed is that we conservatively - assumed stack realignment might be needed, but in the end nothing that - needed the stack alignment had been spilled, clear frame_pointer_needed - and say we don't need stack realignment. */ - if (stack_realign + assumed stack realignment might be needed or -fno-omit-frame-pointer + is used, but in the end nothing that needed the stack alignment had + been spilled nor stack access, clear frame_pointer_needed and say we + don't need stack realignment. */ + if ((stack_realign || !flag_omit_frame_pointer) + && !flag_keep_frame_pointer && frame_pointer_needed && crtl->is_leaf - && flag_omit_frame_pointer && crtl->sp_is_unchanging && !ix86_current_function_calls_tls_descriptor && !crtl->accesses_prior_frames @@ -14402,7 +14404,7 @@ ix86_expand_prologue (void) if (ix86_function_naked (current_function_decl)) return; - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); /* DRAP should not coexist with stack_realign_fp */ gcc_assert (!(crtl->drap_reg && stack_realign_fp)); @@ -15266,7 +15268,7 @@ ix86_expand_epilogue (int style) return; } - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); frame = m->frame; m->fs.sp_realigned = stack_realign_fp; @@ -15801,7 +15803,7 @@ ix86_expand_split_stack_prologue (void) gcc_assert (flag_split_stack && reload_completed); - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); frame = cfun->machine->frame; allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index cc0f5a00a4f..7a3b3d53f17 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -397,7 +397,7 @@ Objective-C and Objective-C++ Dialects}. -fno-peephole2 -fno-printf-return-value -fno-sched-interblock @gol -fno-sched-spec -fno-signed-zeros @gol -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol --fomit-frame-pointer -foptimize-sibling-calls @gol +-fomit-frame-pointer -fkeep-frame-pointer -foptimize-sibling-calls @gol -fpartial-inlining -fpeel-loops -fpredictive-commoning @gol -fprefetch-loop-arrays @gol -fprofile-correction @gol @@ -7365,9 +7365,20 @@ The default setting (when not optimizing for size) for 32-bit GNU/Linux x86 and 32-bit Darwin x86 targets is @option{-fomit-frame-pointer}. You can configure GCC with the @option{--enable-frame-pointer} configure option to change the default. +This option overrides @option{-fkeep-frame-pointer}. + +Note that @option{-fno-omit-frame-pointer} doesn't force a new stack +frame for all functions if it isn't otherwise needed, and hence doesn't +guarantee a new frame pointer for all functions. Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. +@item -fkeep-frame-pointer +@opindex fkeep-frame-pointer +Keep the frame pointer in a register for functions. This option always +forces a new stack frame for all functions. This option overrides +@option{-fomit-frame-pointer}. Disabled by default. + @item -foptimize-sibling-calls @opindex foptimize-sibling-calls Optimize sibling and tail recursive calls. diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1a.c b/gcc/testsuite/gcc.target/i386/pr81736-1a.c new file mode 100644 index 00000000000..92c7bc97a0d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1a.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +extern int i; + +int +foo (void) +{ + return i; +} + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1b.c b/gcc/testsuite/gcc.target/i386/pr81736-1b.c new file mode 100644 index 00000000000..692ca9b7a30 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1b.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fkeep-frame-pointer -fno-omit-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1c.c b/gcc/testsuite/gcc.target/i386/pr81736-1c.c new file mode 100644 index 00000000000..36ee6bc63f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1c.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -fno-omit-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1d.c b/gcc/testsuite/gcc.target/i386/pr81736-1d.c new file mode 100644 index 00000000000..143985852f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1d.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fkeep-frame-pointer -fomit-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1e.c b/gcc/testsuite/gcc.target/i386/pr81736-1e.c new file mode 100644 index 00000000000..fe98e96074c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1e.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -fkeep-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* Need to use a frame pointer. */ +/* { dg-final { scan-assembler "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1f.c b/gcc/testsuite/gcc.target/i386/pr81736-1f.c new file mode 100644 index 00000000000..682cb3b4030 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1f.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fkeep-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* Need to use a frame pointer. */ +/* { dg-final { scan-assembler "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-1g.c b/gcc/testsuite/gcc.target/i386/pr81736-1g.c new file mode 100644 index 00000000000..b6d19985c8c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-1g.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer -fkeep-frame-pointer" } */ + +#include "pr81736-1a.c" + +/* Need to use a frame pointer. */ +/* { dg-final { scan-assembler "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-2.c b/gcc/testsuite/gcc.target/i386/pr81736-2.c new file mode 100644 index 00000000000..a3720879937 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +int +#ifndef __x86_64__ +__attribute__((regparm(3))) +#endif +foo (int i) +{ + return i; +} + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-3.c b/gcc/testsuite/gcc.target/i386/pr81736-3.c new file mode 100644 index 00000000000..c3bde7dd933 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +void +foo (void) +{ + asm ("# " : : : "ebx"); +} + +/* Need to use a frame pointer. */ +/* { dg-final { scan-assembler "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-4.c b/gcc/testsuite/gcc.target/i386/pr81736-4.c new file mode 100644 index 00000000000..25f50016a64 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +int +foo (int i1, int i2, int i3, int i4, int i5, int i6, int i7) +{ + return i7; +} + +/* Need to use a frame pointer. */ +/* { dg-final { scan-assembler "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-5.c b/gcc/testsuite/gcc.target/i386/pr81736-5.c new file mode 100644 index 00000000000..e1602cf25ba --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-5.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer -mavx" } */ + +typedef int v8si __attribute__ ((vector_size (32))); + +void +#ifndef __x86_64__ +__attribute__((regparm(3))) +#endif +foo (v8si *out_start, v8si *out_end, v8si *regions) +{ + v8si base = regions[3]; + *out_start = base; + *out_end = base; +} + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ +/* Verify no dynamic realignment is performed. */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*sp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-6.c b/gcc/testsuite/gcc.target/i386/pr81736-6.c new file mode 100644 index 00000000000..6198574c8cc --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-6.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +struct foo +{ + int head; +} a; + +int +bar (void) +{ + return a.head != 0; +} + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr81736-7.c b/gcc/testsuite/gcc.target/i386/pr81736-7.c new file mode 100644 index 00000000000..f947886e642 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr81736-7.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ + +extern int foo (void); + +int +bar (void) +{ + return foo (); +} + +/* No need to use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/toplev.c b/gcc/toplev.c index d23714c4773..55069784bdd 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1297,6 +1297,10 @@ process_options (void) "-floop-parallelize-all)"); #endif + /* Don't omit frame pointer if -fkeep-frame-pointer is used. */ + if (flag_keep_frame_pointer) + flag_omit_frame_pointer = 0; + if (flag_check_pointer_bounds) { if (targetm.chkp_bound_mode () == VOIDmode) -- 2.13.4