|
|
85359c |
diff -Nrup a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
|
|
|
85359c |
--- a/gcc/config/i386/i386.c 2018-01-03 16:10:46.278171086 -0700
|
|
|
85359c |
+++ b/gcc/config/i386/i386.c 2018-01-03 16:12:32.022220166 -0700
|
|
|
85359c |
@@ -9862,14 +9862,13 @@ static void
|
|
|
85359c |
ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
|
|
|
85359c |
{
|
|
|
85359c |
struct machine_function *m = cfun->machine;
|
|
|
85359c |
+ struct ix86_frame frame;
|
|
|
85359c |
+ ix86_compute_frame_layout (&frame);
|
|
|
85359c |
|
|
|
85359c |
/* If this function does not statically allocate stack space, then
|
|
|
85359c |
no probes are needed. */
|
|
|
85359c |
if (!size)
|
|
|
85359c |
{
|
|
|
85359c |
- struct ix86_frame frame;
|
|
|
85359c |
- ix86_compute_frame_layout (&frame);
|
|
|
85359c |
-
|
|
|
85359c |
/* However, the allocation of space via pushes for register
|
|
|
85359c |
saves could be viewed as allocating space, but without the
|
|
|
85359c |
need to probe. */
|
|
|
85359c |
@@ -9888,21 +9887,40 @@ ix86_adjust_stack_and_probe_stack_clash
|
|
|
85359c |
pointer could be anywhere in the guard page. The safe thing
|
|
|
85359c |
to do is emit a probe now.
|
|
|
85359c |
|
|
|
85359c |
+ The probe can be avoided if we have already emitted any callee
|
|
|
85359c |
+ register saves into the stack or have a frame pointer (which will
|
|
|
85359c |
+ have been saved as well). Those saves will function as implicit
|
|
|
85359c |
+ probes.
|
|
|
85359c |
+
|
|
|
85359c |
?!? This should be revamped to work like aarch64 and s390 where
|
|
|
85359c |
we track the offset from the most recent probe. Normally that
|
|
|
85359c |
offset would be zero. For a non-return function we would reset
|
|
|
85359c |
it to PROBE_INTERVAL - (STACK_BOUNDARY / BITS_PER_UNIT). Then
|
|
|
85359c |
we just probe when we cross PROBE_INTERVAL. */
|
|
|
85359c |
- if (TREE_THIS_VOLATILE (cfun->decl))
|
|
|
85359c |
+ if (TREE_THIS_VOLATILE (cfun->decl)
|
|
|
85359c |
+ && !(frame.nregs || frame.nsseregs || frame_pointer_needed))
|
|
|
85359c |
+
|
|
|
85359c |
{
|
|
|
85359c |
/* We can safely use any register here since we're just going to push
|
|
|
85359c |
its value and immediately pop it back. But we do try and avoid
|
|
|
85359c |
argument passing registers so as not to introduce dependencies in
|
|
|
85359c |
the pipeline. For 32 bit we use %esi and for 64 bit we use %rax. */
|
|
|
85359c |
rtx dummy_reg = gen_rtx_REG (word_mode, TARGET_64BIT ? AX_REG : SI_REG);
|
|
|
85359c |
- rtx insn = emit_insn (gen_push (dummy_reg));
|
|
|
85359c |
- RTX_FRAME_RELATED_P (insn) = 1;
|
|
|
85359c |
- ix86_emit_restore_reg_using_pop (dummy_reg);
|
|
|
85359c |
+ rtx insn_push = emit_insn (gen_push (dummy_reg));
|
|
|
85359c |
+ rtx insn_pop = emit_insn (gen_pop (dummy_reg));
|
|
|
85359c |
+ m->fs.sp_offset -= UNITS_PER_WORD;
|
|
|
85359c |
+ if (m->fs.cfa_reg == stack_pointer_rtx)
|
|
|
85359c |
+ {
|
|
|
85359c |
+ m->fs.cfa_offset -= UNITS_PER_WORD;
|
|
|
85359c |
+ rtx x = plus_constant (Pmode, stack_pointer_rtx, -UNITS_PER_WORD);
|
|
|
85359c |
+ x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
|
|
|
85359c |
+ add_reg_note (insn_push, REG_CFA_ADJUST_CFA, x);
|
|
|
85359c |
+ RTX_FRAME_RELATED_P (insn_push) = 1;
|
|
|
85359c |
+ x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
|
|
|
85359c |
+ x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
|
|
|
85359c |
+ add_reg_note (insn_pop, REG_CFA_ADJUST_CFA, x);
|
|
|
85359c |
+ RTX_FRAME_RELATED_P (insn_pop) = 1;
|
|
|
85359c |
+ }
|
|
|
85359c |
emit_insn (gen_blockage ());
|
|
|
85359c |
}
|
|
|
85359c |
|
|
|
85359c |
|
|
|
85359c |
diff -Nrup a/gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-12.c b/gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-12.c
|
|
|
85359c |
--- gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-12.c 2018-01-03 15:42:40.849530670 -0700
|
|
|
85359c |
+++ gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-12.c 2018-01-03 15:36:12.528488596 -0700
|
|
|
85359c |
@@ -7,7 +7,6 @@ __attribute__ ((noreturn)) void exit (in
|
|
|
85359c |
__attribute__ ((noreturn)) void
|
|
|
85359c |
f (void)
|
|
|
85359c |
{
|
|
|
85359c |
- asm volatile ("nop" ::: "edi");
|
|
|
85359c |
exit (1);
|
|
|
85359c |
}
|
|
|
85359c |
|
|
|
85359c |
diff -Nrup a/gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-17.c b/gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-17.c
|
|
|
85359c |
--- gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-17.c 1969-12-31 17:00:00.000000000 -0700
|
|
|
85359c |
+++ gcc-4.8.5-20150702/gcc/testsuite/gcc.target/i386/stack-check-17.c 2018-01-03 15:36:12.528488596 -0700
|
|
|
85359c |
@@ -0,0 +1,37 @@
|
|
|
85359c |
+/* { dg-do compile } */
|
|
|
85359c |
+/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fomit-frame-pointer" } */
|
|
|
85359c |
+/* { dg-require-effective-target supports_stack_clash_protection } */
|
|
|
85359c |
+
|
|
|
85359c |
+
|
|
|
85359c |
+int x0, x1;
|
|
|
85359c |
+void f1 (void);
|
|
|
85359c |
+void f2 (int, int);
|
|
|
85359c |
+
|
|
|
85359c |
+__attribute__ ((noreturn))
|
|
|
85359c |
+void
|
|
|
85359c |
+f3 (void)
|
|
|
85359c |
+{
|
|
|
85359c |
+ int y0 = x0;
|
|
|
85359c |
+ int y1 = x1;
|
|
|
85359c |
+ f1 ();
|
|
|
85359c |
+ f2 (y0, y1);
|
|
|
85359c |
+ while (1);
|
|
|
85359c |
+}
|
|
|
85359c |
+
|
|
|
85359c |
+/* Verify no explicit probes. */
|
|
|
85359c |
+/* { dg-final { scan-assembler-not "or\[ql\]" } } */
|
|
|
85359c |
+
|
|
|
85359c |
+/* We also want to verify we did not use a push/pop sequence
|
|
|
85359c |
+ to probe *sp as the callee register saves are sufficient
|
|
|
85359c |
+ to probe *sp.
|
|
|
85359c |
+
|
|
|
85359c |
+ y0/y1 are live across the call and thus must be allocated
|
|
|
85359c |
+ into either a stack slot or callee saved register. The former
|
|
|
85359c |
+ would be rather dumb. So assume it does not happen.
|
|
|
85359c |
+
|
|
|
85359c |
+ So search for two/four pushes for the callee register saves/argument
|
|
|
85359c |
+ pushes and no pops (since the function has no reachable epilogue). */
|
|
|
85359c |
+/* { dg-final { scan-assembler-times "push\[ql\]" 2 { target { ! ia32 } } } } */
|
|
|
85359c |
+/* { dg-final { scan-assembler-times "push\[ql\]" 4 { target { ia32 } } } } */
|
|
|
85359c |
+/* { dg-final { scan-assembler-not "pop" } } */
|
|
|
85359c |
+
|