From 89e06365dbba5b64cd7c761b5c15876499a1069f Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Thu, 1 Feb 2018 09:22:56 -0700 Subject: [PATCH] re PR target/84128 (i686: Stack spilling in -fstack-clash-protection prologue neglects %esp change) PR target/84128 * config/i386/i386.c (release_scratch_register_on_entry): Add new OFFSET and RELEASE_VIA_POP arguments. Use SP+OFFSET to restore the scratch if RELEASE_VIA_POP is false. (ix86_adjust_stack_and_probe_stack_clash): Un-constify SIZE. If we have to save a temporary register, decrement SIZE appropriately. Pass new arguments to release_scratch_register_on_entry. (ix86_adjust_stack_and_probe): Likewise. (ix86_emit_probe_stack_range): Pass new arguments to release_scratch_register_on_entry. PR target/84128 * gcc.target/i386/pr84128.c: New test. From-SVN: r257303 --- gcc/ChangeLog | 27 ++++++++--- gcc/config/i386/i386.c | 62 +++++++++++++++++++------ gcc/testsuite/ChangeLog | 13 ++++-- gcc/testsuite/gcc.target/i386/pr84128.c | 30 ++++++++++++ 4 files changed, 106 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr84128.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f44038f514..25a1beefe70 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2018-02-01 Jeff Law + + PR target/84128 + * config/i386/i386.c (release_scratch_register_on_entry): Add new + OFFSET and RELEASE_VIA_POP arguments. Use SP+OFFSET to restore + the scratch if RELEASE_VIA_POP is false. + (ix86_adjust_stack_and_probe_stack_clash): Un-constify SIZE. + If we have to save a temporary register, decrement SIZE appropriately. + Pass new arguments to release_scratch_register_on_entry. + (ix86_adjust_stack_and_probe): Likewise. + (ix86_emit_probe_stack_range): Pass new arguments to + release_scratch_register_on_entry. + 2018-02-01 Uros Bizjak PR rtl-optimization/84157 @@ -180,7 +193,7 @@ * common.opt (falign-functions=, falign-jumps=, falign-labels=, falign-loops=): Add Optimization flag. -2017-01-30 Jeff Law +2018-01-30 Jeff Law PR target/84064 * i386.c (ix86_adjust_stack_and_probe_stack_clash): New argument @@ -568,7 +581,7 @@ * config/m68k/m68k.c (m68k_promote_function_mode): New function. (TARGET_PROMOTE_FUNCTION_MODE): New macro. -2017-01-24 Jeff Law +2018-01-24 Jeff Law PR target/83994 * i386.c (get_probe_interval): Move to earlier point. @@ -3173,7 +3186,7 @@ * doc/sourcebuild.texi (arm_fp16fml_neon_ok, arm_fp16fml_neon): Document new effective target and option set. -2017-01-11 Kyrylo Tkachov +2018-01-11 Kyrylo Tkachov * config/arm/arm-cpus.in (armv8_4): New feature. (ARMv8_4a): New fgroup. @@ -3932,7 +3945,7 @@ of first and second elements in UNSPEC_VPERMR vector. (altivec_expand_vec_perm_le): Likewise. -2017-01-08 Jeff Law +2018-01-08 Jeff Law PR rtl-optimizatin/81308 * tree-switch-conversion.c (cfg_altered): New file scoped static. @@ -4200,7 +4213,7 @@ range_int_cst_p rather than !symbolic_range_p before calling extract_range_from_multiplicative_op_1. -2017-01-04 Jeff Law +2018-01-04 Jeff Law * tree-ssa-math-opts.c (execute_cse_reciprocals_1): Remove redundant test in assertion. @@ -4815,7 +4828,7 @@ * expmed.c (make_tree): Build VECTOR_CSTs directly from the CONST_VECTOR encoding. -2017-01-03 Jakub Jelinek +2018-01-03 Jakub Jelinek Jeff Law PR target/83641 @@ -4873,7 +4886,7 @@ (sprintf_dom_walker::compute_format_length): Same. (try_substitute_return_value): Same. -2017-01-03 Jeff Law +2018-01-03 Jeff Law PR middle-end/83654 * explow.c (anti_adjust_stack_and_probe_stack_clash): Test a diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index deb7e8ff617..9943be145ae 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12567,22 +12567,39 @@ get_scratch_register_on_entry (struct scratch_reg *sr) } } -/* Release a scratch register obtained from the preceding function. */ +/* Release a scratch register obtained from the preceding function. + + If RELEASE_VIA_POP is true, we just pop the register off the stack + to release it. This is what non-Linux systems use with -fstack-check. + + Otherwise we use OFFSET to locate the saved register and the + allocated stack space becomes part of the local frame and is + deallocated by the epilogue. */ static void -release_scratch_register_on_entry (struct scratch_reg *sr) +release_scratch_register_on_entry (struct scratch_reg *sr, HOST_WIDE_INT offset, + bool release_via_pop) { if (sr->saved) { - struct machine_function *m = cfun->machine; - rtx x, insn = emit_insn (gen_pop (sr->reg)); + if (release_via_pop) + { + struct machine_function *m = cfun->machine; + rtx x, insn = emit_insn (gen_pop (sr->reg)); - /* The RTX_FRAME_RELATED_P mechanism doesn't know about pop. */ - RTX_FRAME_RELATED_P (insn) = 1; - x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD)); - x = gen_rtx_SET (stack_pointer_rtx, x); - add_reg_note (insn, REG_FRAME_RELATED_EXPR, x); - m->fs.sp_offset -= UNITS_PER_WORD; + /* The RX FRAME_RELATED_P mechanism doesn't know about pop. */ + RTX_FRAME_RELATED_P (insn) = 1; + x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD)); + x = gen_rtx_SET (stack_pointer_rtx, x); + add_reg_note (insn, REG_FRAME_RELATED_EXPR, x); + m->fs.sp_offset -= UNITS_PER_WORD; + } + else + { + rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + x = gen_rtx_SET (sr->reg, gen_rtx_MEM (word_mode, x)); + emit_insn (x); + } } } @@ -12597,7 +12614,7 @@ release_scratch_register_on_entry (struct scratch_reg *sr) pushed on the stack. */ static void -ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, +ix86_adjust_stack_and_probe_stack_clash (HOST_WIDE_INT size, const bool int_registers_saved) { struct machine_function *m = cfun->machine; @@ -12713,6 +12730,12 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, struct scratch_reg sr; get_scratch_register_on_entry (&sr); + /* If we needed to save a register, then account for any space + that was pushed (we are not going to pop the register when + we do the restore). */ + if (sr.saved) + size -= UNITS_PER_WORD; + /* Step 1: round SIZE down to a multiple of the interval. */ HOST_WIDE_INT rounded_size = size & -probe_interval; @@ -12761,7 +12784,9 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, m->fs.cfa_reg == stack_pointer_rtx); dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size); - release_scratch_register_on_entry (&sr); + /* This does not deallocate the space reserved for the scratch + register. That will be deallocated in the epilogue. */ + release_scratch_register_on_entry (&sr, size, false); } /* Make sure nothing is scheduled before we are done. */ @@ -12774,7 +12799,7 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, pushed on the stack. */ static void -ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, +ix86_adjust_stack_and_probe (HOST_WIDE_INT size, const bool int_registers_saved) { /* We skip the probe for the first interval + a small dope of 4 words and @@ -12847,6 +12872,11 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, get_scratch_register_on_entry (&sr); + /* If we needed to save a register, then account for any space + that was pushed (we are not going to pop the register when + we do the restore). */ + if (sr.saved) + size -= UNITS_PER_WORD; /* Step 1: round SIZE to the previous multiple of the interval. */ @@ -12906,7 +12936,9 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, (get_probe_interval () + dope)))); - release_scratch_register_on_entry (&sr); + /* This does not deallocate the space reserved for the scratch + register. That will be deallocated in the epilogue. */ + release_scratch_register_on_entry (&sr, size, false); } /* Even if the stack pointer isn't the CFA register, we need to correctly @@ -13055,7 +13087,7 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size, sr.reg), rounded_size - size)); - release_scratch_register_on_entry (&sr); + release_scratch_register_on_entry (&sr, size, true); } /* Make sure nothing is scheduled before we are done. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index da557b80629..8ce7c29050c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-01-30 Jeff Law + + PR target/84128 + * gcc.target/i386/pr84128.c: New test. + 2018-02-01 Georg-Johann Lay * gcc.dg/tree-ssa/vrp111.c (dg-options): Add @@ -218,7 +223,7 @@ PR target/84064 * gcc.target/i386/pr84064: New test. -2017-01-30 Thomas Koenig +2018-01-30 Thomas Koenig PR fortran/84134 * gfortran.dg/data_implied_do_2.f90: New test. @@ -316,7 +321,7 @@ PR tree-optimization/84057 * gcc.dg/graphite/pr84057.c: New testcase. -2017-01-29 Thomas Koenig +2018-01-29 Thomas Koenig PR fortran/84073 * gfortran.dg/bind_c_usage_31.f90: New test. @@ -2489,7 +2494,7 @@ check_effective_target_arm_fp16fml_neon_ok, add_options_for_arm_fp16fml_neon): New procedures. -2017-01-11 Kyrylo Tkachov +2018-01-11 Kyrylo Tkachov * gcc.target/arm/multilib.exp: Add some -march=armv8.4-a combination tests. @@ -2747,7 +2752,7 @@ PR c++/83734 * g++.dg/cpp0x/pr83734.C: New test. -2017-01-09 Carl Love +2018-01-09 Carl Love * gcc.target/powerpc/builtins-1.c (main): Add tests for vec_mergee and vec_mergeo builtins with float, double, long long, unsigned long long, diff --git a/gcc/testsuite/gcc.target/i386/pr84128.c b/gcc/testsuite/gcc.target/i386/pr84128.c new file mode 100644 index 00000000000..a8323fd6dde --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr84128.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -march=i686 -mtune=generic -fstack-clash-protection" } */ +/* { dg-require-effective-target ia32 } */ + +__attribute__ ((noinline, noclone, weak, regparm (3))) +int +f1 (long arg0, int (*pf) (long, void *)) +{ + unsigned char buf[32768]; + return pf (arg0, buf); +} + +__attribute__ ((noinline, noclone, weak)) +int +f2 (long arg0, void *ignored) +{ + if (arg0 != 17) + __builtin_abort (); + return 19; +} + +int +main (void) +{ + if (f1 (17, f2) != 19) + __builtin_abort (); + return 0; +} + + -- 2.30.2