From ce7decc9722fecccbcdd7d481424ff9f4ba4b81b Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Fri, 9 Mar 2018 09:06:52 +0000 Subject: [PATCH] PR target/84763 * config/i386/winnt.c (i386_pe_seh_cold_init): Use small pre-allocation when the function accesses prior frames. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@258381 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 ++++++ gcc/config/i386/winnt.c | 24 ++++++++++++++++++++---- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.c-torture/compile/20180309-1.c | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/20180309-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5675cdb7c3b..69b7def90bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-03-09 Eric Botcazou + + PR target/84763 + * config/i386/winnt.c (i386_pe_seh_cold_init): Use small pre-allocation + when the function accesses prior frames. + 2018-03-08 Jakub Jelinek PR debug/84456 diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 9b406f49094..d5c256b23ce 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -879,7 +879,7 @@ void i386_pe_seh_cold_init (FILE *f, const char *name) { struct seh_frame_state *seh; - HOST_WIDE_INT offset; + HOST_WIDE_INT alloc_offset, offset; if (!TARGET_SEH) return; @@ -891,7 +891,16 @@ i386_pe_seh_cold_init (FILE *f, const char *name) assemble_name (f, name); fputc ('\n', f); - offset = seh->sp_offset - INCOMING_FRAME_SP_OFFSET; + /* In the normal case, the frame pointer is near the bottom of the frame + so we can do the full stack allocation and set it afterwards. There + is an exception when the function accesses prior frames so, in this + case, we need to pre-allocate a small chunk before setting it. */ + if (crtl->accesses_prior_frames) + alloc_offset = seh->cfa_offset; + else + alloc_offset = seh->sp_offset; + + offset = alloc_offset - INCOMING_FRAME_SP_OFFSET; if (offset > 0 && offset < SEH_MAX_FRAME_SIZE) fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset); @@ -903,12 +912,12 @@ i386_pe_seh_cold_init (FILE *f, const char *name) : (gcc_unreachable (), "")), f); print_reg (gen_rtx_REG (DImode, regno), 0, f); fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", - seh->sp_offset - seh->reg_offset[regno]); + alloc_offset - seh->reg_offset[regno]); } if (seh->cfa_reg != stack_pointer_rtx) { - offset = seh->sp_offset - seh->cfa_offset; + offset = alloc_offset - seh->cfa_offset; gcc_assert ((offset & 15) == 0); gcc_assert (IN_RANGE (offset, 0, 240)); @@ -918,6 +927,13 @@ i386_pe_seh_cold_init (FILE *f, const char *name) fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset); } + if (crtl->accesses_prior_frames) + { + offset = seh->sp_offset - alloc_offset; + if (offset > 0 && offset < SEH_MAX_FRAME_SIZE) + fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset); + } + fputs ("\t.seh_endprologue\n", f); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1917aef3cf1..80d60c880f8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-03-09 Eric Botcazou + + * gcc.c-torture/compile/20180309-1.c: New test. + 2018-03-08 Jakub Jelinek PR c++/80598 diff --git a/gcc/testsuite/gcc.c-torture/compile/20180309-1.c b/gcc/testsuite/gcc.c-torture/compile/20180309-1.c new file mode 100644 index 00000000000..078446696e9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20180309-1.c @@ -0,0 +1,22 @@ +/* PR target/84763 */ +/* { dg-require-effective-target return_address } */ + +extern void abort (void); + +void *foo (unsigned int *data, unsigned int len) +{ + unsigned int local_data[128]; + + if (len > 128) + abort (); + + for (unsigned int i = 0; i < len; i++) + local_data[i] = data[i] + data[len - 1 - i] * 2; + + void *ret = __builtin_frame_address (0); + + for (unsigned int i = 0; i < len; i++) + ret = ret + local_data[i] % 8; + + return ret; +} -- 2.11.4.GIT