Blame SOURCES/gcc48-rh1469697-22.patch

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