56d343
commit 33839c8f8aa7857cc5f22ddb3f0960999cb0dfc7
56d343
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
56d343
Date:   Wed Jan 31 05:02:30 2018 +0000
56d343
56d343
            PR target/84064
56d343
            * i386.c (ix86_adjust_stack_and_probe_stack_clash): New argument
56d343
            INT_REGISTERS_SAVED.  Check it prior to calling
56d343
            get_scratch_register_on_entry.
56d343
            (ix86_adjust_stack_and_probe): Similarly.
56d343
            (ix86_emit_probe_stack_range): Similarly.
56d343
            (ix86_expand_prologue): Corresponding changes.
56d343
56d343
            PR target/84064
56d343
            * gcc.target/i386/pr84064: New test.
56d343
56d343
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
56d343
index 5230227..2fe2a0c 100644
56d343
--- a/gcc/config/i386/i386.c
56d343
+++ b/gcc/config/i386/i386.c
56d343
@@ -10206,10 +10206,14 @@ release_scratch_register_on_entry (struct scratch_reg *sr)
56d343
    This differs from the next routine in that it tries hard to prevent
56d343
    attacks that jump the stack guard.  Thus it is never allowed to allocate
56d343
    more than PROBE_INTERVAL bytes of stack space without a suitable
56d343
-   probe.  */
56d343
+   probe.
56d343
+
56d343
+   INT_REGISTERS_SAVED is true if integer registers have already been
56d343
+   pushed on the stack.  */
56d343
 
56d343
 static void
56d343
-ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
56d343
+ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size,
56d343
+					 const bool int_registers_saved)
56d343
 {
56d343
   struct machine_function *m = cfun->machine;
56d343
   struct ix86_frame frame;
56d343
@@ -10318,6 +10322,12 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
56d343
     }
56d343
   else
56d343
     {
56d343
+      /* We expect the GP registers to be saved when probes are used
56d343
+	 as the probing sequences might need a scratch register and
56d343
+	 the routine to allocate one assumes the integer registers
56d343
+	 have already been saved.  */
56d343
+      gcc_assert (int_registers_saved);
56d343
+
56d343
       struct scratch_reg sr;
56d343
       get_scratch_register_on_entry (&sr);
56d343
 
56d343
@@ -10376,10 +10386,14 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
56d343
   emit_insn (gen_blockage ());
56d343
 }
56d343
 
56d343
-/* Emit code to adjust the stack pointer by SIZE bytes while probing it.  */
56d343
+/* Emit code to adjust the stack pointer by SIZE bytes while probing it.
56d343
+
56d343
+   INT_REGISTERS_SAVED is true if integer registers have already been
56d343
+   pushed on the stack.  */
56d343
 
56d343
 static void
56d343
-ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
56d343
+ix86_adjust_stack_and_probe (const HOST_WIDE_INT size,
56d343
+			     const bool int_registers_saved)
56d343
 {
56d343
   /* We skip the probe for the first interval + a small dope of 4 words and
56d343
      probe that many bytes past the specified size to maintain a protection
56d343
@@ -10440,6 +10454,12 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
56d343
      equality test for the loop condition.  */
56d343
   else
56d343
     {
56d343
+      /* We expect the GP registers to be saved when probes are used
56d343
+	 as the probing sequences might need a scratch register and
56d343
+	 the routine to allocate one assumes the integer registers
56d343
+	 have already been saved.  */
56d343
+      gcc_assert (int_registers_saved);
56d343
+
56d343
       HOST_WIDE_INT rounded_size;
56d343
       struct scratch_reg sr;
56d343
 
56d343
@@ -10564,10 +10584,14 @@ output_adjust_stack_and_probe (rtx reg)
56d343
 }
56d343
 
56d343
 /* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
56d343
-   inclusive.  These are offsets from the current stack pointer.  */
56d343
+   inclusive.  These are offsets from the current stack pointer.
56d343
+
56d343
+   INT_REGISTERS_SAVED is true if integer registers have already been
56d343
+   pushed on the stack.  */
56d343
 
56d343
 static void
56d343
-ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
56d343
+ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
56d343
+			     const bool int_registers_saved)
56d343
 {
56d343
   /* See if we have a constant small number of probes to generate.  If so,
56d343
      that's the easy case.  The run-time loop is made up of 7 insns in the
56d343
@@ -10595,6 +10619,12 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
56d343
      equality test for the loop condition.  */
56d343
   else
56d343
     {
56d343
+      /* We expect the GP registers to be saved when probes are used
56d343
+	 as the probing sequences might need a scratch register and
56d343
+	 the routine to allocate one assumes the integer registers
56d343
+	 have already been saved.  */
56d343
+      gcc_assert (int_registers_saved);
56d343
+
56d343
       HOST_WIDE_INT rounded_size, last;
56d343
       struct scratch_reg sr;
56d343
 
56d343
@@ -11072,20 +11102,15 @@ ix86_expand_prologue (void)
56d343
       && (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
56d343
 	  || flag_stack_clash_protection))
56d343
     {
56d343
-      /* We expect the GP registers to be saved when probes are used
56d343
-	 as the probing sequences might need a scratch register and
56d343
-	 the routine to allocate one assumes the integer registers
56d343
-	 have already been saved.  */
56d343
-      gcc_assert (int_registers_saved);
56d343
-
56d343
       if (flag_stack_clash_protection)
56d343
 	{
56d343
-	  ix86_adjust_stack_and_probe_stack_clash (allocate);
56d343
+	  ix86_adjust_stack_and_probe_stack_clash (allocate,
56d343
+						   int_registers_saved);
56d343
 	  allocate = 0;
56d343
 	}
56d343
       else if (STACK_CHECK_MOVING_SP)
56d343
 	{
56d343
-	  ix86_adjust_stack_and_probe (allocate);
56d343
+	  ix86_adjust_stack_and_probe (allocate, int_registers_saved);
56d343
 	  allocate = 0;
56d343
 	}
56d343
       else
56d343
@@ -11096,9 +11121,11 @@ ix86_expand_prologue (void)
56d343
 	    size = 0x80000000 - get_stack_check_protect () - 1;
56d343
 
56d343
 	  if (TARGET_STACK_PROBE)
56d343
-	    ix86_emit_probe_stack_range (0, size + get_stack_check_protect ());
56d343
+	    ix86_emit_probe_stack_range (0, size + get_stack_check_protect (),
56d343
+					 int_registers_saved);
56d343
 	  else
56d343
-	    ix86_emit_probe_stack_range (get_stack_check_protect (), size);
56d343
+	    ix86_emit_probe_stack_range (get_stack_check_protect (), size,
56d343
+					 int_registers_saved);
56d343
 	}
56d343
     }
56d343
 
56d343
diff --git a/gcc/testsuite/gcc.target/i386/pr84064.c b/gcc/testsuite/gcc.target/i386/pr84064.c
56d343
new file mode 100644
56d343
index 0000000..01f8d9e
56d343
--- /dev/null
56d343
+++ b/gcc/testsuite/gcc.target/i386/pr84064.c
56d343
@@ -0,0 +1,10 @@
56d343
+/* { dg-do compile } */
56d343
+/* { dg-options "-O2 -march=i686 -fstack-clash-protection" } */
56d343
+/* { dg-require-effective-target ia32 } */
56d343
+
56d343
+void
56d343
+f (void *p1, void *p2)
56d343
+{
56d343
+  __builtin_memcpy (p1, p2, 1000);
56d343
+}
56d343
+