Blame SOURCES/gcc48-rh1537828-4.patch

802f23
commit 14041afe24556efd5845564aa183b6451fd9d6cc
802f23
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
802f23
Date:   Thu Feb 1 16:22:56 2018 +0000
802f23
802f23
            PR target/84128
802f23
            * config/i386/i386.c (release_scratch_register_on_entry): Add new
802f23
            OFFSET and RELEASE_VIA_POP arguments.  Use SP+OFFSET to restore
802f23
            the scratch if RELEASE_VIA_POP is false.
802f23
            (ix86_adjust_stack_and_probe_stack_clash): Un-constify SIZE.
802f23
            If we have to save a temporary register, decrement SIZE appropriately.
802f23
            Pass new arguments to release_scratch_register_on_entry.
802f23
            (ix86_adjust_stack_and_probe): Likewise.
802f23
            (ix86_emit_probe_stack_range): Pass new arguments to
802f23
            release_scratch_register_on_entry.
802f23
802f23
            PR target/84128
802f23
            * gcc.target/i386/pr84128.c: New test.
802f23
802f23
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
802f23
index 2fe2a0c..c25d26c 100644
802f23
--- a/gcc/config/i386/i386.c
802f23
+++ b/gcc/config/i386/i386.c
802f23
@@ -10182,22 +10182,39 @@ get_scratch_register_on_entry (struct scratch_reg *sr)
802f23
     }
802f23
 }
802f23
 
802f23
-/* Release a scratch register obtained from the preceding function.  */
802f23
+/* Release a scratch register obtained from the preceding function.
802f23
+
802f23
+   If RELEASE_VIA_POP is true, we just pop the register off the stack
802f23
+   to release it.  This is what non-Linux systems use with -fstack-check.
802f23
+
802f23
+   Otherwise we use OFFSET to locate the saved register and the
802f23
+   allocated stack space becomes part of the local frame and is
802f23
+   deallcated by the epilogue.  */
802f23
 
802f23
 static void
802f23
-release_scratch_register_on_entry (struct scratch_reg *sr)
802f23
+release_scratch_register_on_entry (struct scratch_reg *sr, HOST_WIDE_INT offset,
802f23
+				   bool release_via_pop)
802f23
 {
802f23
   if (sr->saved)
802f23
     {
802f23
-      struct machine_function *m = cfun->machine;
802f23
-      rtx x, insn = emit_insn (gen_pop (sr->reg));
802f23
+      if (release_via_pop)
802f23
+	{
802f23
+	  struct machine_function *m = cfun->machine;
802f23
+	  rtx x, insn = emit_insn (gen_pop (sr->reg));
802f23
 
802f23
-      /* The RTX_FRAME_RELATED_P mechanism doesn't know about pop.  */
802f23
-      RTX_FRAME_RELATED_P (insn) = 1;
802f23
-      x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD));
802f23
-      x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
802f23
-      add_reg_note (insn, REG_FRAME_RELATED_EXPR, x);
802f23
-      m->fs.sp_offset -= UNITS_PER_WORD;
802f23
+	  /* The RTX FRAME_RELATED_P mechanism doesn't know about pop.  */
802f23
+	  RTX_FRAME_RELATED_P (insn) = 1;
802f23
+	  x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD));
802f23
+	  x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
802f23
+	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, x);
802f23
+	  m->fs.sp_offset -= UNITS_PER_WORD;
802f23
+	}
802f23
+      else
802f23
+	{
802f23
+	  rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
802f23
+	  x = gen_rtx_SET (VOIDmode, sr->reg, gen_rtx_MEM (word_mode, x));
802f23
+	  emit_insn (x);
802f23
+	}
802f23
     }
802f23
 }
802f23
 
802f23
@@ -10212,7 +10229,7 @@ release_scratch_register_on_entry (struct scratch_reg *sr)
802f23
    pushed on the stack.  */
802f23
 
802f23
 static void
802f23
-ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size,
802f23
+ix86_adjust_stack_and_probe_stack_clash (HOST_WIDE_INT size,
802f23
 					 const bool int_registers_saved)
802f23
 {
802f23
   struct machine_function *m = cfun->machine;
802f23
@@ -10331,6 +10348,12 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size,
802f23
       struct scratch_reg sr;
802f23
       get_scratch_register_on_entry (&sr);
802f23
 
802f23
+      /* If we needed to save a register, then account for any space
802f23
+	 that was pushed (we are not going to pop the register when
802f23
+	 we do the restore).  */
802f23
+      if (sr.saved)
802f23
+	size -= UNITS_PER_WORD;
802f23
+
802f23
       /* Step 1: round SIZE down to a multiple of the interval.  */
802f23
       HOST_WIDE_INT rounded_size = size & -probe_interval;
802f23
 
802f23
@@ -10379,7 +10402,9 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size,
802f23
 				   m->fs.cfa_reg == stack_pointer_rtx);
802f23
       dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
802f23
 
802f23
-      release_scratch_register_on_entry (&sr);
802f23
+      /* This does not deallocate the space reserved for the scratch
802f23
+	 register.  That will be deallocated in the epilogue.  */
802f23
+      release_scratch_register_on_entry (&sr, size, false);
802f23
     }
802f23
 
802f23
   /* Make sure nothing is scheduled before we are done.  */
802f23
@@ -10392,7 +10417,7 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size,
802f23
    pushed on the stack.  */
802f23
 
802f23
 static void
802f23
-ix86_adjust_stack_and_probe (const HOST_WIDE_INT size,
802f23
+ix86_adjust_stack_and_probe (HOST_WIDE_INT size,
802f23
 			     const bool int_registers_saved)
802f23
 {
802f23
   /* We skip the probe for the first interval + a small dope of 4 words and
802f23
@@ -10465,6 +10490,11 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size,
802f23
 
802f23
       get_scratch_register_on_entry (&sr);
802f23
 
802f23
+      /* If we needed to save a register, then account for any space
802f23
+	 that was pushed (we are not going to pop the register when
802f23
+	 we do the restore).  */
802f23
+      if (sr.saved)
802f23
+	size -= UNITS_PER_WORD;
802f23
 
802f23
       /* Step 1: round SIZE to the previous multiple of the interval.  */
802f23
 
802f23
@@ -10516,7 +10546,9 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size,
802f23
 						    (get_probe_interval ()
802f23
 						     + dope))));
802f23
 
802f23
-      release_scratch_register_on_entry (&sr);
802f23
+      /* This does not deallocate the space reserved for the scratch
802f23
+	 register.  That will be deallocated in the epilogue.  */
802f23
+      release_scratch_register_on_entry (&sr, size, false);
802f23
     }
802f23
 
802f23
   gcc_assert (cfun->machine->fs.cfa_reg != stack_pointer_rtx);
802f23
@@ -10669,7 +10701,7 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
802f23
 						       sr.reg),
802f23
 					 rounded_size - size));
802f23
 
802f23
-      release_scratch_register_on_entry (&sr);
802f23
+      release_scratch_register_on_entry (&sr, size, true);
802f23
     }
802f23
 
802f23
   /* Make sure nothing is scheduled before we are done.  */
802f23
diff --git a/gcc/testsuite/gcc.target/i386/pr84128.c b/gcc/testsuite/gcc.target/i386/pr84128.c
802f23
new file mode 100644
802f23
index 0000000..a8323fd
802f23
--- /dev/null
802f23
+++ b/gcc/testsuite/gcc.target/i386/pr84128.c
802f23
@@ -0,0 +1,30 @@
802f23
+/* { dg-do run } */
802f23
+/* { dg-options "-O2 -march=i686 -mtune=generic -fstack-clash-protection" } */
802f23
+/* { dg-require-effective-target ia32 } */
802f23
+
802f23
+__attribute__ ((noinline, noclone, weak, regparm (3)))
802f23
+int
802f23
+f1 (long arg0, int (*pf) (long, void *))
802f23
+{
802f23
+  unsigned char buf[32768];
802f23
+  return pf (arg0, buf);
802f23
+}
802f23
+
802f23
+__attribute__ ((noinline, noclone, weak))
802f23
+int
802f23
+f2 (long arg0, void *ignored)
802f23
+{
802f23
+  if (arg0 != 17)
802f23
+    __builtin_abort ();
802f23
+  return 19;
802f23
+}
802f23
+
802f23
+int
802f23
+main (void)
802f23
+{
802f23
+  if (f1 (17, f2) != 19)
802f23
+    __builtin_abort ();
802f23
+  return 0;
802f23
+}
802f23
+
802f23
+