public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Jeff Law <law@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/gcc] rhel-f41-base: - Backport -fstack-clash-protection from development trunk (#1512529)
Date: Mon, 29 Jun 2026 12:27:38 GMT	[thread overview]
Message-ID: <178273605857.1.7396222920870365489.rpms-gcc-e987aff0a2c5@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/gcc
Branch : rhel-f41-base
Commit : e987aff0a2c5b4c640bf032cee6b4610d57341bf
Author : Jeff Law <law@redhat.com>
Date   : 2017-11-28T09:02:22-07:00
Stats  : +6313/-1 in 19 file(s)
URL    : https://src.fedoraproject.org/rpms/gcc/c/e987aff0a2c5b4c640bf032cee6b4610d57341bf?branch=rhel-f41-base

Log:
- Backport -fstack-clash-protection from development trunk (#1512529)

---
diff --git a/gcc.spec b/gcc.spec
index 98742a1..37c61b2 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -4,7 +4,7 @@
 %global gcc_major 7
 # Note, gcc_release must be integer, if you want to add suffixes to
 # %{release}, append them after %{gcc_release} on Release: line.
-%global gcc_release 2
+%global gcc_release 3
 %global nvptx_tools_gitrev c28050f60193b3b95a18866a96f03334e874e78f
 %global nvptx_newlib_gitrev aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24
 %global _unpackaged_files_terminate_build 0
@@ -242,6 +242,25 @@ Patch1000: nvptx-tools-no-ptxas.patch
 Patch1001: nvptx-tools-build.patch
 Patch1002: nvptx-tools-glibc.patch
 
+Patch2001: gcc7-rh1512529-1.patch
+Patch2002: gcc7-rh1512529-2.patch
+Patch2003: gcc7-rh1512529-3.patch
+Patch2004: gcc7-rh1512529-4.patch
+Patch2005: gcc7-rh1512529-5.patch
+Patch2006: gcc7-rh1512529-6.patch
+Patch2007: gcc7-rh1512529-7.patch
+Patch2008: gcc7-rh1512529-8.patch
+Patch2009: gcc7-rh1512529-9.patch
+Patch2010: gcc7-rh1512529-10.patch
+Patch2011: gcc7-rh1512529-11.patch
+Patch2012: gcc7-rh1512529-12.patch
+Patch2013: gcc7-rh1512529-13.patch
+Patch2014: gcc7-rh1512529-14.patch
+Patch2015: gcc7-rh1512529-15.patch
+Patch2016: gcc7-rh1512529-16.patch
+Patch2017: gcc7-rh1512529-17.patch
+Patch2018: gcc7-rh1512529-18.patch
+
 # On ARM EABI systems, we do want -gnueabi to be part of the
 # target triple.
 %ifnarch %{arm}
@@ -838,6 +857,25 @@ cd nvptx-tools-%{nvptx_tools_gitrev}
 %patch1002 -p1 -b .nvptx-tools-glibc~
 cd ..
 
+%patch2001 -p1
+%patch2002 -p1
+%patch2003 -p1
+%patch2004 -p1
+%patch2005 -p1
+%patch2006 -p1
+%patch2007 -p1
+%patch2008 -p1
+%patch2009 -p1
+%patch2010 -p1
+%patch2011 -p1
+%patch2012 -p1
+%patch2013 -p1
+%patch2014 -p1
+%patch2015 -p1
+%patch2016 -p1
+%patch2017 -p1
+%patch2018 -p1
+
 %if 0%{?_enable_debug_packages}
 mkdir dwz-wrapper
 if [ -f /usr/bin/dwz ]; then
@@ -3248,6 +3286,9 @@ fi
 %endif
 
 %changelog
+* Tue Nov 28 2017 Jeff Law  <law@redhat.com> 7.2.1-3
+- Backport -fstack-clash-protection from development trunk (#1512529)
+
 * Fri Sep 15 2017 Jakub Jelinek <jakub@redhat.com> 7.2.1-2
 - update from the 7 branch
   - PRs ada/62235, ada/79441, ada/79542, bootstrap/81926, c++/81355,

diff --git a/gcc7-rh1512529-1.patch b/gcc7-rh1512529-1.patch
new file mode 100644
index 0000000..7b3e763
--- /dev/null
+++ b/gcc7-rh1512529-1.patch
@@ -0,0 +1,340 @@
+commit cc3586c7f4704acbbd3f2f99de5b82bcc8f6fe36
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 04:56:54 2017 +0000
+
+            * common.opt (-fstack-clash-protection): New option.
+            * flag-types.h (enum stack_check_type): Note difference between
+            -fstack-check= and -fstack-clash-protection.
+            * params.def (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE): New PARAM.
+            (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL): Likewise.
+            * toplev.c (process_options): Issue warnings/errors for cases
+            not handled with -fstack-clash-protection.
+            * doc/invoke.texi (-fstack-clash-protection): Document new option.
+            (-fstack-check): Note additional problem with -fstack-check=generic.
+            Note that -fstack-check is primarily for Ada and refer users
+            to -fstack-clash-protection for stack-clash-protection.
+            Document new params for stack clash protection.
+    
+            * gcc.dg/stack-check-2.c: New test.
+            * lib/target-supports.exp
+            (check_effective_target_supports_stack_clash_protection): New function.
+            (check_effective_target_frame_pointer_for_non_leaf): Likewise.
+            (check_effective_target_caller_implicit_probes): Likewise.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252994 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 592bbd15309..bcaea91c130 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2291,13 +2291,18 @@ Common Report Var(flag_variable_expansion_in_unroller) Optimization
+ Apply variable expansion when loops are unrolled.
+ 
+ fstack-check=
+-Common Report RejectNegative Joined
++Common Report RejectNegative Joined Optimization
+ -fstack-check=[no|generic|specific]	Insert stack checking code into the program.
+ 
+ fstack-check
+ Common Alias(fstack-check=, specific, no)
+ Insert stack checking code into the program.  Same as -fstack-check=specific.
+ 
++fstack-clash-protection
++Common Report Var(flag_stack_clash_protection) Optimization
++Insert code to probe each page of stack space as it is allocated to protect
++from stack-clash style attacks.
++
+ fstack-limit
+ Common Var(common_deferred_options) Defer
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index a0fb09eb9e1..f77035571a1 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -10026,6 +10026,21 @@ compilation without.  The value for compilation with profile feedback
+ needs to be more conservative (higher) in order to make tracer
+ effective.
+ 
++@item stack-clash-protection-guard-size
++Specify the size of the operating system provided stack guard as
++2 raised to @var{num} bytes.  The default value is 12 (4096 bytes).
++Acceptable values are between 12 and 30.  Higher values may reduce the
++number of explicit probes, but a value larger than the operating system
++provided guard will leave code vulnerable to stack clash style attacks.
++
++@item stack-clash-protection-probe-interval
++Stack clash protection involves probing stack space as it is allocated.  This
++param controls the maximum distance between probes into the stack as 2 raised
++to @var{num} bytes.  Acceptable values are between 10 and 16 and defaults to
++12.  Higher values may reduce the number of explicit probes, but a value
++larger than the operating system provided guard will leave code vulnerable to
++stack clash style attacks.
++
+ @item max-cse-path-length
+ 
+ The maximum number of basic blocks on path that CSE considers.
+@@ -11218,7 +11233,8 @@ target support in the compiler but comes with the following drawbacks:
+ @enumerate
+ @item
+ Modified allocation strategy for large objects: they are always
+-allocated dynamically if their size exceeds a fixed threshold.
++allocated dynamically if their size exceeds a fixed threshold.  Note this
++may change the semantics of some code.
+ 
+ @item
+ Fixed limit on the size of the static frame of functions: when it is
+@@ -11233,6 +11249,25 @@ generic implementation, code performance is hampered.
+ Note that old-style stack checking is also the fallback method for
+ @samp{specific} if no target support has been added in the compiler.
+ 
++@samp{-fstack-check=} is designed for Ada's needs to detect infinite recursion
++and stack overflows.  @samp{specific} is an excellent choice when compiling
++Ada code.  It is not generally sufficient to protect against stack-clash
++attacks.  To protect against those you want @samp{-fstack-clash-protection}.
++
++@item -fstack-clash-protection
++@opindex fstack-clash-protection
++Generate code to prevent stack clash style attacks.  When this option is
++enabled, the compiler will only allocate one page of stack space at a time
++and each page is accessed immediately after allocation.  Thus, it prevents
++allocations from jumping over any stack guard page provided by the
++operating system.
++
++Most targets do not fully support stack clash protection.  However, on
++those targets @option{-fstack-clash-protection} will protect dynamic stack
++allocations.  @option{-fstack-clash-protection} may also provide limited
++protection for static stack allocations if the target supports
++@option{-fstack-check=specific}.
++
+ @item -fstack-limit-register=@var{reg}
+ @itemx -fstack-limit-symbol=@var{sym}
+ @itemx -fno-stack-limit
+diff --git a/gcc/flag-types.h b/gcc/flag-types.h
+index 27a38efdc8e..4e5a4e58119 100644
+--- a/gcc/flag-types.h
++++ b/gcc/flag-types.h
+@@ -166,7 +166,14 @@ enum permitted_flt_eval_methods
+   PERMITTED_FLT_EVAL_METHODS_C11
+ };
+ 
+-/* Type of stack check.  */
++/* Type of stack check.
++
++   Stack checking is designed to detect infinite recursion and stack
++   overflows for Ada programs.  Furthermore stack checking tries to ensure
++   in that scenario that enough stack space is left to run a signal handler.
++
++   -fstack-check= does not prevent stack-clash style attacks.  For that
++   you want -fstack-clash-protection.  */
+ enum stack_check_type
+ {
+   /* Do not check the stack.  */
+diff --git a/gcc/params.def b/gcc/params.def
+index 6b07518a34b..ce66e393eb1 100644
+--- a/gcc/params.def
++++ b/gcc/params.def
+@@ -213,6 +213,16 @@ DEFPARAM(PARAM_STACK_FRAME_GROWTH,
+ 	 "Maximal stack frame growth due to inlining (in percent).",
+ 	 1000, 0, 0)
+ 
++DEFPARAM(PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE,
++	 "stack-clash-protection-guard-size",
++	 "Size of the stack guard expressed as a power of two.",
++	 12, 12, 30)
++
++DEFPARAM(PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL,
++	 "stack-clash-protection-probe-interval",
++	 "Interval in which to probe the stack expressed as a power of two.",
++	 12, 10, 16)
++
+ /* The GCSE optimization will be disabled if it would require
+    significantly more memory than this value.  */
+ DEFPARAM(PARAM_MAX_GCSE_MEMORY,
+diff --git a/gcc/testsuite/gcc.dg/stack-check-2.c b/gcc/testsuite/gcc.dg/stack-check-2.c
+new file mode 100644
+index 00000000000..196c4bbfbdd
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-2.c
+@@ -0,0 +1,66 @@
++/* The goal here is to ensure that we never consider a call to a noreturn
++   function as a potential tail call.
++
++   Right now GCC discovers potential tail calls by looking at the
++   predecessors of the exit block.  A call to a non-return function
++   has no successors and thus can never match that first filter.
++
++   But that could change one day and we want to catch it.  The problem
++   is the compiler could potentially optimize a tail call to a nonreturn
++   function, even if the caller has a frame.  That breaks the assumption
++   that calls probe *sp when saving the return address that some targets
++   depend on to elide stack probes.  */
++
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-tree-tailc -fdump-tree-optimized" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++extern void foo (void) __attribute__ ((__noreturn__));
++
++
++void
++test_direct_1 (void)
++{
++  foo ();
++}
++
++void
++test_direct_2 (void)
++{
++  return foo ();
++}
++
++void (*indirect)(void)__attribute__ ((noreturn));
++
++
++void
++test_indirect_1 ()
++{
++  (*indirect)();
++}
++
++void
++test_indirect_2 (void)
++{
++  return (*indirect)();;
++}
++
++
++typedef void (*pvfn)() __attribute__ ((noreturn));
++
++void (*indirect_casted)(void);
++
++void
++test_indirect_casted_1 ()
++{
++  (*(pvfn)indirect_casted)();
++}
++
++void
++test_indirect_casted_2 (void)
++{
++  return (*(pvfn)indirect_casted)();
++}
++/* { dg-final { scan-tree-dump-not "tail call" "tailc" } } */
++/* { dg-final { scan-tree-dump-not "tail call" "optimized" } } */
++
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index 57caec74836..1000f15358b 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8371,3 +8371,80 @@ proc check_effective_target_arm_coproc4_ok { } {
+     return [check_cached_effective_target arm_coproc4_ok \
+ 		check_effective_target_arm_coproc4_ok_nocache]
+ }
++
++# Return 1 if the target has support for stack probing designed
++# to avoid stack-clash style attacks.
++#
++# This is used to restrict the stack-clash mitigation tests to
++# just those targets that have been explicitly supported.
++# 
++# In addition to the prologue work on those targets, each target's
++# properties should be described in the functions below so that
++# tests do not become a mess of unreadable target conditions.
++# 
++proc check_effective_target_supports_stack_clash_protection { } {
++
++   # Temporary until the target bits are fully ACK'd.
++#  if { [istarget aarch*-*-*] || [istarget x86_64-*-*]
++#       || [istarget i?86-*-*] || [istarget s390*-*-*]
++#       || [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
++#	return 1
++#  }
++  return 0
++}
++
++# Return 1 if the target creates a frame pointer for non-leaf functions
++# Note we ignore cases where we apply tail call optimization here.
++proc check_effective_target_frame_pointer_for_non_leaf { } {
++  if { [istarget aarch*-*-*] } {
++	return 1
++  }
++  return 0
++}
++
++# Return 1 if the target's calling sequence or its ABI
++# create implicit stack probes at or prior to function entry.
++proc check_effective_target_caller_implicit_probes { } {
++
++  # On x86/x86_64 the call instruction itself pushes the return
++  # address onto the stack.  That is an implicit probe of *sp.
++  if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
++	return 1
++  }
++
++  # On PPC, the ABI mandates that the address of the outer
++  # frame be stored at *sp.  Thus each allocation of stack
++  # space is itself an implicit probe of *sp.
++  if { [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
++	return 1
++  }
++
++  # s390's ABI has a register save area allocated by the
++  # caller for use by the callee.  The mere existence does
++  # not constitute a probe by the caller, but when the slots
++  # used by the callee those stores are implicit probes.
++  if { [istarget s390*-*-*] } {
++	return 1
++  }
++
++  # Not strictly true on aarch64, but we have agreed that we will
++  # consider any function that pushes SP more than 3kbytes into
++  # the guard page as broken.  This essentially means that we can
++  # consider the aarch64 as having a caller implicit probe at
++  # *(sp + 1k).
++  if { [istarget aarch64*-*-*] } {
++	return 1;
++  }
++
++  return 0
++}
++
++# Targets that potentially realign the stack pointer often cause residual
++# stack allocations and make it difficult to elimination loops or residual
++# allocations for dynamic stack allocations
++proc check_effective_target_callee_realigns_stack { } {
++  if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
++	return 1
++  }
++  return 0
++}
+diff --git a/gcc/toplev.c b/gcc/toplev.c
+index e7a5d487313..a7da7964fbb 100644
+--- a/gcc/toplev.c
++++ b/gcc/toplev.c
+@@ -1574,6 +1574,26 @@ process_options (void)
+       flag_associative_math = 0;
+     }
+ 
++  /* -fstack-clash-protection is not currently supported on targets
++     where the stack grows up.  */
++  if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD)
++    {
++      warning_at (UNKNOWN_LOCATION, 0,
++		  "%<-fstack-clash-protection%> is not supported on targets "
++		  "where the stack grows from lower to higher addresses");
++      flag_stack_clash_protection = 0;
++    }
++
++  /* We can not support -fstack-check= and -fstack-clash-protection at
++     the same time.  */
++  if (flag_stack_check != NO_STACK_CHECK && flag_stack_clash_protection)
++    {
++      warning_at (UNKNOWN_LOCATION, 0,
++		  "%<-fstack-check=%> and %<-fstack-clash_protection%> are "
++		  "mutually exclusive.  Disabling %<-fstack-check=%>");
++      flag_stack_check = NO_STACK_CHECK;
++    }
++
+   /* With -fcx-limited-range, we do cheap and quick complex arithmetic.  */
+   if (flag_cx_limited_range)
+     flag_complex_method = 0;

diff --git a/gcc7-rh1512529-10.patch b/gcc7-rh1512529-10.patch
new file mode 100644
index 0000000..26ccbf4
--- /dev/null
+++ b/gcc7-rh1512529-10.patch
@@ -0,0 +1,605 @@
+commit b552ddab57a34fe1acb8d714b5f556082600b9e0
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Mon Sep 25 23:13:55 2017 +0000
+
+            * config/rs6000/rs6000-protos.h (output_probe_stack_range): Update
+            prototype for new argument.
+            * config/rs6000/rs6000.c (rs6000_emit_allocate_stack_1): New function,
+            mostly extracted from rs6000_emit_allocate_stack.
+            (rs6000_emit_probe_stack_range_stack_clash): New function.
+            (rs6000_emit_allocate_stack): Call
+            rs6000_emit_probe_stack_range_stack_clash as needed.
+            (rs6000_emit_probe_stack_range): Add additional argument
+            to call to gen_probe_stack_range{si,di}.
+            (output_probe_stack_range): New.
+            (output_probe_stack_range_1): Renamed from output_probe_stack_range.
+            (output_probe_stack_range_stack_clash): New.
+            (rs6000_emit_prologue): Emit notes into dump file as requested.
+            * rs6000.md (allocate_stack): Handle -fstack-clash-protection.
+            (probe_stack_range<P:mode>): Operand 0 is now early-clobbered.
+            Add additional operand and pass it to output_probe_stack_range.
+    
+            * lib/target-supports.exp
+            (check_effective_target_supports_stack_clash_protection): Enable for
+            rs6000 and powerpc targets.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253179 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
+index 74ad733d1b9..d48aa88f4b1 100644
+--- a/gcc/config/rs6000/rs6000-protos.h
++++ b/gcc/config/rs6000/rs6000-protos.h
+@@ -134,7 +134,7 @@ extern void rs6000_emit_sCOND (machine_mode, rtx[]);
+ extern void rs6000_emit_cbranch (machine_mode, rtx[]);
+ extern char * output_cbranch (rtx, const char *, int, rtx_insn *);
+ extern char * output_e500_flip_gt_bit (rtx, rtx);
+-extern const char * output_probe_stack_range (rtx, rtx);
++extern const char * output_probe_stack_range (rtx, rtx, rtx);
+ extern bool rs6000_emit_set_const (rtx, rtx);
+ extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
+ extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
+diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
+index 1836e1d147d..8235bff2469 100644
+--- a/gcc/config/rs6000/rs6000.c
++++ b/gcc/config/rs6000/rs6000.c
+@@ -28133,6 +28133,221 @@ rs6000_emit_stack_tie (rtx fp, bool hard_frame_needed)
+   emit_insn (gen_stack_tie (gen_rtx_PARALLEL (VOIDmode, p)));
+ }
+ 
++/* Allocate SIZE_INT bytes on the stack using a store with update style insn
++   and set the appropriate attributes for the generated insn.  Return the
++   first insn which adjusts the stack pointer or the last insn before
++   the stack adjustment loop. 
++
++   SIZE_INT is used to create the CFI note for the allocation.
++
++   SIZE_RTX is an rtx containing the size of the adjustment.  Note that
++   since stacks grow to lower addresses its runtime value is -SIZE_INT.
++
++   ORIG_SP contains the backchain value that must be stored at *sp.  */
++
++static rtx_insn *
++rs6000_emit_allocate_stack_1 (HOST_WIDE_INT size_int, rtx orig_sp)
++{
++  rtx_insn *insn;
++
++  rtx size_rtx = GEN_INT (-size_int);
++  if (size_int > 32767)
++    {
++      rtx tmp_reg = gen_rtx_REG (Pmode, 0);
++      /* Need a note here so that try_split doesn't get confused.  */
++      if (get_last_insn () == NULL_RTX)
++	emit_note (NOTE_INSN_DELETED);
++      insn = emit_move_insn (tmp_reg, size_rtx);
++      try_split (PATTERN (insn), insn, 0);
++      size_rtx = tmp_reg;
++    }
++  
++  if (Pmode == SImode)
++    insn = emit_insn (gen_movsi_update_stack (stack_pointer_rtx,
++					      stack_pointer_rtx,
++					      size_rtx,
++					      orig_sp));
++  else
++    insn = emit_insn (gen_movdi_di_update_stack (stack_pointer_rtx,
++						 stack_pointer_rtx,
++						 size_rtx,
++						 orig_sp));
++  rtx par = PATTERN (insn);
++  gcc_assert (GET_CODE (par) == PARALLEL);
++  rtx set = XVECEXP (par, 0, 0);
++  gcc_assert (GET_CODE (set) == SET);
++  rtx mem = SET_DEST (set);
++  gcc_assert (MEM_P (mem));
++  MEM_NOTRAP_P (mem) = 1;
++  set_mem_alias_set (mem, get_frame_alias_set ());
++
++  RTX_FRAME_RELATED_P (insn) = 1;
++  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
++		gen_rtx_SET (stack_pointer_rtx,
++			     gen_rtx_PLUS (Pmode,
++					   stack_pointer_rtx,
++					   GEN_INT (-size_int))));
++
++  /* Emit a blockage to ensure the allocation/probing insns are
++     not optimized, combined, removed, etc.  Add REG_STACK_CHECK
++     note for similar reasons.  */
++  if (flag_stack_clash_protection)
++    {
++      add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
++      emit_insn (gen_blockage ());
++    }
++
++  return insn;
++}
++
++static HOST_WIDE_INT
++get_stack_clash_protection_probe_interval (void)
++{
++  return (HOST_WIDE_INT_1U
++	  << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL));
++}
++
++static HOST_WIDE_INT
++get_stack_clash_protection_guard_size (void)
++{
++  return (HOST_WIDE_INT_1U
++	  << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE));
++}
++
++/* Allocate ORIG_SIZE bytes on the stack and probe the newly
++   allocated space every STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes.
++
++   COPY_REG, if non-null, should contain a copy of the original
++   stack pointer at exit from this function.
++
++   This is subtly different than the Ada probing in that it tries hard to
++   prevent attacks that jump the stack guard.  Thus it is never allowed to
++   allocate more than STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes of stack
++   space without a suitable probe.  */
++static rtx_insn *
++rs6000_emit_probe_stack_range_stack_clash (HOST_WIDE_INT orig_size,
++					   rtx copy_reg)
++{
++  rtx orig_sp = copy_reg;
++
++  HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
++
++  /* Round the size down to a multiple of PROBE_INTERVAL.  */
++  HOST_WIDE_INT rounded_size = ROUND_DOWN (orig_size, probe_interval);
++
++  /* If explicitly requested,
++       or the rounded size is not the same as the original size
++       or the the rounded size is greater than a page,
++     then we will need a copy of the original stack pointer.  */
++  if (rounded_size != orig_size
++      || rounded_size > probe_interval
++      || copy_reg)
++    {
++      /* If the caller did not request a copy of the incoming stack
++	 pointer, then we use r0 to hold the copy.  */
++      if (!copy_reg)
++	orig_sp = gen_rtx_REG (Pmode, 0);
++      emit_move_insn (orig_sp, stack_pointer_rtx);
++    }
++
++  /* There's three cases here.
++
++     One is a single probe which is the most common and most efficiently
++     implemented as it does not have to have a copy of the original
++     stack pointer if there are no residuals.
++
++     Second is unrolled allocation/probes which we use if there's just
++     a few of them.  It needs to save the original stack pointer into a
++     temporary for use as a source register in the allocation/probe.
++
++     Last is a loop.  This is the most uncommon case and least efficient.  */
++  rtx_insn *retval = NULL;
++  if (rounded_size == probe_interval)
++    {
++      retval = rs6000_emit_allocate_stack_1 (probe_interval, stack_pointer_rtx);
++
++      dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
++    }
++  else if (rounded_size <= 8 * probe_interval)
++    {
++      /* The ABI requires using the store with update insns to allocate
++	 space and store the backchain into the stack
++
++	 So we save the current stack pointer into a temporary, then
++	 emit the store-with-update insns to store the saved stack pointer
++	 into the right location in each new page.  */
++      for (int i = 0; i < rounded_size; i += probe_interval)
++	{
++	  rtx_insn *insn
++	    = rs6000_emit_allocate_stack_1 (probe_interval, orig_sp);
++
++	  /* Save the first stack adjustment in RETVAL.  */
++	  if (i == 0)
++	    retval = insn;
++	}
++
++      dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
++    }
++  else
++    {
++      /* Compute the ending address.  */
++      rtx end_addr
++	= copy_reg ? gen_rtx_REG (Pmode, 0) : gen_rtx_REG (Pmode, 12);
++      rtx rs = GEN_INT (-rounded_size);
++      rtx_insn *insn;
++      if (add_operand (rs, Pmode))
++	insn = emit_insn (gen_add3_insn (end_addr, stack_pointer_rtx, rs));
++      else
++	{
++	  emit_move_insn (end_addr, GEN_INT (-rounded_size));
++	  insn = emit_insn (gen_add3_insn (end_addr, end_addr,
++					   stack_pointer_rtx));
++	  /* Describe the effect of INSN to the CFI engine.  */
++	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
++			gen_rtx_SET (end_addr,
++				     gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++						   rs)));
++	}
++      RTX_FRAME_RELATED_P (insn) = 1;
++
++      /* Emit the loop.  */
++      if (TARGET_64BIT)
++	retval = emit_insn (gen_probe_stack_rangedi (stack_pointer_rtx,
++						     stack_pointer_rtx, orig_sp,
++						     end_addr));
++      else
++	retval = emit_insn (gen_probe_stack_rangesi (stack_pointer_rtx,
++						     stack_pointer_rtx, orig_sp,
++						     end_addr));
++      RTX_FRAME_RELATED_P (retval) = 1;
++      /* Describe the effect of INSN to the CFI engine.  */
++      add_reg_note (retval, REG_FRAME_RELATED_EXPR,
++		    gen_rtx_SET (stack_pointer_rtx, end_addr));
++
++      /* Emit a blockage to ensure the allocation/probing insns are
++	 not optimized, combined, removed, etc.  Other cases handle this
++	 within their call to rs6000_emit_allocate_stack_1.  */
++      emit_insn (gen_blockage ());
++
++      dump_stack_clash_frame_info (PROBE_LOOP, rounded_size != orig_size);
++    }
++
++  if (orig_size != rounded_size)
++    {
++      /* Allocate (and implicitly probe) any residual space.   */
++      HOST_WIDE_INT residual = orig_size - rounded_size;
++
++      rtx_insn *insn = rs6000_emit_allocate_stack_1 (residual, orig_sp);
++
++      /* If the residual was the only allocation, then we can return the
++	 allocating insn.  */
++      if (!retval)
++	retval = insn;
++    }
++
++  return retval;
++}
++
+ /* Emit the correct code for allocating stack space, as insns.
+    If COPY_REG, make sure a copy of the old frame is left there.
+    The generated code may use hard register 0 as a temporary.  */
+@@ -28144,7 +28359,6 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
+   rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+   rtx tmp_reg = gen_rtx_REG (Pmode, 0);
+   rtx todec = gen_int_mode (-size, Pmode);
+-  rtx par, set, mem;
+ 
+   if (INTVAL (todec) != -size)
+     {
+@@ -28184,6 +28398,23 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
+ 	warning (0, "stack limit expression is not supported");
+     }
+ 
++  if (flag_stack_clash_protection)
++    {
++      if (size < get_stack_clash_protection_guard_size ())
++	dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++      else
++	{
++	  rtx_insn *insn = rs6000_emit_probe_stack_range_stack_clash (size,
++								      copy_reg);
++
++	  /* If we asked for a copy with an offset, then we still need add in
++	     the offset.  */
++	  if (copy_reg && copy_off)
++	    emit_insn (gen_add3_insn (copy_reg, copy_reg, GEN_INT (copy_off)));
++	  return insn;
++	}
++    }
++
+   if (copy_reg)
+     {
+       if (copy_off != 0)
+@@ -28192,38 +28423,11 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
+ 	emit_move_insn (copy_reg, stack_reg);
+     }
+ 
+-  if (size > 32767)
+-    {
+-      /* Need a note here so that try_split doesn't get confused.  */
+-      if (get_last_insn () == NULL_RTX)
+-	emit_note (NOTE_INSN_DELETED);
+-      insn = emit_move_insn (tmp_reg, todec);
+-      try_split (PATTERN (insn), insn, 0);
+-      todec = tmp_reg;
+-    }
+-  
+-  insn = emit_insn (TARGET_32BIT
+-		    ? gen_movsi_update_stack (stack_reg, stack_reg,
+-					      todec, stack_reg)
+-		    : gen_movdi_di_update_stack (stack_reg, stack_reg,
+-						 todec, stack_reg));
+   /* Since we didn't use gen_frame_mem to generate the MEM, grab
+      it now and set the alias set/attributes. The above gen_*_update
+      calls will generate a PARALLEL with the MEM set being the first
+      operation. */
+-  par = PATTERN (insn);
+-  gcc_assert (GET_CODE (par) == PARALLEL);
+-  set = XVECEXP (par, 0, 0);
+-  gcc_assert (GET_CODE (set) == SET);
+-  mem = SET_DEST (set);
+-  gcc_assert (MEM_P (mem));
+-  MEM_NOTRAP_P (mem) = 1;
+-  set_mem_alias_set (mem, get_frame_alias_set ());
+-
+-  RTX_FRAME_RELATED_P (insn) = 1;
+-  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+-		gen_rtx_SET (stack_reg, gen_rtx_PLUS (Pmode, stack_reg,
+-						      GEN_INT (-size))));
++  insn = rs6000_emit_allocate_stack_1 (size, stack_reg);
+   return insn;
+ }
+ 
+@@ -28305,9 +28509,9 @@ rs6000_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+ 	 until it is equal to ROUNDED_SIZE.  */
+ 
+       if (TARGET_64BIT)
+-	emit_insn (gen_probe_stack_rangedi (r12, r12, r0));
++	emit_insn (gen_probe_stack_rangedi (r12, r12, stack_pointer_rtx, r0));
+       else
+-	emit_insn (gen_probe_stack_rangesi (r12, r12, r0));
++	emit_insn (gen_probe_stack_rangesi (r12, r12, stack_pointer_rtx, r0));
+ 
+ 
+       /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
+@@ -28319,10 +28523,10 @@ rs6000_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+ }
+ 
+ /* Probe a range of stack addresses from REG1 to REG2 inclusive.  These are
+-   absolute addresses.  */
++   addresses, not offsets.  */
+ 
+-const char *
+-output_probe_stack_range (rtx reg1, rtx reg2)
++static const char *
++output_probe_stack_range_1 (rtx reg1, rtx reg2)
+ {
+   static int labelno = 0;
+   char loop_lab[32];
+@@ -28357,6 +28561,95 @@ output_probe_stack_range (rtx reg1, rtx reg2)
+   return "";
+ }
+ 
++/* This function is called when rs6000_frame_related is processing
++   SETs within a PARALLEL, and returns whether the REGNO save ought to
++   be marked RTX_FRAME_RELATED_P.  The PARALLELs involved are those
++   for out-of-line register save functions, store multiple, and the
++   Darwin world_save.  They may contain registers that don't really
++   need saving.  */
++
++static bool
++interesting_frame_related_regno (unsigned int regno)
++{
++  /* Saves apparently of r0 are actually saving LR.  It doesn't make
++     sense to substitute the regno here to test save_reg_p (LR_REGNO).
++     We *know* LR needs saving, and dwarf2cfi.c is able to deduce that
++     (set (mem) (r0)) is saving LR from a prior (set (r0) (lr)) marked
++     as frame related.  */
++  if (regno == 0)
++    return true;
++  /* If we see CR2 then we are here on a Darwin world save.  Saves of
++     CR2 signify the whole CR is being saved.  This is a long-standing
++     ABI wart fixed by ELFv2.  As for r0/lr there is no need to check
++     that CR needs to be saved.  */
++  if (regno == CR2_REGNO)
++    return true;
++  /* Omit frame info for any user-defined global regs.  If frame info
++     is supplied for them, frame unwinding will restore a user reg.
++     Also omit frame info for any reg we don't need to save, as that
++     bloats frame info and can cause problems with shrink wrapping.
++     Since global regs won't be seen as needing to be saved, both of
++     these conditions are covered by save_reg_p.  */
++  return save_reg_p (regno);
++}
++
++/* Probe a range of stack addresses from REG1 to REG3 inclusive.  These are
++   addresses, not offsets.
++
++   REG2 contains the backchain that must be stored into *sp at each allocation.
++
++   This is subtly different than the Ada probing above in that it tries hard
++   to prevent attacks that jump the stack guard.  Thus, it is never allowed
++   to allocate more than PROBE_INTERVAL bytes of stack space without a
++   suitable probe.  */
++
++static const char *
++output_probe_stack_range_stack_clash (rtx reg1, rtx reg2, rtx reg3)
++{
++  static int labelno = 0;
++  char loop_lab[32];
++  rtx xops[3];
++
++  HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
++
++  ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
++
++  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
++
++  /* This allocates and probes.  */
++  xops[0] = reg1;
++  xops[1] = reg2;
++  xops[2] = GEN_INT (-probe_interval);
++  if (TARGET_64BIT)
++    output_asm_insn ("stdu %1,%2(%0)", xops);
++  else
++    output_asm_insn ("stwu %1,%2(%0)", xops);
++
++  /* Jump to LOOP_LAB if TEST_ADDR != LAST_ADDR.  */
++  xops[0] = reg1;
++  xops[1] = reg3;
++  if (TARGET_64BIT)
++    output_asm_insn ("cmpd 0,%0,%1", xops);
++  else
++    output_asm_insn ("cmpw 0,%0,%1", xops);
++
++  fputs ("\tbne 0,", asm_out_file);
++  assemble_name_raw (asm_out_file, loop_lab);
++  fputc ('\n', asm_out_file);
++
++  return "";
++}
++
++/* Wrapper around the output_probe_stack_range routines.  */
++const char *
++output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
++{
++  if (flag_stack_clash_protection)
++    return output_probe_stack_range_stack_clash (reg1, reg2, reg3);
++  else
++    return output_probe_stack_range_1 (reg1, reg3);
++}
++
+ /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
+    with (plus:P (reg 1) VAL), and with REG2 replaced with REPL2 if REG2
+    is not NULL.  It would be nice if dwarf2out_frame_debug_expr could
+@@ -29951,6 +30244,13 @@ rs6000_emit_prologue (void)
+ 	  }
+     }
+ 
++  /* If we are emitting stack probes, but allocate no stack, then
++     just note that in the dump file.  */
++  if (flag_stack_clash_protection
++      && dump_file
++      && !info->push_p)
++    dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
++
+   /* Update stack and set back pointer unless this is V.4,
+      for which it was done previously.  */
+   if (!WORLD_SAVE_P (info) && info->push_p
+diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
+index 3323976a35d..843148e9703 100644
+--- a/gcc/config/rs6000/rs6000.md
++++ b/gcc/config/rs6000/rs6000.md
+@@ -10386,10 +10386,20 @@
+ ;;
+ ;; First, an insn to allocate new stack space for dynamic use (e.g., alloca).
+ ;; We move the back-chain and decrement the stack pointer.
+-
++;;
++;; Operand1 is more naturally reg_or_short_operand.  However, for a large
++;; constant alloca, using that predicate will force the generic code to put
++;; the constant size into a register before calling the expander.
++;;
++;; As a result the expander would not have the constant size information
++;; in those cases and would have to generate less efficient code.
++;;
++;; Thus we allow reg_or_cint_operand instead so that the expander can see
++;; the constant size.  The value is forced into a register if necessary.
++;;
+ (define_expand "allocate_stack"
+   [(set (match_operand 0 "gpc_reg_operand" "")
+-	(minus (reg 1) (match_operand 1 "reg_or_short_operand" "")))
++	(minus (reg 1) (match_operand 1 "reg_or_cint_operand" "")))
+    (set (reg 1)
+ 	(minus (reg 1) (match_dup 1)))]
+   ""
+@@ -10399,6 +10409,15 @@
+   rtx neg_op0;
+   rtx insn, par, set, mem;
+ 
++  /* By allowing reg_or_cint_operand as the predicate we can get
++     better code for stack-clash-protection because we do not lose
++     size information.  But the rest of the code expects the operand
++     to be reg_or_short_operand.  If it isn't, then force it into
++     a register.  */
++  rtx orig_op1 = operands[1];
++  if (!reg_or_short_operand (operands[1], Pmode))
++    operands[1] = force_reg (Pmode, operands[1]);
++
+   emit_move_insn (chain, stack_bot);
+ 
+   /* Check stack bounds if necessary.  */
+@@ -10411,6 +10430,51 @@
+       emit_insn (gen_cond_trap (LTU, available, operands[1], const0_rtx));
+     }
+ 
++  /* Allocate and probe if requested.
++     This may look similar to the loop we use for prologue allocations,
++     but it is critically different.  For the former we know the loop
++     will iterate, but do not know that generally here.  The former
++     uses that knowledge to rotate the loop.  Combining them would be
++     possible with some performance cost.  */
++  if (flag_stack_clash_protection)
++    {
++      rtx rounded_size, last_addr, residual;
++      HOST_WIDE_INT probe_interval;
++      compute_stack_clash_protection_loop_data (&rounded_size, &last_addr,
++						&residual, &probe_interval,
++						orig_op1);
++      
++      /* We do occasionally get in here with constant sizes, we might
++	 as well do a reasonable job when we obviously can.  */
++      if (rounded_size != const0_rtx)
++	{
++	  rtx loop_lab, end_loop;
++	  bool rotated = CONST_INT_P (rounded_size);
++
++	  emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop,
++							last_addr, rotated);
++
++	  if (Pmode == SImode)
++	    emit_insn (gen_movsi_update_stack (stack_pointer_rtx,
++					       stack_pointer_rtx,
++					       GEN_INT (-probe_interval),
++					       chain));
++	  else
++	    emit_insn (gen_movdi_di_update_stack (stack_pointer_rtx,
++					          stack_pointer_rtx,
++					          GEN_INT (-probe_interval),
++					          chain));
++	  emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop,
++						      last_addr, rotated);
++	}
++
++      /* Now handle residuals.  We just have to set operands[1] correctly
++	 and let the rest of the expander run.  */
++      operands[1] = residual;
++      if (!CONST_INT_P (residual))
++	operands[1] = force_reg (Pmode, operands[1]);
++    }
++
+   if (GET_CODE (operands[1]) != CONST_INT
+       || INTVAL (operands[1]) < -32767
+       || INTVAL (operands[1]) > 32768)
+@@ -11549,12 +11613,13 @@
+    (set_attr "length" "4")])
+ 
+ (define_insn "probe_stack_range<P:mode>"
+-  [(set (match_operand:P 0 "register_operand" "=r")
++  [(set (match_operand:P 0 "register_operand" "=&r")
+ 	(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
+-			    (match_operand:P 2 "register_operand" "r")]
++			    (match_operand:P 2 "register_operand" "r")
++			    (match_operand:P 3 "register_operand" "r")]
+ 			   UNSPECV_PROBE_STACK_RANGE))]
+   ""
+-  "* return output_probe_stack_range (operands[0], operands[2]);"
++  "* return output_probe_stack_range (operands[0], operands[2], operands[3]);"
+   [(set_attr "type" "three")])
+ \f
+ ;; Compare insns are next.  Note that the RS/6000 has two types of compares,
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index cb58a2be35f..02eb2066393 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8385,12 +8385,12 @@ proc check_effective_target_arm_coproc4_ok { } {
+ proc check_effective_target_supports_stack_clash_protection { } {
+ 
+    # Temporary until the target bits are fully ACK'd.
+-#  if { [istarget aarch*-*-*]
+-#       || [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
++#  if { [istarget aarch*-*-*] } {
+ #	return 1
+ #  }
+ 
+     if { [istarget x86_64-*-*] || [istarget i?86-*-*] 
++	  || [istarget powerpc*-*-*] || [istarget rs6000*-*-*]
+ 	  || [istarget s390*-*-*] } {
+ 	return 1
+     }

diff --git a/gcc7-rh1512529-11.patch b/gcc7-rh1512529-11.patch
new file mode 100644
index 0000000..4d9c746
--- /dev/null
+++ b/gcc7-rh1512529-11.patch
@@ -0,0 +1,28 @@
+commit eecbe7ada9a8ab913e779a27c0e90ec736eedc78
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Fri Nov 3 17:14:23 2017 +0000
+
+            * config/i386/i386.c (ix86_expand_prologue): Tighten assert
+            for int_registers_saved.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254386 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 086848b2c73..fd74f1f6c0c 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -14172,8 +14172,12 @@ ix86_expand_prologue (void)
+       && (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+ 	  || flag_stack_clash_protection))
+     {
+-      /* We expect the registers to be saved when probes are used.  */
+-      gcc_assert (int_registers_saved);
++      /* This assert wants to verify that integer registers were saved
++	 prior to probing.  This is necessary when probing may be implemented
++	 as a function call (Windows).  It is not necessary for stack clash
++	 protection probing.  */
++      if (!flag_stack_clash_protection)
++	gcc_assert (int_registers_saved);
+ 
+       if (flag_stack_clash_protection)
+ 	{

diff --git a/gcc7-rh1512529-12.patch b/gcc7-rh1512529-12.patch
new file mode 100644
index 0000000..3f2786e
--- /dev/null
+++ b/gcc7-rh1512529-12.patch
@@ -0,0 +1,81 @@
+commit 75179275ecc35724a058676199188e0d13e65054
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Fri Nov 3 20:30:53 2017 +0000
+
+            * config/i386/i386.c (ix86_emit_restore_reg_using_pop): Prototype.
+            (ix86_adjust_stack_and_probe_stack_clash): Use a push/pop sequence
+            to probe at the start of a noreturn function.
+    
+            * gcc.target/i386/stack-check-12.c: New test.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254396 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index fd74f1f6c0c..3c828ba492d 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -96,6 +96,7 @@ static rtx legitimize_dllimport_symbol (rtx, bool);
+ static rtx legitimize_pe_coff_extern_decl (rtx, bool);
+ static rtx legitimize_pe_coff_symbol (rtx, bool);
+ static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool);
++static void ix86_emit_restore_reg_using_pop (rtx);
+ 
+ #ifndef CHECK_STACK_LIMIT
+ #define CHECK_STACK_LIMIT (-1)
+@@ -13287,10 +13288,13 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+      no probes are needed.  */
+   if (!size)
+     {
++      struct ix86_frame frame;
++      ix86_compute_frame_layout (&frame);
++
+       /* However, the allocation of space via pushes for register
+ 	 saves could be viewed as allocating space, but without the
+ 	 need to probe.  */
+-      if (m->frame.nregs || m->frame.nsseregs || frame_pointer_needed)
++      if (frame.nregs || frame.nsseregs || frame_pointer_needed)
+         dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
+       else
+ 	dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
+@@ -13312,8 +13316,14 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+      we just probe when we cross PROBE_INTERVAL.  */
+   if (TREE_THIS_VOLATILE (cfun->decl))
+     {
+-      emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+-				       -GET_MODE_SIZE (word_mode)));
++      /* We can safely use any register here since we're just going to push
++	 its value and immediately pop it back.  But we do try and avoid
++	 argument passing registers so as not to introduce dependencies in
++	 the pipeline.  For 32 bit we use %esi and for 64 bit we use %rax.  */
++      rtx dummy_reg = gen_rtx_REG (word_mode, TARGET_64BIT ? AX_REG : SI_REG);
++      rtx_insn *insn = emit_insn (gen_push (dummy_reg));
++      RTX_FRAME_RELATED_P (insn) = 1;
++      ix86_emit_restore_reg_using_pop (dummy_reg);
+       emit_insn (gen_blockage ());
+     }
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/stack-check-12.c b/gcc/testsuite/gcc.target/i386/stack-check-12.c
+new file mode 100644
+index 00000000000..cb69bb08086
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/stack-check-12.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -mtune=generic" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++__attribute__ ((noreturn)) void exit (int);
++
++__attribute__ ((noreturn)) void
++f (void)
++{
++  asm volatile ("nop" ::: "edi");
++  exit (1);
++}
++
++/* { dg-final { scan-assembler-not "or\[ql\]" } } */
++/* { dg-final { scan-assembler "pushl	%esi" { target ia32 } } } */
++/* { dg-final { scan-assembler "popl	%esi" { target ia32 } } }*/
++/* { dg-final { scan-assembler "pushq	%rax" { target { ! ia32 } } } } */
++/* { dg-final { scan-assembler "popq	%rax" { target { ! ia32 } } } }*/
++

diff --git a/gcc7-rh1512529-13.patch b/gcc7-rh1512529-13.patch
new file mode 100644
index 0000000..8221622
--- /dev/null
+++ b/gcc7-rh1512529-13.patch
@@ -0,0 +1,228 @@
+commit 2f97a7844f2211bbd4fd869c18e26801bb795aa9
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Mon Nov 6 15:51:16 2017 +0000
+
+            PR target/82788
+            * config/i386/i386.c (PROBE_INTERVAL): Remove.
+            (get_probe_interval): New functions.
+            (ix86_adjust_stack_and_probe_stack_clash): Use get_probe_interval.
+            (ix86_adjust_stack_and_probe): Likewise.
+            (output_adjust_stack_and_probe): Likewise.
+            (ix86_emit_probe_stack_range): Likewise.
+            (ix86_expand_prologue): Likewise.
+    
+            PR target/82788
+            * gcc.dg/pr82788.c: New test.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254456 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index acd192a98c5..a904afe828d 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -13270,7 +13270,17 @@ release_scratch_register_on_entry (struct scratch_reg *sr)
+     }
+ }
+ 
+-#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
++/* Return the probing interval for -fstack-clash-protection.  */
++
++static HOST_WIDE_INT
++get_probe_interval (void)
++{
++  if (flag_stack_clash_protection)
++    return (HOST_WIDE_INT_1U
++	    << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL));
++  else
++    return (HOST_WIDE_INT_1U << STACK_CHECK_PROBE_INTERVAL_EXP);
++}
+ 
+ /* Emit code to adjust the stack pointer by SIZE bytes while probing it.
+ 
+@@ -13339,8 +13349,7 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+   /* We're allocating a large enough stack frame that we need to
+      emit probes.  Either emit them inline or in a loop depending
+      on the size.  */
+-  HOST_WIDE_INT probe_interval
+-    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  HOST_WIDE_INT probe_interval = get_probe_interval ();
+   if (size <= 4 * probe_interval)
+     {
+       HOST_WIDE_INT i;
+@@ -13349,7 +13358,7 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+ 	  /* Allocate PROBE_INTERVAL bytes.  */
+ 	  rtx insn
+ 	    = pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+-					 GEN_INT (-PROBE_INTERVAL), -1,
++					 GEN_INT (-probe_interval), -1,
+ 					 m->fs.cfa_reg == stack_pointer_rtx);
+ 	  add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
+ 
+@@ -13442,7 +13451,7 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+      that's the easy case.  The run-time loop is made up of 9 insns in the
+      generic case while the compile-time loop is made up of 3+2*(n-1) insns
+      for n # of intervals.  */
+-  if (size <= 4 * PROBE_INTERVAL)
++  if (size <= 4 * get_probe_interval ())
+     {
+       HOST_WIDE_INT i, adjust;
+       bool first_probe = true;
+@@ -13451,15 +13460,15 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+ 	 values of N from 1 until it exceeds SIZE.  If only one probe is
+ 	 needed, this will not generate any code.  Then adjust and probe
+ 	 to PROBE_INTERVAL + SIZE.  */
+-      for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
++      for (i = get_probe_interval (); i < size; i += get_probe_interval ())
+ 	{
+ 	  if (first_probe)
+ 	    {
+-	      adjust = 2 * PROBE_INTERVAL + dope;
++	      adjust = 2 * get_probe_interval () + dope;
+ 	      first_probe = false;
+ 	    }
+ 	  else
+-	    adjust = PROBE_INTERVAL;
++	    adjust = get_probe_interval ();
+ 
+ 	  emit_insn (gen_rtx_SET (stack_pointer_rtx,
+ 				  plus_constant (Pmode, stack_pointer_rtx,
+@@ -13468,9 +13477,9 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+ 	}
+ 
+       if (first_probe)
+-	adjust = size + PROBE_INTERVAL + dope;
++	adjust = size + get_probe_interval () + dope;
+       else
+-        adjust = size + PROBE_INTERVAL - i;
++        adjust = size + get_probe_interval () - i;
+ 
+       emit_insn (gen_rtx_SET (stack_pointer_rtx,
+ 			      plus_constant (Pmode, stack_pointer_rtx,
+@@ -13480,7 +13489,8 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+       /* Adjust back to account for the additional first interval.  */
+       last = emit_insn (gen_rtx_SET (stack_pointer_rtx,
+ 				     plus_constant (Pmode, stack_pointer_rtx,
+-						    PROBE_INTERVAL + dope)));
++						    (get_probe_interval ()
++						     + dope))));
+     }
+ 
+   /* Otherwise, do the same as above, but in a loop.  Note that we must be
+@@ -13498,7 +13508,7 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+ 
+       /* Step 1: round SIZE to the previous multiple of the interval.  */
+ 
+-      rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
++      rounded_size = ROUND_DOWN (size, get_probe_interval ());
+ 
+ 
+       /* Step 2: compute initial and final value of the loop counter.  */
+@@ -13506,7 +13516,7 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+       /* SP = SP_0 + PROBE_INTERVAL.  */
+       emit_insn (gen_rtx_SET (stack_pointer_rtx,
+ 			      plus_constant (Pmode, stack_pointer_rtx,
+-					     - (PROBE_INTERVAL + dope))));
++					     - (get_probe_interval () + dope))));
+ 
+       /* LAST_ADDR = SP_0 + PROBE_INTERVAL + ROUNDED_SIZE.  */
+       if (rounded_size <= (HOST_WIDE_INT_1 << 31))
+@@ -13551,7 +13561,8 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+       /* Adjust back to account for the additional first interval.  */
+       last = emit_insn (gen_rtx_SET (stack_pointer_rtx,
+ 				     plus_constant (Pmode, stack_pointer_rtx,
+-						    PROBE_INTERVAL + dope)));
++						    (get_probe_interval ()
++						     + dope))));
+ 
+       release_scratch_register_on_entry (&sr);
+     }
+@@ -13568,7 +13579,7 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
+       XVECEXP (expr, 0, 1)
+ 	= gen_rtx_SET (stack_pointer_rtx,
+ 		       plus_constant (Pmode, stack_pointer_rtx,
+-				      PROBE_INTERVAL + dope + size));
++				      get_probe_interval () + dope + size));
+       add_reg_note (last, REG_FRAME_RELATED_EXPR, expr);
+       RTX_FRAME_RELATED_P (last) = 1;
+ 
+@@ -13595,7 +13606,7 @@ output_adjust_stack_and_probe (rtx reg)
+ 
+   /* SP = SP + PROBE_INTERVAL.  */
+   xops[0] = stack_pointer_rtx;
+-  xops[1] = GEN_INT (PROBE_INTERVAL);
++  xops[1] = GEN_INT (get_probe_interval ());
+   output_asm_insn ("sub%z0\t{%1, %0|%0, %1}", xops);
+ 
+   /* Probe at SP.  */
+@@ -13625,14 +13636,14 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+      that's the easy case.  The run-time loop is made up of 6 insns in the
+      generic case while the compile-time loop is made up of n insns for n #
+      of intervals.  */
+-  if (size <= 6 * PROBE_INTERVAL)
++  if (size <= 6 * get_probe_interval ())
+     {
+       HOST_WIDE_INT i;
+ 
+       /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
+ 	 it exceeds SIZE.  If only one probe is needed, this will not
+ 	 generate any code.  Then probe at FIRST + SIZE.  */
+-      for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
++      for (i = get_probe_interval (); i < size; i += get_probe_interval ())
+ 	emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ 					 -(first + i)));
+ 
+@@ -13655,7 +13666,7 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+ 
+       /* Step 1: round SIZE to the previous multiple of the interval.  */
+ 
+-      rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
++      rounded_size = ROUND_DOWN (size, get_probe_interval ());
+ 
+ 
+       /* Step 2: compute initial and final value of the loop counter.  */
+@@ -13716,7 +13727,7 @@ output_probe_stack_range (rtx reg, rtx end)
+ 
+   /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL.  */
+   xops[0] = reg;
+-  xops[1] = GEN_INT (PROBE_INTERVAL);
++  xops[1] = GEN_INT (get_probe_interval ());
+   output_asm_insn ("sub%z0\t{%1, %0|%0, %1}", xops);
+ 
+   /* Probe at TEST_ADDR.  */
+@@ -14194,7 +14205,7 @@ ix86_expand_prologue (void)
+       else if (STACK_CHECK_MOVING_SP)
+ 	{
+ 	  if (!(crtl->is_leaf && !cfun->calls_alloca
+-		&& allocate <= PROBE_INTERVAL))
++		&& allocate <= get_probe_interval ()))
+ 	    {
+ 	      ix86_adjust_stack_and_probe (allocate);
+ 	      allocate = 0;
+@@ -14211,7 +14222,7 @@ ix86_expand_prologue (void)
+ 	    {
+ 	      if (crtl->is_leaf && !cfun->calls_alloca)
+ 		{
+-		  if (size > PROBE_INTERVAL)
++		  if (size > get_probe_interval ())
+ 		    ix86_emit_probe_stack_range (0, size);
+ 		}
+ 	      else
+@@ -14222,7 +14233,7 @@ ix86_expand_prologue (void)
+ 	    {
+ 	      if (crtl->is_leaf && !cfun->calls_alloca)
+ 		{
+-		  if (size > PROBE_INTERVAL
++		  if (size > get_probe_interval ()
+ 		      && size > get_stack_check_protect ())
+ 		    ix86_emit_probe_stack_range (get_stack_check_protect (),
+ 						 size - get_stack_check_protect ());
+diff --git a/gcc/testsuite/gcc.dg/pr82788.c b/gcc/testsuite/gcc.dg/pr82788.c
+new file mode 100644
+index 00000000000..a8f628fd7f6
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr82788.c
+@@ -0,0 +1,4 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-probe-interval=10 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++int main() { int a[1442]; return 0;}

diff --git a/gcc7-rh1512529-14.patch b/gcc7-rh1512529-14.patch
new file mode 100644
index 0000000..b79edf8
--- /dev/null
+++ b/gcc7-rh1512529-14.patch
@@ -0,0 +1,43 @@
+commit 799fb6fee433891510ab613a024450c926cdb4b3
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Nov 15 06:30:31 2017 +0000
+
+            * explow.c (anti_adjust_stack_and_probe_stack_clash): Avoid probing
+            the red zone for stack_clash_protection_final_dynamic_probe targets
+            when the total dynamic stack size is zero bytes.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254753 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/explow.c b/gcc/explow.c
+index 6af6355fe30..53c4a6d7db9 100644
+--- a/gcc/explow.c
++++ b/gcc/explow.c
+@@ -1978,6 +1978,13 @@ anti_adjust_stack_and_probe_stack_clash (rtx size)
+   if (size != CONST0_RTX (Pmode)
+       && targetm.stack_clash_protection_final_dynamic_probe (residual))
+     {
++      /* SIZE could be zero at runtime and in that case *sp could hold
++	 live data.  Furthermore, we don't want to probe into the red
++	 zone.
++
++	 Go ahead and just guard a probe at *sp on SIZE != 0 at runtime
++	 if SIZE is not a compile time constant.  */
++
+       /* Ideally we would just probe at *sp.  However, if SIZE is not
+ 	 a compile-time constant, but is zero at runtime, then *sp
+ 	 might hold live data.  So probe at *sp if we know that
+@@ -1990,9 +1997,12 @@ anti_adjust_stack_and_probe_stack_clash (rtx size)
+ 	}
+       else
+ 	{
+-	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+-					   -GET_MODE_SIZE (word_mode)));
++	  rtx label = gen_label_rtx ();
++	  emit_cmp_and_jump_insns (size, CONST0_RTX (GET_MODE (size)),
++				   EQ, NULL_RTX, Pmode, 1, label);
++	  emit_stack_probe (stack_pointer_rtx);
+ 	  emit_insn (gen_blockage ());
++	  emit_label (label);
+ 	}
+     }
+ }

diff --git a/gcc7-rh1512529-15.patch b/gcc7-rh1512529-15.patch
new file mode 100644
index 0000000..90f7afd
--- /dev/null
+++ b/gcc7-rh1512529-15.patch
@@ -0,0 +1,46 @@
+commit df7f99d5297f3c592401d7312c481578a8a62991
+Author: Jeff Law <law@redhat.com>
+Date:   Wed Nov 22 11:55:10 2017 -0700
+
+               * gcc.dg/stack-check-5.c: Skip with -fstack-protector.
+                * gcc.dg/stack-check-6.c: Likewise.
+                * gcc.dg/stack-check-6a.c: Likewise.
+
+diff --git a/gcc/testsuite/gcc.dg/stack-check-5.c b/gcc/testsuite/gcc.dg/stack-check-5.c
+index 3178f5d8ce5..dd9f8dbf607 100644
+--- a/gcc/testsuite/gcc.dg/stack-check-5.c
++++ b/gcc/testsuite/gcc.dg/stack-check-5.c
+@@ -1,6 +1,8 @@
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
+ /* { dg-require-effective-target supports_stack_clash_protection } */
++/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */
++
+ 
+ 
+ /* Otherwise the S/390 back-end might save the stack pointer in f2 ()
+diff --git a/gcc/testsuite/gcc.dg/stack-check-6.c b/gcc/testsuite/gcc.dg/stack-check-6.c
+index ad2021c9037..83559c5533c 100644
+--- a/gcc/testsuite/gcc.dg/stack-check-6.c
++++ b/gcc/testsuite/gcc.dg/stack-check-6.c
+@@ -1,6 +1,8 @@
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
+ /* { dg-require-effective-target supports_stack_clash_protection } */
++/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */
++
+ 
+ 
+ extern void foo (char *);
+diff --git a/gcc/testsuite/gcc.dg/stack-check-6a.c b/gcc/testsuite/gcc.dg/stack-check-6a.c
+index 6f8e7128921..a1a2acbd6bd 100644
+--- a/gcc/testsuite/gcc.dg/stack-check-6a.c
++++ b/gcc/testsuite/gcc.dg/stack-check-6a.c
+@@ -4,6 +4,7 @@
+ /* { dg-do compile  } */
+ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=16" } */
+ /* { dg-require-effective-target supports_stack_clash_protection  } */
++/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */
+ 
+ #include "stack-check-6.c"
+ 

diff --git a/gcc7-rh1512529-16.patch b/gcc7-rh1512529-16.patch
new file mode 100644
index 0000000..a44227f
--- /dev/null
+++ b/gcc7-rh1512529-16.patch
@@ -0,0 +1,473 @@
+commit dafbd9e0c347cde6d8192f374787f5dbee4aed89
+Author: Jeff Law <law@redhat.com>
+Date:   Wed Nov 22 12:01:56 2017 -0700
+
+    aarch64 support
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 75c12f1de65..d7100c36664 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -2747,7 +2747,14 @@ aarch64_output_probe_stack_range (rtx reg1, rtx reg2)
+   output_asm_insn ("sub\t%0, %0, %1", xops);
+ 
+   /* Probe at TEST_ADDR.  */
+-  output_asm_insn ("str\txzr, [%0]", xops);
++  if (flag_stack_clash_protection)
++    {
++      gcc_assert (xops[0] == stack_pointer_rtx);
++      xops[1] = GEN_INT (PROBE_INTERVAL - 8);
++      output_asm_insn ("str\txzr, [%0, %1]", xops);
++    }
++  else
++    output_asm_insn ("str\txzr, [%0]", xops);
+ 
+   /* Test if TEST_ADDR == LAST_ADDR.  */
+   xops[1] = reg2;
+@@ -3511,6 +3518,125 @@ aarch64_set_handled_components (sbitmap components)
+       cfun->machine->reg_is_wrapped_separately[regno] = true;
+ }
+ 
++/* Allocate SIZE bytes of stack space using SCRATCH_REG as a scratch
++   register.  */
++
++static void
++aarch64_allocate_and_probe_stack_space (int scratchreg, HOST_WIDE_INT size)
++{
++  HOST_WIDE_INT probe_interval
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  HOST_WIDE_INT guard_size
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
++  HOST_WIDE_INT guard_used_by_caller = 1024;
++
++  /* SIZE should be large enough to require probing here.  ie, it
++     must be larger than GUARD_SIZE - GUARD_USED_BY_CALLER.
++
++     We can allocate GUARD_SIZE - GUARD_USED_BY_CALLER as a single chunk
++     without any probing.  */
++  gcc_assert (size >= guard_size - guard_used_by_caller);
++  aarch64_sub_sp (scratchreg, guard_size - guard_used_by_caller, true);
++  HOST_WIDE_INT orig_size = size;
++  size -= (guard_size - guard_used_by_caller);
++
++  HOST_WIDE_INT rounded_size = size & -probe_interval;
++  HOST_WIDE_INT residual = size - rounded_size;
++
++  /* We can handle a small number of allocations/probes inline.  Otherwise
++     punt to a loop.  */
++  if (rounded_size && rounded_size <= 4 * probe_interval)
++    {
++      /* We don't use aarch64_sub_sp here because we don't want to
++	 repeatedly load SCRATCHREG.  */
++      rtx scratch_rtx = gen_rtx_REG (Pmode, scratchreg);
++      if (probe_interval > ARITH_FACTOR)
++	emit_move_insn (scratch_rtx, GEN_INT (-probe_interval));
++      else
++	scratch_rtx = GEN_INT (-probe_interval);
++
++      for (HOST_WIDE_INT i = 0; i < rounded_size; i += probe_interval)
++	{
++	  rtx_insn *insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
++						     scratch_rtx));
++          add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
++
++	  if (probe_interval > ARITH_FACTOR)
++	    {
++	      RTX_FRAME_RELATED_P (insn) = 1;
++	      rtx adj = plus_constant (Pmode, stack_pointer_rtx, -probe_interval);
++	      add_reg_note (insn, REG_CFA_ADJUST_CFA,
++			    gen_rtx_SET (stack_pointer_rtx, adj));
++	    }
++
++	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++					   (probe_interval
++					    - GET_MODE_SIZE (word_mode))));
++	  emit_insn (gen_blockage ());
++	}
++      dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
++    }
++  else if (rounded_size)
++    {
++      /* Compute the ending address.  */
++      rtx temp = gen_rtx_REG (word_mode, scratchreg);
++      emit_move_insn (temp, GEN_INT (-rounded_size));
++      rtx_insn *insn
++	 = emit_insn (gen_add3_insn (temp, stack_pointer_rtx, temp));
++
++      /* For the initial allocation, we don't have a frame pointer
++	 set up, so we always need CFI notes.  If we're doing the
++	 final allocation, then we may have a frame pointer, in which
++	 case it is the CFA, otherwise we need CFI notes.
++
++	 We can determine which allocation we are doing by looking at
++	 the temporary register.  IP0 is the initial allocation, IP1
++	 is the final allocation.  */
++      if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
++	{
++	  /* We want the CFA independent of the stack pointer for the
++	     duration of the loop.  */
++	  add_reg_note (insn, REG_CFA_DEF_CFA,
++			plus_constant (Pmode, temp,
++				       (rounded_size + (orig_size - size))));
++	  RTX_FRAME_RELATED_P (insn) = 1;
++	}
++
++      /* This allocates and probes the stack.
++
++	 It also probes at a 4k interval regardless of the value of
++	 PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL.  */
++      insn = emit_insn (gen_probe_stack_range (stack_pointer_rtx,
++					       stack_pointer_rtx, temp));
++
++      /* Now reset the CFA register if needed.  */
++      if (scratchreg == IP0_REGNUM || !frame_pointer_needed)
++	{
++	  add_reg_note (insn, REG_CFA_DEF_CFA,
++			plus_constant (Pmode, stack_pointer_rtx,
++				       (rounded_size + (orig_size - size))));
++	  RTX_FRAME_RELATED_P (insn) = 1;
++	}
++
++      emit_insn (gen_blockage ());
++      dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
++    }
++  else
++    dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size);
++
++  /* Handle any residuals.
++     Note that any residual must be probed.  */
++  if (residual)
++    {
++      aarch64_sub_sp (scratchreg, residual, true);
++      add_reg_note (get_last_insn (), REG_STACK_CHECK, const0_rtx);
++      emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++				       (residual - GET_MODE_SIZE (word_mode))));
++      emit_insn (gen_blockage ());
++    }
++  return;
++}
++
+ /* AArch64 stack frames generated by this compiler look like:
+ 
+ 	+-------------------------------+
+@@ -3592,7 +3718,54 @@ aarch64_expand_prologue (void)
+ 	aarch64_emit_probe_stack_range (get_stack_check_protect (), frame_size);
+     }
+ 
+-  aarch64_sub_sp (IP0_REGNUM, initial_adjust, true);
++  /* We do not fully protect aarch64 against stack clash style attacks
++     as doing so would be prohibitively expensive with less utility over
++     time as newer compilers are deployed.
++
++     We assume the guard is at least 64k.  Furthermore, we assume that
++     the caller has not pushed the stack pointer more than 1k into
++     the guard.  A caller that pushes the stack pointer than 1k into
++     the guard is considered invalid.
++
++     Note that the caller's ability to push the stack pointer into the
++     guard is a function of the number and size of outgoing arguments and/or
++     dynamic stack allocations due to the mandatory save of the link register
++     in the caller's frame.
++
++     With those assumptions the callee can allocate up to 63k of stack
++     space without probing.
++
++     When probing is needed, we emit a probe at the start of the prologue
++     and every PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes thereafter.
++
++     We have to track how much space has been allocated, but we do not
++     track stores into the stack as implicit probes except for the
++     fp/lr store.  */
++  HOST_WIDE_INT guard_size
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
++  HOST_WIDE_INT guard_used_by_caller = 1024;
++  if (flag_stack_clash_protection)
++    {
++      if (frame_size == 0)
++	dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
++      else if (initial_adjust < guard_size - guard_used_by_caller
++	       && final_adjust < guard_size - guard_used_by_caller)
++	dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++    }
++
++  /* In theory we should never have both an initial adjustment
++     and a callee save adjustment.  Verify that is the case since the
++     code below does not handle it for -fstack-clash-protection.  */
++  gcc_assert (initial_adjust == 0 || callee_adjust == 0);
++
++  /* Only probe if the initial adjustment is larger than the guard
++     less the amount of the guard reserved for use by the caller's
++     outgoing args.  */
++  if (flag_stack_clash_protection
++      && initial_adjust >= guard_size - guard_used_by_caller)
++    aarch64_allocate_and_probe_stack_space (IP0_REGNUM, initial_adjust);
++  else
++    aarch64_sub_sp (IP0_REGNUM, initial_adjust, true);
+ 
+   if (callee_adjust != 0)
+     aarch64_push_regs (reg1, reg2, callee_adjust);
+@@ -3613,7 +3786,30 @@ aarch64_expand_prologue (void)
+ 			     callee_adjust != 0 || frame_pointer_needed);
+   aarch64_save_callee_saves (DFmode, callee_offset, V0_REGNUM, V31_REGNUM,
+ 			     callee_adjust != 0 || frame_pointer_needed);
+-  aarch64_sub_sp (IP1_REGNUM, final_adjust, !frame_pointer_needed);
++
++  /* We may need to probe the final adjustment as well.  */
++  if (flag_stack_clash_protection && final_adjust != 0)
++    {
++      /* First probe if the final adjustment is larger than the guard size
++	 less the amount of the guard reserved for use by the caller's
++	 outgoing args.  */
++      if (final_adjust >= guard_size - guard_used_by_caller)
++	aarch64_allocate_and_probe_stack_space (IP1_REGNUM, final_adjust);
++      else
++	aarch64_sub_sp (IP1_REGNUM, final_adjust, !frame_pointer_needed);
++
++      /* We must also probe if the final adjustment is larger than the guard
++	 that is assumed used by the caller.  This may be sub-optimal.  */
++      if (final_adjust >= guard_used_by_caller)
++	{
++	  if (dump_file)
++	    fprintf (dump_file,
++		     "Stack clash aarch64 large outgoing arg, probing\n");
++	  emit_stack_probe (stack_pointer_rtx);
++	}
++    }
++  else
++    aarch64_sub_sp (IP1_REGNUM, final_adjust, !frame_pointer_needed);
+ }
+ 
+ /* Return TRUE if we can use a simple_return insn.
+@@ -3679,7 +3875,11 @@ aarch64_expand_epilogue (bool for_sibcall)
+       RTX_FRAME_RELATED_P (insn) = callee_adjust == 0;
+     }
+   else
+-    aarch64_add_sp (IP1_REGNUM, final_adjust, df_regs_ever_live_p (IP1_REGNUM));
++    aarch64_add_sp (IP1_REGNUM, final_adjust,
++		    /* A stack clash protection prologue may not have
++		       left IP1_REGNUM in a usable state.  */
++		    (flag_stack_clash_protection
++		     || df_regs_ever_live_p (IP1_REGNUM)));
+ 
+   aarch64_restore_callee_saves (DImode, callee_offset, R0_REGNUM, R30_REGNUM,
+ 				callee_adjust != 0, &cfi_ops);
+@@ -3702,7 +3902,11 @@ aarch64_expand_epilogue (bool for_sibcall)
+       cfi_ops = NULL;
+     }
+ 
+-  aarch64_add_sp (IP0_REGNUM, initial_adjust, df_regs_ever_live_p (IP0_REGNUM));
++  /* A stack clash protection prologue may not have left IP0_REGNUM
++     in a usable state.  */
++  aarch64_add_sp (IP0_REGNUM, initial_adjust,
++		  (flag_stack_clash_protection
++		   || df_regs_ever_live_p (IP0_REGNUM)));
+ 
+   if (cfi_ops)
+     {
+@@ -8696,6 +8900,12 @@ aarch64_override_options_internal (struct gcc_options *opts)
+ 			   opts->x_param_values,
+ 			   global_options_set.x_param_values);
+ 
++  /* We assume the guard page is 64k.  */
++  maybe_set_param_value (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE,
++			 16,
++			 opts->x_param_values,
++			 global_options_set.x_param_values);
++
+   aarch64_override_options_after_change_1 (opts);
+ }
+ 
+@@ -14726,6 +14936,28 @@ aarch64_sched_can_speculate_insn (rtx_insn *insn)
+     }
+ }
+ 
++/* It has been decided that to allow up to 1kb of outgoing argument
++   space to be allocated w/o probing.  If more than 1kb of outgoing
++   argment space is allocated, then it must be probed and the last
++   probe must occur no more than 1kbyte away from the end of the
++   allocated space.
++
++   This implies that the residual part of an alloca allocation may
++   need probing in cases where the generic code might not otherwise
++   think a probe is needed.
++
++   This target hook returns TRUE when allocating RESIDUAL bytes of
++   alloca space requires an additional probe, otherwise FALSE is
++   returned.  */
++
++static bool
++aarch64_stack_clash_protection_final_dynamic_probe (rtx residual)
++{
++  return (residual == CONST0_RTX (Pmode)
++	  || GET_CODE (residual) != CONST_INT
++	  || INTVAL (residual) >= 1024);
++}
++
+ /* Target-specific selftests.  */
+ 
+ #if CHECKING_P
+@@ -15154,6 +15386,10 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
+ #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4
+ 
++#undef TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE
++#define TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE \
++  aarch64_stack_clash_protection_final_dynamic_probe
++
+ #if CHECKING_P
+ #undef TARGET_RUN_TARGET_SELFTESTS
+ #define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 51368e29f2d..09b353d7470 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -5413,7 +5413,7 @@
+ )
+ 
+ (define_insn "probe_stack_range"
+-  [(set (match_operand:DI 0 "register_operand" "=r")
++  [(set (match_operand:DI 0 "register_operand" "=rk")
+ 	(unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
+ 			     (match_operand:DI 2 "register_operand" "r")]
+ 			      UNSPECV_PROBE_STACK_RANGE))]
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-12.c b/gcc/testsuite/gcc.target/aarch64/stack-check-12.c
+new file mode 100644
+index 00000000000..2ce38483b6b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-12.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++extern void arf (unsigned long int *, unsigned long int *);
++void
++frob ()
++{
++  unsigned long int num[1000];
++  unsigned long int den[1000];
++  arf (den, num);
++}
++
++/* This verifies that the scheduler did not break the dependencies
++   by adjusting the offsets within the probe and that the scheduler
++   did not reorder around the stack probes.  */
++/* { dg-final { scan-assembler-times "sub\\tsp, sp, #4096\\n\\tstr\\txzr, .sp, 4088." 3 } } */
++
++
++
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-13.c b/gcc/testsuite/gcc.target/aarch64/stack-check-13.c
+new file mode 100644
+index 00000000000..d8886835989
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-13.c
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++#define ARG32(X) X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
++#define ARG192(X) ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X)
++void out1(ARG192(__int128));
++int t1(int);
++
++int t3(int x)
++{
++  if (x < 1000)
++    return t1 (x) + 1;
++
++  out1 (ARG192(1));
++  return 0;
++}
++
++
++
++/* This test creates a large (> 1k) outgoing argument area that needs
++   to be probed.  We don't test the exact size of the space or the
++   exact offset to make the test a little less sensitive to trivial
++   output changes.  */
++/* { dg-final { scan-assembler-times "sub\\tsp, sp, #....\\n\\tstr\\txzr, \\\[sp" 1 } } */
++
++
++
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-14.c b/gcc/testsuite/gcc.target/aarch64/stack-check-14.c
+new file mode 100644
+index 00000000000..59ffe01376d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-14.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++int t1(int);
++
++int t2(int x)
++{
++  char *p = __builtin_alloca (4050);
++  x = t1 (x);
++  return p[x];
++}
++
++
++/* This test has a constant sized alloca that is smaller than the
++   probe interval.  But it actually requires two probes instead
++   of one because of the optimistic assumptions we made in the
++   aarch64 prologue code WRT probing state. 
++
++   The form can change quite a bit so we just check for two
++   probes without looking at the actual address.  */
++/* { dg-final { scan-assembler-times "str\\txzr," 2 } } */
++
++
++
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-15.c b/gcc/testsuite/gcc.target/aarch64/stack-check-15.c
+new file mode 100644
+index 00000000000..e06db6dc2f0
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-15.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++int t1(int);
++
++int t2(int x)
++{
++  char *p = __builtin_alloca (x);
++  x = t1 (x);
++  return p[x];
++}
++
++
++/* This test has a variable sized alloca.  It requires 3 probes.
++   One in the loop, one for the residual and at the end of the
++   alloca area. 
++
++   The form can change quite a bit so we just check for two
++   probes without looking at the actual address.  */
++/* { dg-final { scan-assembler-times "str\\txzr," 3 } } */
++
++
++
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index 02eb2066393..5431c236aa1 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8384,14 +8384,9 @@ proc check_effective_target_arm_coproc4_ok { } {
+ # 
+ proc check_effective_target_supports_stack_clash_protection { } {
+ 
+-   # Temporary until the target bits are fully ACK'd.
+-#  if { [istarget aarch*-*-*] } {
+-#	return 1
+-#  }
+-
+     if { [istarget x86_64-*-*] || [istarget i?86-*-*] 
+ 	  || [istarget powerpc*-*-*] || [istarget rs6000*-*-*]
+-	  || [istarget s390*-*-*] } {
++	  || [istarget aarch64*-**] || [istarget s390*-*-*] } {
+ 	return 1
+     }
+   return 0

diff --git a/gcc7-rh1512529-17.patch b/gcc7-rh1512529-17.patch
new file mode 100644
index 0000000..e3b813c
--- /dev/null
+++ b/gcc7-rh1512529-17.patch
@@ -0,0 +1,40 @@
+commit 5ed5d56d36fc50627edf537c75afa0fdf6ba4f5d
+Author: Jeff Law <law@redhat.com>
+Date:   Wed Nov 22 12:02:50 2017 -0700
+
+    2017-10-31  Segher Boessenkool  <segher@kernel.crsahing.org>
+    
+           PR target/82674
+           * config/rs6000/rs6000.md (allocate_stack): Force update interval
+           into a register if it does not fit into an immediate offset field.
+
+diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
+index 843148e9703..4b9732a78ec 100644
+--- a/gcc/config/rs6000/rs6000.md
++++ b/gcc/config/rs6000/rs6000.md
+@@ -10450,6 +10450,9 @@
+ 	{
+ 	  rtx loop_lab, end_loop;
+ 	  bool rotated = CONST_INT_P (rounded_size);
++	  rtx update = GEN_INT (-probe_interval);
++	  if (probe_interval > 32768)
++	    update = force_reg (Pmode, update);
+ 
+ 	  emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop,
+ 							last_addr, rotated);
+@@ -10457,13 +10460,11 @@
+ 	  if (Pmode == SImode)
+ 	    emit_insn (gen_movsi_update_stack (stack_pointer_rtx,
+ 					       stack_pointer_rtx,
+-					       GEN_INT (-probe_interval),
+-					       chain));
++					       update, chain));
+ 	  else
+ 	    emit_insn (gen_movdi_di_update_stack (stack_pointer_rtx,
+ 					          stack_pointer_rtx,
+-					          GEN_INT (-probe_interval),
+-					          chain));
++					          update, chain));
+ 	  emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop,
+ 						      last_addr, rotated);
+ 	}

diff --git a/gcc7-rh1512529-18.patch b/gcc7-rh1512529-18.patch
new file mode 100644
index 0000000..0aaf01f
--- /dev/null
+++ b/gcc7-rh1512529-18.patch
@@ -0,0 +1,13 @@
+diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
+index 5b6f18602e7..b5e96a1a0e4 100644
+--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
++++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
+@@ -1262,7 +1262,7 @@ struct __sanitizer_esr_context {
+ 
+ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
+   static const u32 kEsrMagic = 0x45535201;
+-  u8 *aux = ucontext->uc_mcontext.__reserved;
++  u8 *aux = ucontext->uc_mcontext.__glibc_reserved1;
+   while (true) {
+     _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
+     if (ctx->size == 0) break;

diff --git a/gcc7-rh1512529-2.patch b/gcc7-rh1512529-2.patch
new file mode 100644
index 0000000..e334b5c
--- /dev/null
+++ b/gcc7-rh1512529-2.patch
@@ -0,0 +1,735 @@
+commit bed27844b80e17ad786028a0a82c7d47990d15bb
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 05:05:12 2017 +0000
+
+    2017-09-18  Jeff Law  <law@redhat.com>
+    
+            * explow.c: Include "params.h".
+            (anti_adjust_stack_and_probe_stack_clash): New function.
+            (get_stack_check_protect): Likewise.
+            (compute_stack_clash_protection_loop_data): Likewise.
+            (emit_stack_clash_protection_loop_start): Likewise.
+            (emit_stack_clash_protection_loop_end): Likewise.
+            (allocate_dynamic_stack_space): Use get_stack_check_protect.
+            Use anti_adjust_stack_and_probe_stack_clash.
+            * explow.h (compute_stack_clash_protection_loop_data): Prototype.
+            (emit_stack_clash_protection_loop_start): Likewise.
+            (emit_stack_clash_protection_loop_end): Likewise.
+            * rtl.h (get_stack_check_protect): Prototype.
+            * target.def (stack_clash_protection_final_dynamic_probe): New hook.
+            * targhooks.c (default_stack_clash_protection_final_dynamic_probe): New.
+            * targhooks.h (default_stack_clash_protection_final_dynamic_probe):
+            Prototype.
+            * doc/tm.texi.in (TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE):
+            Add @hook.
+            * doc/tm.texi: Rebuilt.
+            * config/aarch64/aarch64.c (aarch64_expand_prologue): Use
+            get_stack_check_protect.
+            * config/alpha/alpha.c (alpha_expand_prologue): Likewise.
+            * config/arm/arm.c (arm_expand_prologue): Likewise.
+            (arm_frame_pointer_required): Likewise.
+            * config/i386/i386.c (ix86_expand_prologue): Likewise.
+            * config/ia64/ia64.c (ia64_expand_prologue): Likewise.
+            * config/mips/mips.c (mips_expand_prologue): Likewise.
+            * config/powerpcspe/powerpcspe.c (rs6000_emit_prologue): Likewise.
+            * config/rs6000/rs6000.c (rs6000_emit_prologue): Likewise.
+            * config/sparc/sparc.c (sparc_expand_prologue): Likewise.
+            (sparc_flat_expand_prologue): Likewise.
+    
+            * gcc.dg/stack-check-3.c: New test.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252995 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 1bd010be756..75c12f1de65 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -3582,12 +3582,14 @@ aarch64_expand_prologue (void)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (frame_size > PROBE_INTERVAL && frame_size > STACK_CHECK_PROTECT)
+-	    aarch64_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					    frame_size - STACK_CHECK_PROTECT);
++	  if (frame_size > PROBE_INTERVAL
++	      && frame_size > get_stack_check_protect ())
++	    aarch64_emit_probe_stack_range (get_stack_check_protect (),
++					    (frame_size
++					     - get_stack_check_protect ()));
+ 	}
+       else if (frame_size > 0)
+-	aarch64_emit_probe_stack_range (STACK_CHECK_PROTECT, frame_size);
++	aarch64_emit_probe_stack_range (get_stack_check_protect (), frame_size);
+     }
+ 
+   aarch64_sub_sp (IP0_REGNUM, initial_adjust, true);
+diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
+index 00a69c1a08d..91f3d7cfbeb 100644
+--- a/gcc/config/alpha/alpha.c
++++ b/gcc/config/alpha/alpha.c
+@@ -7741,7 +7741,7 @@ alpha_expand_prologue (void)
+ 
+   probed_size = frame_size;
+   if (flag_stack_check)
+-    probed_size += STACK_CHECK_PROTECT;
++    probed_size += get_stack_check_protect ();
+ 
+   if (probed_size <= 32768)
+     {
+diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
+index 1ded0d2a17d..242d7c792fe 100644
+--- a/gcc/config/arm/arm.c
++++ b/gcc/config/arm/arm.c
+@@ -21604,13 +21604,13 @@ arm_expand_prologue (void)
+ 
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    arm_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					size - STACK_CHECK_PROTECT,
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    arm_emit_probe_stack_range (get_stack_check_protect (),
++					size - get_stack_check_protect (),
+ 					regno, live_regs_mask);
+ 	}
+       else if (size > 0)
+-	arm_emit_probe_stack_range (STACK_CHECK_PROTECT, size,
++	arm_emit_probe_stack_range (get_stack_check_protect (), size,
+ 				    regno, live_regs_mask);
+     }
+ 
+@@ -27751,7 +27751,7 @@ arm_frame_pointer_required (void)
+ 	{
+ 	  /* We don't have the final size of the frame so adjust.  */
+ 	  size += 32 * UNITS_PER_WORD;
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
+ 	    return true;
+ 	}
+       else
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 2d163797ba0..60bab9a26a6 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -14037,7 +14037,7 @@ ix86_expand_prologue (void)
+ 	  HOST_WIDE_INT size = allocate;
+ 
+ 	  if (TARGET_64BIT && size >= HOST_WIDE_INT_C (0x80000000))
+-	    size = 0x80000000 - STACK_CHECK_PROTECT - 1;
++	    size = 0x80000000 - get_stack_check_protect () - 1;
+ 
+ 	  if (TARGET_STACK_PROBE)
+ 	    {
+@@ -14047,18 +14047,20 @@ ix86_expand_prologue (void)
+ 		    ix86_emit_probe_stack_range (0, size);
+ 		}
+ 	      else
+-		ix86_emit_probe_stack_range (0, size + STACK_CHECK_PROTECT);
++		ix86_emit_probe_stack_range (0,
++					     size + get_stack_check_protect ());
+ 	    }
+ 	  else
+ 	    {
+ 	      if (crtl->is_leaf && !cfun->calls_alloca)
+ 		{
+-		  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-		    ix86_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-						 size - STACK_CHECK_PROTECT);
++		  if (size > PROBE_INTERVAL
++		      && size > get_stack_check_protect ())
++		    ix86_emit_probe_stack_range (get_stack_check_protect (),
++						 size - get_stack_check_protect ());
+ 		}
+ 	      else
+-		ix86_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
++		ix86_emit_probe_stack_range (get_stack_check_protect (), size);
+ 	    }
+ 	}
+     }
+diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
+index a9f479b6e5c..17d6b3318a6 100644
+--- a/gcc/config/ia64/ia64.c
++++ b/gcc/config/ia64/ia64.c
+@@ -3476,15 +3476,16 @@ ia64_expand_prologue (void)
+ 
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    ia64_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					 size - STACK_CHECK_PROTECT,
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    ia64_emit_probe_stack_range (get_stack_check_protect (),
++					 size - get_stack_check_protect (),
+ 					 bs_size);
+-	  else if (size + bs_size > STACK_CHECK_PROTECT)
+-	    ia64_emit_probe_stack_range (STACK_CHECK_PROTECT, 0, bs_size);
++	  else if (size + bs_size > get_stack_check_protect ())
++	    ia64_emit_probe_stack_range (get_stack_check_protect (),
++					 0, bs_size);
+ 	}
+       else if (size + bs_size > 0)
+-	ia64_emit_probe_stack_range (STACK_CHECK_PROTECT, size, bs_size);
++	ia64_emit_probe_stack_range (get_stack_check_protect (), size, bs_size);
+     }
+ 
+   if (dump_file) 
+diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
+index 6bfd86a07af..7d85ce7055a 100644
+--- a/gcc/config/mips/mips.c
++++ b/gcc/config/mips/mips.c
+@@ -12081,12 +12081,12 @@ mips_expand_prologue (void)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    mips_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					 size - STACK_CHECK_PROTECT);
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    mips_emit_probe_stack_range (get_stack_check_protect (),
++					 size - get_stack_check_protect ());
+ 	}
+       else if (size > 0)
+-	mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
++	mips_emit_probe_stack_range (get_stack_check_protect (), size);
+     }
+ 
+   /* Save the registers.  Allocate up to MIPS_MAX_FIRST_STACK_STEP
+diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
+index 66496a1f80f..1836e1d147d 100644
+--- a/gcc/config/rs6000/rs6000.c
++++ b/gcc/config/rs6000/rs6000.c
+@@ -29294,12 +29294,12 @@ rs6000_emit_prologue (void)
+ 
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					   size - STACK_CHECK_PROTECT);
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    rs6000_emit_probe_stack_range (get_stack_check_protect (),
++					   size - get_stack_check_protect ());
+ 	}
+       else if (size > 0)
+-	rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
++	rs6000_emit_probe_stack_range (get_stack_check_protect (), size);
+     }
+ 
+   if (TARGET_FIX_AND_CONTINUE)
+diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
+index 83ca1dcc617..b32bb9859e1 100644
+--- a/gcc/config/sparc/sparc.c
++++ b/gcc/config/sparc/sparc.c
+@@ -5695,12 +5695,12 @@ sparc_expand_prologue (void)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    sparc_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					  size - STACK_CHECK_PROTECT);
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    sparc_emit_probe_stack_range (get_stack_check_protect (),
++					  size - get_stack_check_protect ());
+ 	}
+       else if (size > 0)
+-	sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
++	sparc_emit_probe_stack_range (get_stack_check_protect (), size);
+     }
+ 
+   if (size == 0)
+@@ -5806,12 +5806,12 @@ sparc_flat_expand_prologue (void)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+-	  if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+-	    sparc_emit_probe_stack_range (STACK_CHECK_PROTECT,
+-					  size - STACK_CHECK_PROTECT);
++	  if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
++	    sparc_emit_probe_stack_range (get_stack_check_protect (),
++					  size - get_stack_check_protect ());
+ 	}
+       else if (size > 0)
+-	sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
++	sparc_emit_probe_stack_range (get_stack_check_protect (), size);
+     }
+ 
+   if (sparc_save_local_in_regs_p)
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index c4f2c893c8e..0ba2925a1bd 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -3419,6 +3419,10 @@ GCC computed the default from the values of the above macros and you will
+ normally not need to override that default.
+ @end defmac
+ 
++@deftypefn {Target Hook} bool TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE (rtx @var{residual})
++Some targets make optimistic assumptions about the state of stack probing when they emit their prologues.  On such targets a probe into the end of any dynamically allocated space is likely required for safety against stack clash style attacks.  Define this variable to return nonzero if such a probe is required or zero otherwise.  You need not define this macro if it would always have the value zero.
++@end deftypefn
++
+ @need 2000
+ @node Frame Registers
+ @subsection Registers That Address the Stack Frame
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 1c471d8da35..d31255e86cb 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -2999,6 +2999,8 @@ GCC computed the default from the values of the above macros and you will
+ normally not need to override that default.
+ @end defmac
+ 
++@hook TARGET_STACK_CLASH_PROTECTION_FINAL_DYNAMIC_PROBE
++
+ @need 2000
+ @node Frame Registers
+ @subsection Registers That Address the Stack Frame
+diff --git a/gcc/explow.c b/gcc/explow.c
+index 67cb6ff1513..e7db438b1ec 100644
+--- a/gcc/explow.c
++++ b/gcc/explow.c
+@@ -39,8 +39,11 @@ along with GCC; see the file COPYING3.  If not see
+ #include "expr.h"
+ #include "common/common-target.h"
+ #include "output.h"
++#include "params.h"
++#include "dumpfile.h"
+ 
+ static rtx break_out_memory_refs (rtx);
++static void anti_adjust_stack_and_probe_stack_clash (rtx);
+ 
+ 
+ /* Truncate and perhaps sign-extend C as appropriate for MODE.  */
+@@ -1271,6 +1274,29 @@ get_dynamic_stack_size (rtx *psize, unsigned size_align,
+   *psize = size;
+ }
+ 
++/* Return the number of bytes to "protect" on the stack for -fstack-check.
++
++   "protect" in the context of -fstack-check means how many bytes we
++   should always ensure are available on the stack.  More importantly
++   this is how many bytes are skipped when probing the stack.
++
++   On some targets we want to reuse the -fstack-check prologue support
++   to give a degree of protection against stack clashing style attacks.
++
++   In that scenario we do not want to skip bytes before probing as that
++   would render the stack clash protections useless.
++
++   So we never use STACK_CHECK_PROTECT directly.  Instead we indirect though
++   this helper which allows us to provide different values for
++   -fstack-check and -fstack-clash-protection.  */
++HOST_WIDE_INT
++get_stack_check_protect (void)
++{
++  if (flag_stack_clash_protection)
++    return 0;
++ return STACK_CHECK_PROTECT;
++}
++
+ /* Return an rtx representing the address of an area of memory dynamically
+    pushed on the stack.
+ 
+@@ -1429,7 +1455,7 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
+     probe_stack_range (STACK_OLD_CHECK_PROTECT + STACK_CHECK_MAX_FRAME_SIZE,
+ 		       size);
+   else if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+-    probe_stack_range (STACK_CHECK_PROTECT, size);
++    probe_stack_range (get_stack_check_protect (), size);
+ 
+   /* Don't let anti_adjust_stack emit notes.  */
+   suppress_reg_args_size = true;
+@@ -1482,6 +1508,8 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
+ 
+       if (flag_stack_check && STACK_CHECK_MOVING_SP)
+ 	anti_adjust_stack_and_probe (size, false);
++      else if (flag_stack_clash_protection)
++	anti_adjust_stack_and_probe_stack_clash (size);
+       else
+ 	anti_adjust_stack (size);
+ 
+@@ -1757,6 +1785,219 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
+   emit_insn (gen_blockage ());
+ }
+ 
++/* Compute parameters for stack clash probing a dynamic stack
++   allocation of SIZE bytes.
++
++   We compute ROUNDED_SIZE, LAST_ADDR, RESIDUAL and PROBE_INTERVAL.
++
++   Additionally we conditionally dump the type of probing that will
++   be needed given the values computed.  */
++
++void
++compute_stack_clash_protection_loop_data (rtx *rounded_size, rtx *last_addr,
++					  rtx *residual,
++					  HOST_WIDE_INT *probe_interval,
++					  rtx size)
++{
++  /* Round SIZE down to STACK_CLASH_PROTECTION_PROBE_INTERVAL */
++  *probe_interval
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  *rounded_size = simplify_gen_binary (AND, Pmode, size,
++				        GEN_INT (-*probe_interval));
++
++  /* Compute the value of the stack pointer for the last iteration.
++     It's just SP + ROUNDED_SIZE.  */
++  rtx rounded_size_op = force_operand (*rounded_size, NULL_RTX);
++  *last_addr = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
++					      stack_pointer_rtx,
++					      rounded_size_op),
++			      NULL_RTX);
++
++  /* Compute any residuals not allocated by the loop above.  Residuals
++     are just the ROUNDED_SIZE - SIZE.  */
++  *residual = simplify_gen_binary (MINUS, Pmode, size, *rounded_size);
++
++  /* Dump key information to make writing tests easy.  */
++  if (dump_file)
++    {
++      if (*rounded_size == CONST0_RTX (Pmode))
++	fprintf (dump_file,
++		 "Stack clash skipped dynamic allocation and probing loop.\n");
++      else if (GET_CODE (*rounded_size) == CONST_INT
++	       && INTVAL (*rounded_size) <= 4 * *probe_interval)
++	fprintf (dump_file,
++		 "Stack clash dynamic allocation and probing inline.\n");
++      else if (GET_CODE (*rounded_size) == CONST_INT)
++	fprintf (dump_file,
++		 "Stack clash dynamic allocation and probing in "
++		 "rotated loop.\n");
++      else
++	fprintf (dump_file,
++		 "Stack clash dynamic allocation and probing in loop.\n");
++
++      if (*residual != CONST0_RTX (Pmode))
++	fprintf (dump_file,
++		 "Stack clash dynamic allocation and probing residuals.\n");
++      else
++	fprintf (dump_file,
++		 "Stack clash skipped dynamic allocation and "
++		 "probing residuals.\n");
++    }
++}
++
++/* Emit the start of an allocate/probe loop for stack
++   clash protection.
++
++   LOOP_LAB and END_LAB are returned for use when we emit the
++   end of the loop.
++
++   LAST addr is the value for SP which stops the loop.  */
++void
++emit_stack_clash_protection_probe_loop_start (rtx *loop_lab,
++					      rtx *end_lab,
++					      rtx last_addr,
++					      bool rotated)
++{
++  /* Essentially we want to emit any setup code, the top of loop
++     label and the comparison at the top of the loop.  */
++  *loop_lab = gen_label_rtx ();
++  *end_lab = gen_label_rtx ();
++
++  emit_label (*loop_lab);
++  if (!rotated)
++    emit_cmp_and_jump_insns (stack_pointer_rtx, last_addr, EQ, NULL_RTX,
++			     Pmode, 1, *end_lab);
++}
++
++/* Emit the end of a stack clash probing loop.
++
++   This consists of just the jump back to LOOP_LAB and
++   emitting END_LOOP after the loop.  */
++
++void
++emit_stack_clash_protection_probe_loop_end (rtx loop_lab, rtx end_loop,
++					    rtx last_addr, bool rotated)
++{
++  if (rotated)
++    emit_cmp_and_jump_insns (stack_pointer_rtx, last_addr, NE, NULL_RTX,
++			     Pmode, 1, loop_lab);
++  else
++    emit_jump (loop_lab);
++
++  emit_label (end_loop);
++
++}
++
++/* Adjust the stack pointer by minus SIZE (an rtx for a number of bytes)
++   while probing it.  This pushes when SIZE is positive.  SIZE need not
++   be constant.
++
++   This is subtly different than anti_adjust_stack_and_probe to try and
++   prevent stack-clash attacks
++
++     1. It must assume no knowledge of the probing state, any allocation
++	must probe.
++
++	Consider the case of a 1 byte alloca in a loop.  If the sum of the
++	allocations is large, then this could be used to jump the guard if
++	probes were not emitted.
++
++     2. It never skips probes, whereas anti_adjust_stack_and_probe will
++	skip probes on the first couple PROBE_INTERVALs on the assumption
++	they're done elsewhere.
++
++     3. It only allocates and probes SIZE bytes, it does not need to
++	allocate/probe beyond that because this probing style does not
++	guarantee signal handling capability if the guard is hit.  */
++
++static void
++anti_adjust_stack_and_probe_stack_clash (rtx size)
++{
++  /* First ensure SIZE is Pmode.  */
++  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
++    size = convert_to_mode (Pmode, size, 1);
++
++  /* We can get here with a constant size on some targets.  */
++  rtx rounded_size, last_addr, residual;
++  HOST_WIDE_INT probe_interval;
++  compute_stack_clash_protection_loop_data (&rounded_size, &last_addr,
++					    &residual, &probe_interval, size);
++
++  if (rounded_size != CONST0_RTX (Pmode))
++    {
++      if (INTVAL (rounded_size) <= 4 * probe_interval)
++	{
++	  for (HOST_WIDE_INT i = 0;
++	       i < INTVAL (rounded_size);
++	       i += probe_interval)
++	    {
++	      anti_adjust_stack (GEN_INT (probe_interval));
++
++	      /* The prologue does not probe residuals.  Thus the offset
++		 here to probe just beyond what the prologue had already
++		 allocated.  */
++	      emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++					       (probe_interval
++						- GET_MODE_SIZE (word_mode))));
++	      emit_insn (gen_blockage ());
++	    }
++	}
++      else
++	{
++	  rtx loop_lab, end_loop;
++	  bool rotate_loop = GET_CODE (rounded_size) == CONST_INT;
++	  emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop,
++							last_addr, rotate_loop);
++
++	  anti_adjust_stack (GEN_INT (probe_interval));
++
++	  /* The prologue does not probe residuals.  Thus the offset here
++	     to probe just beyond what the prologue had already allocated.  */
++	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++					   (probe_interval
++					    - GET_MODE_SIZE (word_mode))));
++
++	  emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop,
++						      last_addr, rotate_loop);
++	  emit_insn (gen_blockage ());
++	}
++    }
++
++  if (residual != CONST0_RTX (Pmode))
++    {
++      rtx x = force_reg (Pmode, plus_constant (Pmode, residual,
++					       -GET_MODE_SIZE (word_mode)));
++      anti_adjust_stack (residual);
++      emit_stack_probe (gen_rtx_PLUS (Pmode, stack_pointer_rtx, x));
++      emit_insn (gen_blockage ());
++    }
++
++  /* Some targets make optimistic assumptions in their prologues about
++     how the caller may have probed the stack.  Make sure we honor
++     those assumptions when needed.  */
++  if (size != CONST0_RTX (Pmode)
++      && targetm.stack_clash_protection_final_dynamic_probe (residual))
++    {
++      /* Ideally we would just probe at *sp.  However, if SIZE is not
++	 a compile-time constant, but is zero at runtime, then *sp
++	 might hold live data.  So probe at *sp if we know that
++	 an allocation was made, otherwise probe into the red zone
++	 which is obviously undesirable.  */
++      if (GET_CODE (size) == CONST_INT)
++	{
++	  emit_stack_probe (stack_pointer_rtx);
++	  emit_insn (gen_blockage ());
++	}
++      else
++	{
++	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++					   -GET_MODE_SIZE (word_mode)));
++	  emit_insn (gen_blockage ());
++	}
++    }
++}
++
++
+ /* Adjust the stack pointer by minus SIZE (an rtx for a number of bytes)
+    while probing it.  This pushes when SIZE is positive.  SIZE need not
+    be constant.  If ADJUST_BACK is true, adjust back the stack pointer
+diff --git a/gcc/explow.h b/gcc/explow.h
+index 217a3226adb..b85c051e8ce 100644
+--- a/gcc/explow.h
++++ b/gcc/explow.h
+@@ -69,6 +69,15 @@ extern void anti_adjust_stack (rtx);
+ /* Add some bytes to the stack while probing it.  An rtx says how many. */
+ extern void anti_adjust_stack_and_probe (rtx, bool);
+ 
++/* Support for building allocation/probing loops for stack-clash
++   protection of dyamically allocated stack space.  */
++extern void compute_stack_clash_protection_loop_data (rtx *, rtx *, rtx *,
++						      HOST_WIDE_INT *, rtx);
++extern void emit_stack_clash_protection_probe_loop_start (rtx *, rtx *,
++							  rtx, bool);
++extern void emit_stack_clash_protection_probe_loop_end (rtx, rtx,
++							rtx, bool);
++
+ /* This enum is used for the following two functions.  */
+ enum save_level {SAVE_BLOCK, SAVE_FUNCTION, SAVE_NONLOCAL};
+ 
+diff --git a/gcc/rtl.h b/gcc/rtl.h
+index 93330425c00..98f993a95a5 100644
+--- a/gcc/rtl.h
++++ b/gcc/rtl.h
+@@ -2707,6 +2707,7 @@ get_full_set_src_cost (rtx x, machine_mode mode, struct full_rtx_costs *c)
+ /* In explow.c */
+ extern HOST_WIDE_INT trunc_int_for_mode	(HOST_WIDE_INT, machine_mode);
+ extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false);
++extern HOST_WIDE_INT get_stack_check_protect (void);
+ 
+ /* In rtl.c */
+ extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
+diff --git a/gcc/target.def b/gcc/target.def
+index 6bebfd5b9d6..8b8ad1f4938 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -5473,6 +5473,13 @@ these registers when the target switches are opposed to them.)",
+  void, (void),
+  hook_void_void)
+ 
++DEFHOOK
++(stack_clash_protection_final_dynamic_probe,
++ "Some targets make optimistic assumptions about the state of stack probing when they emit their prologues.  On such targets a probe into the end of any dynamically allocated space is likely required for safety against stack clash style attacks.  Define this variable to return nonzero if such a probe is required or zero otherwise.  You need not define this macro if it would always have the value zero.",
++ bool, (rtx residual),
++ default_stack_clash_protection_final_dynamic_probe)
++
++
+ /* Functions specific to the C family of frontends.  */
+ #undef HOOK_PREFIX
+ #define HOOK_PREFIX "TARGET_C_"
+diff --git a/gcc/targhooks.c b/gcc/targhooks.c
+index 1cdec068ed8..225048e7518 100644
+--- a/gcc/targhooks.c
++++ b/gcc/targhooks.c
+@@ -2107,4 +2107,10 @@ default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED)
+   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+ }
+ 
++HOST_WIDE_INT
++default_stack_clash_protection_final_dynamic_probe (rtx residual ATTRIBUTE_UNUSED)
++{
++  return 0;
++}
++
+ #include "gt-targhooks.h"
+diff --git a/gcc/targhooks.h b/gcc/targhooks.h
+index 18070df7839..32ae9d88050 100644
+--- a/gcc/targhooks.h
++++ b/gcc/targhooks.h
+@@ -263,5 +263,6 @@ extern unsigned int default_min_arithmetic_precision (void);
+ 
+ extern enum flt_eval_method
+ default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
++extern bool default_stack_clash_protection_final_dynamic_probe (rtx);
+ 
+ #endif /* GCC_TARGHOOKS_H */
+diff --git a/gcc/testsuite/gcc.dg/stack-check-3.c b/gcc/testsuite/gcc.dg/stack-check-3.c
+new file mode 100644
+index 00000000000..58fb65649ee
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-3.c
+@@ -0,0 +1,86 @@
++/* The goal here is to ensure that dynamic allocations via vlas or
++   alloca calls receive probing.
++
++   Scanning the RTL or assembly code seems like insanity here as does
++   checking for particular allocation sizes and probe offsets.  For
++   now we just verify that there's an allocation + probe loop and
++   residual allocation + probe for f?.  */
++
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-expand -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=4096 --param stack-clash-protection-guard-size=4096" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++__attribute__((noinline, noclone)) void
++foo (char *p)
++{
++  asm volatile ("" : : "r" (p) : "memory");
++}
++
++/* Simple VLA, no other locals. */
++__attribute__((noinline, noclone)) void
++f0 (int x)
++{
++  char vla[x];
++  foo (vla);
++}
++
++/* Simple VLA, small local frame.  */
++__attribute__((noinline, noclone)) void
++f1 (int x)
++{
++  char locals[128];
++  char vla[x];
++  foo (vla);
++}
++
++/* Small constant alloca, no other locals. */
++__attribute__((noinline, noclone)) void
++f2 (int x)
++{
++  char *vla = __builtin_alloca (128);
++  foo (vla);
++}
++
++/* Big constant alloca, small local frame.  */
++__attribute__((noinline, noclone)) void
++f3 (int x)
++{
++  char locals[128];
++  char *vla = __builtin_alloca (16384);
++  foo (vla);
++}
++
++/* Big constant alloca, small local frame.  */
++__attribute__((noinline, noclone)) void
++f3a (int x)
++{
++  char locals[128];
++  char *vla = __builtin_alloca (32768);
++  foo (vla);
++}
++
++/* Nonconstant alloca, no other locals. */
++__attribute__((noinline, noclone)) void
++f4 (int x)
++{
++  char *vla = __builtin_alloca (x);
++  foo (vla);
++}
++
++/* Nonconstant alloca, small local frame.  */
++__attribute__((noinline, noclone)) void
++f5 (int x)
++{
++  char locals[128];
++  char *vla = __builtin_alloca (x);
++  foo (vla);
++}
++
++/* { dg-final { scan-rtl-dump-times "allocation and probing residuals" 7 "expand" } } */
++
++
++/* { dg-final { scan-rtl-dump-times "allocation and probing in loop" 7 "expand" { target callee_realigns_stack } } } */
++/* { dg-final { scan-rtl-dump-times "allocation and probing in loop" 4 "expand" { target { ! callee_realigns_stack } } } } */
++/* { dg-final { scan-rtl-dump-times "allocation and probing in rotated loop" 1 "expand" { target { ! callee_realigns_stack } } } } */
++/* { dg-final { scan-rtl-dump-times "allocation and probing inline" 1 "expand" { target { ! callee_realigns_stack } } } } */
++/* { dg-final { scan-rtl-dump-times "skipped dynamic allocation and probing loop" 1 "expand" { target { ! callee_realigns_stack } } } } */

diff --git a/gcc7-rh1512529-3.patch b/gcc7-rh1512529-3.patch
new file mode 100644
index 0000000..112cf25
--- /dev/null
+++ b/gcc7-rh1512529-3.patch
@@ -0,0 +1,199 @@
+commit 640ca5ef08a3ade8fe3f32d8c412008410de989c
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 05:21:09 2017 +0000
+
+            * config/alpha/alpha.c (alpha_expand_prologue): Also check
+            flag_stack_clash_protection.
+            * config/arm/arm.c (arm_compute_static_chain_stack_bytes): Likewise.
+            (arm_expand_prologue, thumb1_expand_prologue): Likewise.
+            (arm_frame_pointer_required): Likewise.
+            * config/ia64/ia64.c (ia64_compute_frame_size): Likewise.
+            (ia64_expand_prologue): Likewise.
+            * config/mips/mips.c (mips_expand_prologue): Likewise.
+            * config/powerpcspe/powerpcspe.c (rs6000_expand_prologue): Likewise.
+            * config/sparc/sparc.c (sparc_expand_prologue): Likewise.
+            (sparc_flat_expand_prologue): Likewise.
+            * config/spu/spu.c (spu_expand_prologue): Likewise.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252996 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
+index 91f3d7cfbeb..36e78a0caf7 100644
+--- a/gcc/config/alpha/alpha.c
++++ b/gcc/config/alpha/alpha.c
+@@ -7740,7 +7740,7 @@ alpha_expand_prologue (void)
+      Note that we are only allowed to adjust sp once in the prologue.  */
+ 
+   probed_size = frame_size;
+-  if (flag_stack_check)
++  if (flag_stack_check || flag_stack_clash_protection)
+     probed_size += get_stack_check_protect ();
+ 
+   if (probed_size <= 32768)
+@@ -7755,7 +7755,7 @@ alpha_expand_prologue (void)
+ 	  /* We only have to do this probe if we aren't saving registers or
+ 	     if we are probing beyond the frame because of -fstack-check.  */
+ 	  if ((sa_size == 0 && probed_size > probed - 4096)
+-	      || flag_stack_check)
++	      || flag_stack_check || flag_stack_clash_protection)
+ 	    emit_insn (gen_probe_stack (GEN_INT (-probed_size)));
+ 	}
+ 
+@@ -7785,7 +7785,8 @@ alpha_expand_prologue (void)
+ 	 late in the compilation, generate the loop as a single insn.  */
+       emit_insn (gen_prologue_stack_probe_loop (count, ptr));
+ 
+-      if ((leftover > 4096 && sa_size == 0) || flag_stack_check)
++      if ((leftover > 4096 && sa_size == 0)
++	  || flag_stack_check || flag_stack_clash_protection)
+ 	{
+ 	  rtx last = gen_rtx_MEM (DImode,
+ 				  plus_constant (Pmode, ptr, -leftover));
+@@ -7793,7 +7794,7 @@ alpha_expand_prologue (void)
+ 	  emit_move_insn (last, const0_rtx);
+ 	}
+ 
+-      if (flag_stack_check)
++      if (flag_stack_check || flag_stack_clash_protection)
+ 	{
+ 	  /* If -fstack-check is specified we have to load the entire
+ 	     constant into a register and subtract from the sp in one go,
+diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
+index 242d7c792fe..4f85a061753 100644
+--- a/gcc/config/arm/arm.c
++++ b/gcc/config/arm/arm.c
+@@ -19083,7 +19083,8 @@ arm_compute_static_chain_stack_bytes (void)
+   /* See the defining assertion in arm_expand_prologue.  */
+   if (IS_NESTED (arm_current_func_type ())
+       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+-	  || (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++	  || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++	       || flag_stack_clash_protection)
+ 	      && !df_regs_ever_live_p (LR_REGNUM)))
+       && arm_r3_live_at_start_p ()
+       && crtl->args.pretend_args_size == 0)
+@@ -21377,7 +21378,8 @@ arm_expand_prologue (void)
+      clobbered when creating the frame, we need to save and restore it.  */
+   clobber_ip = IS_NESTED (func_type)
+ 	       && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+-		   || (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++		   || ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++			|| flag_stack_clash_protection)
+ 		       && !df_regs_ever_live_p (LR_REGNUM)
+ 		       && arm_r3_live_at_start_p ()));
+ 
+@@ -21591,7 +21593,8 @@ arm_expand_prologue (void)
+      stack checking.  We use IP as the first scratch register, except for the
+      non-APCS nested functions if LR or r3 are available (see clobber_ip).  */
+   if (!IS_INTERRUPT (func_type)
+-      && flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++      && (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++	  || flag_stack_clash_protection))
+     {
+       unsigned int regno;
+ 
+@@ -24875,7 +24878,9 @@ thumb1_expand_prologue (void)
+     current_function_static_stack_size = size;
+ 
+   /* If we have a frame, then do stack checking.  FIXME: not implemented.  */
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
++  if ((flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++       || flag_stack_clash_protection)
++      && size)
+     sorry ("-fstack-check=specific for Thumb-1");
+ 
+   amount = offsets->outgoing_args - offsets->saved_regs;
+@@ -27736,7 +27741,8 @@ arm_frame_pointer_required (void)
+      instruction prior to the stack adjustment and this requires a frame
+      pointer if we want to catch the exception using the EABI unwinder.  */
+   if (!IS_INTERRUPT (arm_current_func_type ())
+-      && flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      && (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++	  || flag_stack_clash_protection)
+       && arm_except_unwind_info (&global_options) == UI_TARGET
+       && cfun->can_throw_non_call_exceptions)
+     {
+diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
+index 17d6b3318a6..8acb92fd32b 100644
+--- a/gcc/config/ia64/ia64.c
++++ b/gcc/config/ia64/ia64.c
+@@ -2685,7 +2685,8 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
+     mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_bsp, NULL);
+ 
+   /* Static stack checking uses r2 and r3.  */
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      || flag_stack_clash_protection)
+     current_frame_info.gr_used_mask |= 0xc;
+ 
+   /* Find the size of the register stack frame.  We have only 80 local
+@@ -3468,7 +3469,8 @@ ia64_expand_prologue (void)
+   if (flag_stack_usage_info)
+     current_function_static_stack_size = current_frame_info.total_size;
+ 
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      || flag_stack_clash_protection)
+     {
+       HOST_WIDE_INT size = current_frame_info.total_size;
+       int bs_size = BACKING_STORE_SIZE (current_frame_info.n_input_regs
+diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
+index 7d85ce7055a..b2d3c737b34 100644
+--- a/gcc/config/mips/mips.c
++++ b/gcc/config/mips/mips.c
+@@ -12077,7 +12077,8 @@ mips_expand_prologue (void)
+   if (flag_stack_usage_info)
+     current_function_static_stack_size = size;
+ 
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      || flag_stack_clash_protection)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
+index b32bb9859e1..498bd04f5c2 100644
+--- a/gcc/config/sparc/sparc.c
++++ b/gcc/config/sparc/sparc.c
+@@ -5691,7 +5691,8 @@ sparc_expand_prologue (void)
+   if (flag_stack_usage_info)
+     current_function_static_stack_size = size;
+ 
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      || flag_stack_clash_protection)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+@@ -5802,7 +5803,8 @@ sparc_flat_expand_prologue (void)
+   if (flag_stack_usage_info)
+     current_function_static_stack_size = size;
+ 
+-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++      || flag_stack_clash_protection)
+     {
+       if (crtl->is_leaf && !cfun->calls_alloca)
+ 	{
+diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
+index fcb85c0ee16..22745fa32c3 100644
+--- a/gcc/config/spu/spu.c
++++ b/gcc/config/spu/spu.c
+@@ -1760,7 +1760,7 @@ spu_expand_prologue (void)
+ 
+   if (total_size > 0)
+     {
+-      if (flag_stack_check)
++      if (flag_stack_check || flag_stack_clash_protection)
+ 	{
+ 	  /* We compare against total_size-1 because
+ 	     ($sp >= total_size) <=> ($sp > total_size-1) */
+@@ -5364,7 +5364,7 @@ spu_allocate_stack (rtx op0, rtx op1)
+   emit_insn (gen_spu_convert (sp, stack_pointer_rtx));
+   emit_insn (gen_subv4si3 (sp, sp, splatted));
+ 
+-  if (flag_stack_check)
++  if (flag_stack_check || flag_stack_clash_protection)
+     {
+       rtx avail = gen_reg_rtx(SImode);
+       rtx result = gen_reg_rtx(SImode);

diff --git a/gcc7-rh1512529-4.patch b/gcc7-rh1512529-4.patch
new file mode 100644
index 0000000..9c953ec
--- /dev/null
+++ b/gcc7-rh1512529-4.patch
@@ -0,0 +1,92 @@
+commit 7f0d332f992c3b51c8aff3ed79e2233ed2498863
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 05:23:51 2017 +0000
+
+            * function.c (dump_stack_clash_frame_info): New function.
+            * function.h (dump_stack_clash_frame_info): Prototype.
+            (enum stack_clash_probes): New enum.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252997 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/function.c b/gcc/function.c
+index 21eb586a8f7..6d0f462a262 100644
+--- a/gcc/function.c
++++ b/gcc/function.c
+@@ -5695,6 +5695,58 @@ get_arg_pointer_save_area (void)
+   return ret;
+ }
+ \f
++
++/* If debugging dumps are requested, dump information about how the
++   target handled -fstack-check=clash for the prologue.
++
++   PROBES describes what if any probes were emitted.
++
++   RESIDUALS indicates if the prologue had any residual allocation
++   (i.e. total allocation was not a multiple of PROBE_INTERVAL).  */
++
++void
++dump_stack_clash_frame_info (enum stack_clash_probes probes, bool residuals)
++{
++  if (!dump_file)
++    return;
++
++  switch (probes)
++    {
++    case NO_PROBE_NO_FRAME:
++      fprintf (dump_file,
++	       "Stack clash no probe no stack adjustment in prologue.\n");
++      break;
++    case NO_PROBE_SMALL_FRAME:
++      fprintf (dump_file,
++	       "Stack clash no probe small stack adjustment in prologue.\n");
++      break;
++    case PROBE_INLINE:
++      fprintf (dump_file, "Stack clash inline probes in prologue.\n");
++      break;
++    case PROBE_LOOP:
++      fprintf (dump_file, "Stack clash probe loop in prologue.\n");
++      break;
++    }
++
++  if (residuals)
++    fprintf (dump_file, "Stack clash residual allocation in prologue.\n");
++  else
++    fprintf (dump_file, "Stack clash no residual allocation in prologue.\n");
++
++  if (frame_pointer_needed)
++    fprintf (dump_file, "Stack clash frame pointer needed.\n");
++  else
++    fprintf (dump_file, "Stack clash no frame pointer needed.\n");
++
++  if (TREE_THIS_VOLATILE (cfun->decl))
++    fprintf (dump_file,
++	     "Stack clash noreturn prologue, assuming no implicit"
++	     " probes in caller.\n");
++  else
++    fprintf (dump_file,
++	     "Stack clash not noreturn prologue.\n");
++}
++
+ /* Add a list of INSNS to the hash HASHP, possibly allocating HASHP
+    for the first time.  */
+ 
+diff --git a/gcc/function.h b/gcc/function.h
+index 0f34bcd6123..87dac803622 100644
+--- a/gcc/function.h
++++ b/gcc/function.h
+@@ -553,6 +553,14 @@ do {								\
+   ((TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)	     \
+    ? MAX (FUNCTION_BOUNDARY, 2 * BITS_PER_UNIT) : FUNCTION_BOUNDARY)
+ 
++enum stack_clash_probes {
++  NO_PROBE_NO_FRAME,
++  NO_PROBE_SMALL_FRAME,
++  PROBE_INLINE,
++  PROBE_LOOP
++};
++
++extern void dump_stack_clash_frame_info (enum stack_clash_probes, bool);
+ \f
+ 
+ extern void push_function_context (void);

diff --git a/gcc7-rh1512529-5.patch b/gcc7-rh1512529-5.patch
new file mode 100644
index 0000000..1b6d4ba
--- /dev/null
+++ b/gcc7-rh1512529-5.patch
@@ -0,0 +1,2705 @@
+commit ded495f992254176bd1d08d4f200a7b508a33b9a
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 05:35:07 2017 +0000
+
+            * config/i386/i386.c (ix86_adjust_stack_and_probe_stack_clash): New.
+            (ix86_expand_prologue): Dump stack clash info as needed.
+            Call ix86_adjust_stack_and_probe_stack_clash as needed.
+    
+            * gcc.dg/stack-check-4.c: New test.
+            * gcc.dg/stack-check-5.c: New test.
+            * gcc.dg/stack-check-6.c: New test.
+            * gcc.dg/stack-check-6a.c: New test.
+            * gcc.dg/stack-check-7.c: New test.
+            * gcc.dg/stack-check-8.c: New test.
+            * gcc.dg/stack-check-9.c: New test.
+            * gcc.dg/stack-check-10.c: New test.
+            * lib/target-supports.exp
+            (check_effective_target_supports_stack_clash_protection): Enable for
+            x86 and x86_64 targets.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252998 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 60bab9a26a6..088dca2001f 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -13270,6 +13270,147 @@ release_scratch_register_on_entry (struct scratch_reg *sr)
+ 
+ #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
+ 
++/* Emit code to adjust the stack pointer by SIZE bytes while probing it.
++
++   This differs from the next routine in that it tries hard to prevent
++   attacks that jump the stack guard.  Thus it is never allowed to allocate
++   more than PROBE_INTERVAL bytes of stack space without a suitable
++   probe.  */
++
++static void
++ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
++{
++  struct machine_function *m = cfun->machine;
++
++  /* If this function does not statically allocate stack space, then
++     no probes are needed.  */
++  if (!size)
++    {
++      dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
++      return;
++    }
++
++  /* If we are a noreturn function, then we have to consider the
++     possibility that we're called via a jump rather than a call.
++
++     Thus we don't have the implicit probe generated by saving the
++     return address into the stack at the call.  Thus, the stack
++     pointer could be anywhere in the guard page.  The safe thing
++     to do is emit a probe now.
++
++     ?!? This should be revamped to work like aarch64 and s390 where
++     we track the offset from the most recent probe.  Normally that
++     offset would be zero.  For a non-return function we would reset
++     it to PROBE_INTERVAL - (STACK_BOUNDARY / BITS_PER_UNIT).   Then
++     we just probe when we cross PROBE_INTERVAL.  */
++  if (TREE_THIS_VOLATILE (cfun->decl))
++    {
++      emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++				       -GET_MODE_SIZE (word_mode)));
++      emit_insn (gen_blockage ());
++    }
++
++  /* If we allocate less than the size of the guard statically,
++     then no probing is necessary, but we do need to allocate
++     the stack.  */
++  if (size < (1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE)))
++    {
++      pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++			         GEN_INT (-size), -1,
++			         m->fs.cfa_reg == stack_pointer_rtx);
++      dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++      return;
++    }
++
++  /* We're allocating a large enough stack frame that we need to
++     emit probes.  Either emit them inline or in a loop depending
++     on the size.  */
++  HOST_WIDE_INT probe_interval
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  if (size <= 4 * probe_interval)
++    {
++      HOST_WIDE_INT i;
++      for (i = probe_interval; i <= size; i += probe_interval)
++	{
++	  /* Allocate PROBE_INTERVAL bytes.  */
++	  pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++				     GEN_INT (-probe_interval), -1,
++				     m->fs.cfa_reg == stack_pointer_rtx);
++
++	  /* And probe at *sp.  */
++	  emit_stack_probe (stack_pointer_rtx);
++	  emit_insn (gen_blockage ());
++	}
++
++      /* We need to allocate space for the residual, but we do not need
++	 to probe the residual.  */
++      HOST_WIDE_INT residual = (i - probe_interval - size);
++      if (residual)
++	pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++				   GEN_INT (residual), -1,
++				   m->fs.cfa_reg == stack_pointer_rtx);
++      dump_stack_clash_frame_info (PROBE_INLINE, residual != 0);
++    }
++  else
++    {
++      struct scratch_reg sr;
++      get_scratch_register_on_entry (&sr);
++
++      /* Step 1: round SIZE down to a multiple of the interval.  */
++      HOST_WIDE_INT rounded_size = size & -probe_interval;
++
++      /* Step 2: compute final value of the loop counter.  Use lea if
++	 possible.  */
++      rtx addr = plus_constant (Pmode, stack_pointer_rtx, -rounded_size);
++      rtx insn;
++      if (address_no_seg_operand (addr, Pmode))
++	insn = emit_insn (gen_rtx_SET (sr.reg, addr));
++      else
++	{
++	  emit_move_insn (sr.reg, GEN_INT (-rounded_size));
++	  insn = emit_insn (gen_rtx_SET (sr.reg,
++					 gen_rtx_PLUS (Pmode, sr.reg,
++						       stack_pointer_rtx)));
++	}
++      if (m->fs.cfa_reg == stack_pointer_rtx)
++	{
++	  add_reg_note (insn, REG_CFA_DEF_CFA,
++			plus_constant (Pmode, sr.reg,
++				       m->fs.cfa_offset + rounded_size));
++	  RTX_FRAME_RELATED_P (insn) = 1;
++        }
++
++      /* Step 3: the loop.  */
++      rtx size_rtx = GEN_INT (rounded_size);
++      insn = emit_insn (ix86_gen_adjust_stack_and_probe (sr.reg, sr.reg,
++							 size_rtx));
++      if (m->fs.cfa_reg == stack_pointer_rtx)
++	{
++	  m->fs.cfa_offset += rounded_size;
++	  add_reg_note (insn, REG_CFA_DEF_CFA,
++			plus_constant (Pmode, stack_pointer_rtx,
++				       m->fs.cfa_offset));
++	  RTX_FRAME_RELATED_P (insn) = 1;
++        }
++      m->fs.sp_offset += rounded_size;
++      emit_insn (gen_blockage ());
++
++      /* Step 4: adjust SP if we cannot assert at compile-time that SIZE
++	 is equal to ROUNDED_SIZE.  */
++
++      if (size != rounded_size)
++	pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++				   GEN_INT (rounded_size - size), -1,
++				   m->fs.cfa_reg == stack_pointer_rtx);
++      dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size);
++
++      release_scratch_register_on_entry (&sr);
++    }
++
++  /* Make sure nothing is scheduled before we are done.  */
++  emit_insn (gen_blockage ());
++}
++
+ /* Emit code to adjust the stack pointer by SIZE bytes while probing it.  */
+ 
+ static void
+@@ -14018,12 +14159,19 @@ ix86_expand_prologue (void)
+ 
+   /* The stack has already been decremented by the instruction calling us
+      so probe if the size is non-negative to preserve the protection area.  */
+-  if (allocate >= 0 && flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
++  if (allocate >= 0
++      && (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
++	  || flag_stack_clash_protection))
+     {
+       /* We expect the registers to be saved when probes are used.  */
+       gcc_assert (int_registers_saved);
+ 
+-      if (STACK_CHECK_MOVING_SP)
++      if (flag_stack_clash_protection)
++	{
++	  ix86_adjust_stack_and_probe_stack_clash (allocate);
++	  allocate = 0;
++	}
++      else if (STACK_CHECK_MOVING_SP)
+ 	{
+ 	  if (!(crtl->is_leaf && !cfun->calls_alloca
+ 		&& allocate <= PROBE_INTERVAL))
+diff --git a/gcc/testsuite/gcc.dg/stack-check-10.c b/gcc/testsuite/gcc.dg/stack-check-10.c
+new file mode 100644
+index 00000000000..a86956ad692
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-10.c
+@@ -0,0 +1,41 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++int f (int *);
++
++int
++g (int a)
++{
++  return f (&a);
++}
++
++int f1 (void);
++int f2 (int);
++
++int
++f3 (void)
++{
++  return f2 (f1 ());
++}
++
++
++/* If we have caller implicit probes, then we should not need probes in either callee.
++   Else callees may need probes, particularly if non-leaf functions require a
++   frame/frame pointer.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash no probe" 2 "pro_and_epilogue" { target caller_implicit_probes } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash inline probe" 1 "pro_and_epilogue" { target { ! caller_implicit_probes } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash no probe" 1 "pro_and_epilogue" { target { ! caller_implicit_probes } } } } */
++
++/* Neither of these functions are a nonreturn function.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 2 "pro_and_epilogue" } } */
++
++/* If the callee realigns the stack or has a mandatory frame, then both functions
++   have a residual allocation.  Else just g() has a residual allocation.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 2 "pro_and_epilogue" } } */
++
++
++/* If the target has frame pointers for non-leafs, then both functions will
++   need a frame pointer.  Otherwise neither should.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 2 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
+diff --git a/gcc/testsuite/gcc.dg/stack-check-3.c b/gcc/testsuite/gcc.dg/stack-check-3.c
+index 58fb65649ee..f0bf7c71a5b 100644
+--- a/gcc/testsuite/gcc.dg/stack-check-3.c
++++ b/gcc/testsuite/gcc.dg/stack-check-3.c
+@@ -7,7 +7,7 @@
+    residual allocation + probe for f?.  */
+ 
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-expand -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=4096 --param stack-clash-protection-guard-size=4096" } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-expand -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
+ /* { dg-require-effective-target supports_stack_clash_protection } */
+ 
+ __attribute__((noinline, noclone)) void
+diff --git a/gcc/testsuite/gcc.dg/stack-check-4.c b/gcc/testsuite/gcc.dg/stack-check-4.c
+new file mode 100644
+index 00000000000..b0c5c61972f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-4.c
+@@ -0,0 +1,42 @@
++/* On targets where the call instruction is an implicit probe of *sp, we
++   elide stack probes as long as the size of the local stack is less than
++   PROBE_INTERVAL.
++
++   But if the caller were to transform a tail call into a direct jump
++   we do not have that implicit probe.  This normally isn't a problem as
++   the caller must not have a local frame for that optimization to apply.
++
++   However, a sufficiently smart compiler could realize that the caller's
++   local stack need not be torn down and thus could transform a call into
++   a jump if the target is a noreturn function, even if the caller has
++   a local frame.
++
++   To guard against that, targets that depend on *sp being probed by the
++   call itself must emit a probe if the target function is a noreturn
++   function, even if they just allocate a small amount of stack space.
++
++   Rather than try to parse RTL or assembly code, we instead require the
++   prologue code to emit information into the dump file that we can
++   scan for.   We scan for both the positive and negative cases.  */
++
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++extern void arf (char *);
++
++__attribute__ ((noreturn)) void foo1 ()
++{
++  char x[10];
++  while (1)
++    arf (x);
++}
++
++void foo2 ()
++{
++  char x[10];
++  arf (x);
++}
++/* { dg-final { scan-rtl-dump-times "Stack clash noreturn" 1 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 1 "pro_and_epilogue" } } */
++
+diff --git a/gcc/testsuite/gcc.dg/stack-check-5.c b/gcc/testsuite/gcc.dg/stack-check-5.c
+new file mode 100644
+index 00000000000..2171d9b6c23
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-5.c
+@@ -0,0 +1,74 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++
++extern void foo (char *);
++extern void bar (void);
++
++/* This function allocates no local stack and is a leaf.  It should have no
++   probes on any target and should not require a frame pointer.  */
++int
++f0 (int x, int y)
++{
++  asm volatile ("" : : : "memory");  
++  return x + y;
++}
++
++/* This function allocates no local stack, but is not a leaf.  Ideally it
++   should not need probing and no frame pointer.  */
++int
++f1 (int x, int y)
++{
++  asm volatile ("" : : : "memory");  
++  bar ();
++}
++
++/* This is a leaf with a small frame.  On targets with implicit probes in
++   the caller, this should not need probing.  On targets with no implicit
++   probes in the caller, it may require probes.  Ideally it should need no
++   frame pointer.  */
++void
++f2 (void)
++{
++  char buf[512];
++  asm volatile ("" : : "g" (&buf) : "memory");
++}
++
++/* This is a non-leaf with a small frame.  On targets with implicit probes in
++   the caller, this should not need probing.  On targets with no implicit
++   probes in the caller, it may require probes.  It should need no frame
++   pointer.  */
++void
++f3 (void)
++{
++  char buf[512];
++  foo (buf);
++}
++
++/* If we have caller implicit probes, then we should not need probes.
++   Else callees may need probes, particularly if non-leaf functions require a
++   frame/frame pointer.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash no probe" 4 "pro_and_epilogue" { target caller_implicit_probes } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash no probe" 2 "pro_and_epilogue" { target { ! caller_implicit_probes } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash inline probes " 2 "pro_and_epilogue" { target { ! caller_implicit_probes } } } } */
++
++/* None of these functions are marked with the noreturn attribute.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 4 "pro_and_epilogue" } } */
++
++/* Two functions are leafs, two are not.  Verify the target identified them
++   appropriately.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 4 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
++
++
++/* We have selected the size of the array in f2/f3 to be large enough
++   to not live in the red zone on targets that support it.
++
++   That allows simplification of this test considerably.
++   f1() should not require any allocations, thus no residuals.
++   All the rest of the functions require some kind of allocation,
++   either for the saved fp/rp or the array.  */
++/* { dg-final { scan-rtl-dump-times "Stack clash no residual allocation in prologue" 1 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 3 "pro_and_epilogue" } } */
+diff --git a/gcc/testsuite/gcc.dg/stack-check-6.c b/gcc/testsuite/gcc.dg/stack-check-6.c
+new file mode 100644
+index 00000000000..ad2021c9037
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-6.c
+@@ -0,0 +1,55 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++
++extern void foo (char *);
++extern void bar (void);
++
++
++/* This is a leaf with a frame that is large enough to require probing with
++   a residual allocation, but small enough to probe inline.  */
++void
++f4 (void)
++{
++  char buf[4096 + 512];
++  asm volatile ("" : : "g" (&buf) : "memory");
++}
++
++
++/* This is a non-leaf with a frame large enough to require probing and
++   a residual allocation, but small enough to probe inline.  */
++void
++f5 (void)
++{
++  char buf[4096 + 512];
++  foo (buf);
++}
++
++/* This is a leaf with a frame that is large enough to require probing with
++   a loop plus a residual allocation.  */
++void
++f6 (void)
++{
++  char buf[4096 * 10 + 512];
++  asm volatile ("" : : "g" (&buf) : "memory");
++}
++
++
++/* This is a non-leaf with a frame large enough to require probing with
++   a loop plus a residual allocation.  */
++void
++f7 (void)
++{
++  char buf[4096 * 10 + 512];
++  foo (buf);
++}
++
++/* { dg-final { scan-rtl-dump-times "Stack clash inline probes" 2 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash probe loop" 2 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 4 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 4 "pro_and_epilogue" } } */
++
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 4 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
+diff --git a/gcc/testsuite/gcc.dg/stack-check-6a.c b/gcc/testsuite/gcc.dg/stack-check-6a.c
+new file mode 100644
+index 00000000000..6f8e7128921
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-6a.c
+@@ -0,0 +1,17 @@
++/* The goal here is to verify that increasing the size of the guard allows
++   elimination of all probing on the relevant targets.  */
++   
++/* { dg-do compile  } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=16" } */
++/* { dg-require-effective-target supports_stack_clash_protection  } */
++
++#include "stack-check-6.c"
++
++/* { dg-final { scan-rtl-dump-times "Stack clash inline probes" 0 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash probe loop" 0 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 4 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 4 "pro_and_epilogue" } } */
++
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 4 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash frame pointer needed" 2 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
+diff --git a/gcc/testsuite/gcc.dg/stack-check-7.c b/gcc/testsuite/gcc.dg/stack-check-7.c
+new file mode 100644
+index 00000000000..b963a2881dc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-7.c
+@@ -0,0 +1,36 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -fstack-clash-protection -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++/* For further testing, this can be run under valgrind where it's crashed
++   on aarch64 and ppc64le with -fstack-check=specific.  */
++
++
++__attribute__((noinline, noclone)) void
++foo (char *p)
++{
++  asm volatile ("" : : "r" (p) : "memory");
++}
++
++__attribute__((noinline, noclone)) void
++bar (void)
++{
++  char buf[131072];
++  foo (buf);
++}
++
++__attribute__((noinline, noclone)) void
++baz (void)
++{
++  char buf[12000];
++  foo (buf);
++}
++
++int
++main ()
++{
++  bar ();
++  baz ();
++  return 0;
++}
++
+diff --git a/gcc/testsuite/gcc.dg/stack-check-8.c b/gcc/testsuite/gcc.dg/stack-check-8.c
+new file mode 100644
+index 00000000000..84d5adef154
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-8.c
+@@ -0,0 +1,139 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -fstack-clash-protection -Wno-psabi -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++
++typedef float V __attribute__((vector_size (32)));
++
++__attribute__((noinline, noclone)) void
++foo (char *p)
++{
++  asm volatile ("" : : "r" (p) : "memory");
++}
++
++__attribute__((noinline, noclone)) int
++f0 (int x, int y)
++{
++  asm volatile ("" : : : "memory");  
++  return x + y;
++}
++
++__attribute__((noinline, noclone)) void
++f1 (void)
++{
++  char buf[64];
++  foo (buf);
++}
++
++__attribute__((noinline, noclone)) void
++f2 (void)
++{
++  char buf[12000];
++  foo (buf);
++}
++
++__attribute__((noinline, noclone)) void
++f3 (void)
++{
++  char buf[131072];
++  foo (buf);
++}
++
++__attribute__((noinline, noclone)) void
++f4 (int x)
++{
++  char vla[x];
++  foo (vla);
++}
++
++__attribute__((noinline, noclone)) void
++f5 (int x)
++{
++  char buf[12000];
++  foo (buf);
++  {
++    char vla[x];
++    foo (vla);
++  }
++  {
++    char vla[x];
++    foo (vla);
++  }
++}
++
++V v;
++
++__attribute__((noinline, noclone)) int
++f6 (int x, int y, V a, V b, V c)
++{
++  asm volatile ("" : : : "memory");  
++  v = a + b + c;
++  return x + y;
++}
++
++__attribute__((noinline, noclone)) void
++f7 (V a, V b, V c)
++{
++  char buf[64];
++  foo (buf);
++  v = a + b + c;
++}
++
++__attribute__((noinline, noclone)) void
++f8 (V a, V b, V c)
++{
++  char buf[12000];
++  foo (buf);
++  v = a + b + c;
++}
++
++__attribute__((noinline, noclone)) void
++f9 (V a, V b, V c)
++{
++  char buf[131072];
++  foo (buf);
++  v = a + b + c;
++}
++
++__attribute__((noinline, noclone)) void
++f10 (int x, V a, V b, V c)
++{
++  char vla[x];
++  foo (vla);
++  v = a + b + c;
++}
++
++__attribute__((noinline, noclone)) void
++f11 (int x, V a, V b, V c)
++{
++  char buf[12000];
++  foo (buf);
++  v = a + b + c;
++  {
++    char vla[x];
++    foo (vla);
++  }
++  {
++    char vla[x];
++    foo (vla);
++  }
++}
++
++int
++main ()
++{
++  f0 (2, 3);
++  f1 ();
++  f2 ();
++  f3 ();
++  f4 (12000);
++  f5 (12000);
++  f6 (2, 3, v, v, v);
++  f7 (v, v, v);
++  f8 (v, v, v);
++  f9 (v, v, v);
++  f10 (12000, v, v, v);
++  f11 (12000, v, v, v);
++  return 0;
++}
++
+diff --git a/gcc/testsuite/gcc.dg/stack-check-9.c b/gcc/testsuite/gcc.dg/stack-check-9.c
+new file mode 100644
+index 00000000000..b84075b9b43
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/stack-check-9.c
+@@ -0,0 +1,2022 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++double f1 (void);
++double f2 (double, double);
++
++double
++f3 (void)
++{
++  double d000 = f1 ();
++  double d001 = f1 ();
++  double d002 = f1 ();
++  double d003 = f1 ();
++  double d004 = f1 ();
++  double d005 = f1 ();
++  double d006 = f1 ();
++  double d007 = f1 ();
++  double d008 = f1 ();
++  double d009 = f1 ();
++  double d010 = f1 ();
++  double d011 = f1 ();
++  double d012 = f1 ();
++  double d013 = f1 ();
++  double d014 = f1 ();
++  double d015 = f1 ();
++  double d016 = f1 ();
++  double d017 = f1 ();
++  double d018 = f1 ();
++  double d019 = f1 ();
++  double d020 = f1 ();
++  double d021 = f1 ();
++  double d022 = f1 ();
++  double d023 = f1 ();
++  double d024 = f1 ();
++  double d025 = f1 ();
++  double d026 = f1 ();
++  double d027 = f1 ();
++  double d028 = f1 ();
++  double d029 = f1 ();
++  double d030 = f1 ();
++  double d031 = f1 ();
++  double d032 = f1 ();
++  double d033 = f1 ();
++  double d034 = f1 ();
++  double d035 = f1 ();
++  double d036 = f1 ();
++  double d037 = f1 ();
++  double d038 = f1 ();
++  double d039 = f1 ();
++  double d040 = f1 ();
++  double d041 = f1 ();
++  double d042 = f1 ();
++  double d043 = f1 ();
++  double d044 = f1 ();
++  double d045 = f1 ();
++  double d046 = f1 ();
++  double d047 = f1 ();
++  double d048 = f1 ();
++  double d049 = f1 ();
++  double d050 = f1 ();
++  double d051 = f1 ();
++  double d052 = f1 ();
++  double d053 = f1 ();
++  double d054 = f1 ();
++  double d055 = f1 ();
++  double d056 = f1 ();
++  double d057 = f1 ();
++  double d058 = f1 ();
++  double d059 = f1 ();
++  double d060 = f1 ();
++  double d061 = f1 ();
++  double d062 = f1 ();
++  double d063 = f1 ();
++  double d064 = f1 ();
++  double d065 = f1 ();
++  double d066 = f1 ();
++  double d067 = f1 ();
++  double d068 = f1 ();
++  double d069 = f1 ();
++  double d070 = f1 ();
++  double d071 = f1 ();
++  double d072 = f1 ();
++  double d073 = f1 ();
++  double d074 = f1 ();
++  double d075 = f1 ();
++  double d076 = f1 ();
++  double d077 = f1 ();
++  double d078 = f1 ();
++  double d079 = f1 ();
++  double d080 = f1 ();
++  double d081 = f1 ();
++  double d082 = f1 ();
++  double d083 = f1 ();
++  double d084 = f1 ();
++  double d085 = f1 ();
++  double d086 = f1 ();
++  double d087 = f1 ();
++  double d088 = f1 ();
++  double d089 = f1 ();
++  double d090 = f1 ();
++  double d091 = f1 ();
++  double d092 = f1 ();
++  double d093 = f1 ();
++  double d094 = f1 ();
++  double d095 = f1 ();
++  double d096 = f1 ();
++  double d097 = f1 ();
++  double d098 = f1 ();
++  double d099 = f1 ();
++  double d100 = f1 ();
++  double d101 = f1 ();
++  double d102 = f1 ();
++  double d103 = f1 ();
++  double d104 = f1 ();
++  double d105 = f1 ();
++  double d106 = f1 ();
++  double d107 = f1 ();
++  double d108 = f1 ();
++  double d109 = f1 ();
++  double d110 = f1 ();
++  double d111 = f1 ();
++  double d112 = f1 ();
++  double d113 = f1 ();
++  double d114 = f1 ();
++  double d115 = f1 ();
++  double d116 = f1 ();
++  double d117 = f1 ();
++  double d118 = f1 ();
++  double d119 = f1 ();
++  double d120 = f1 ();
++  double d121 = f1 ();
++  double d122 = f1 ();
++  double d123 = f1 ();
++  double d124 = f1 ();
++  double d125 = f1 ();
++  double d126 = f1 ();
++  double d127 = f1 ();
++  double d128 = f1 ();
++  double d129 = f1 ();
++  double d130 = f1 ();
++  double d131 = f1 ();
++  double d132 = f1 ();
++  double d133 = f1 ();
++  double d134 = f1 ();
++  double d135 = f1 ();
++  double d136 = f1 ();
++  double d137 = f1 ();
++  double d138 = f1 ();
++  double d139 = f1 ();
++  double d140 = f1 ();
++  double d141 = f1 ();
++  double d142 = f1 ();
++  double d143 = f1 ();
++  double d144 = f1 ();
++  double d145 = f1 ();
++  double d146 = f1 ();
++  double d147 = f1 ();
++  double d148 = f1 ();
++  double d149 = f1 ();
++  double d150 = f1 ();
++  double d151 = f1 ();
++  double d152 = f1 ();
++  double d153 = f1 ();
++  double d154 = f1 ();
++  double d155 = f1 ();
++  double d156 = f1 ();
++  double d157 = f1 ();
++  double d158 = f1 ();
++  double d159 = f1 ();
++  double d160 = f1 ();
++  double d161 = f1 ();
++  double d162 = f1 ();
++  double d163 = f1 ();
++  double d164 = f1 ();
++  double d165 = f1 ();
++  double d166 = f1 ();
++  double d167 = f1 ();
++  double d168 = f1 ();
++  double d169 = f1 ();
++  double d170 = f1 ();
++  double d171 = f1 ();
++  double d172 = f1 ();
++  double d173 = f1 ();
++  double d174 = f1 ();
++  double d175 = f1 ();
++  double d176 = f1 ();
++  double d177 = f1 ();
++  double d178 = f1 ();
++  double d179 = f1 ();
++  double d180 = f1 ();
++  double d181 = f1 ();
++  double d182 = f1 ();
++  double d183 = f1 ();
++  double d184 = f1 ();
++  double d185 = f1 ();
++  double d186 = f1 ();
++  double d187 = f1 ();
++  double d188 = f1 ();
++  double d189 = f1 ();
++  double d190 = f1 ();
++  double d191 = f1 ();
++  double d192 = f1 ();
++  double d193 = f1 ();
++  double d194 = f1 ();
++  double d195 = f1 ();
++  double d196 = f1 ();
++  double d197 = f1 ();
++  double d198 = f1 ();
++  double d199 = f1 ();
++  double d200 = f1 ();
++  double d201 = f1 ();
++  double d202 = f1 ();
++  double d203 = f1 ();
++  double d204 = f1 ();
++  double d205 = f1 ();
++  double d206 = f1 ();
++  double d207 = f1 ();
++  double d208 = f1 ();
++  double d209 = f1 ();
++  double d210 = f1 ();
++  double d211 = f1 ();
++  double d212 = f1 ();
++  double d213 = f1 ();
++  double d214 = f1 ();
++  double d215 = f1 ();
++  double d216 = f1 ();
++  double d217 = f1 ();
++  double d218 = f1 ();
++  double d219 = f1 ();
++  double d220 = f1 ();
++  double d221 = f1 ();
++  double d222 = f1 ();
++  double d223 = f1 ();
++  double d224 = f1 ();
++  double d225 = f1 ();
++  double d226 = f1 ();
++  double d227 = f1 ();
++  double d228 = f1 ();
++  double d229 = f1 ();
++  double d230 = f1 ();
++  double d231 = f1 ();
++  double d232 = f1 ();
++  double d233 = f1 ();
++  double d234 = f1 ();
++  double d235 = f1 ();
++  double d236 = f1 ();
++  double d237 = f1 ();
++  double d238 = f1 ();
++  double d239 = f1 ();
++  double d240 = f1 ();
++  double d241 = f1 ();
++  double d242 = f1 ();
++  double d243 = f1 ();
++  double d244 = f1 ();
++  double d245 = f1 ();
++  double d246 = f1 ();
++  double d247 = f1 ();
++  double d248 = f1 ();
++  double d249 = f1 ();
++  double d250 = f1 ();
++  double d251 = f1 ();
++  double d252 = f1 ();
++  double d253 = f1 ();
++  double d254 = f1 ();
++  double d255 = f1 ();
++  double d256 = f1 ();
++  double d257 = f1 ();
++  double d258 = f1 ();
++  double d259 = f1 ();
++  double d260 = f1 ();
++  double d261 = f1 ();
++  double d262 = f1 ();
++  double d263 = f1 ();
++  double d264 = f1 ();
++  double d265 = f1 ();
++  double d266 = f1 ();
++  double d267 = f1 ();
++  double d268 = f1 ();
++  double d269 = f1 ();
++  double d270 = f1 ();
++  double d271 = f1 ();
++  double d272 = f1 ();
++  double d273 = f1 ();
++  double d274 = f1 ();
++  double d275 = f1 ();
++  double d276 = f1 ();
++  double d277 = f1 ();
++  double d278 = f1 ();
++  double d279 = f1 ();
++  double d280 = f1 ();
++  double d281 = f1 ();
++  double d282 = f1 ();
++  double d283 = f1 ();
++  double d284 = f1 ();
++  double d285 = f1 ();
++  double d286 = f1 ();
++  double d287 = f1 ();
++  double d288 = f1 ();
++  double d289 = f1 ();
++  double d290 = f1 ();
++  double d291 = f1 ();
++  double d292 = f1 ();
++  double d293 = f1 ();
++  double d294 = f1 ();
++  double d295 = f1 ();
++  double d296 = f1 ();
++  double d297 = f1 ();
++  double d298 = f1 ();
++  double d299 = f1 ();
++  double d300 = f1 ();
++  double d301 = f1 ();
++  double d302 = f1 ();
++  double d303 = f1 ();
++  double d304 = f1 ();
++  double d305 = f1 ();
++  double d306 = f1 ();
++  double d307 = f1 ();
++  double d308 = f1 ();
++  double d309 = f1 ();
++  double d310 = f1 ();
++  double d311 = f1 ();
++  double d312 = f1 ();
++  double d313 = f1 ();
++  double d314 = f1 ();
++  double d315 = f1 ();
++  double d316 = f1 ();
++  double d317 = f1 ();
++  double d318 = f1 ();
++  double d319 = f1 ();
++  double d320 = f1 ();
++  double d321 = f1 ();
++  double d322 = f1 ();
++  double d323 = f1 ();
++  double d324 = f1 ();
++  double d325 = f1 ();
++  double d326 = f1 ();
++  double d327 = f1 ();
++  double d328 = f1 ();
++  double d329 = f1 ();
++  double d330 = f1 ();
++  double d331 = f1 ();
++  double d332 = f1 ();
++  double d333 = f1 ();
++  double d334 = f1 ();
++  double d335 = f1 ();
++  double d336 = f1 ();
++  double d337 = f1 ();
++  double d338 = f1 ();
++  double d339 = f1 ();
++  double d340 = f1 ();
++  double d341 = f1 ();
++  double d342 = f1 ();
++  double d343 = f1 ();
++  double d344 = f1 ();
++  double d345 = f1 ();
++  double d346 = f1 ();
++  double d347 = f1 ();
++  double d348 = f1 ();
++  double d349 = f1 ();
++  double d350 = f1 ();
++  double d351 = f1 ();
++  double d352 = f1 ();
++  double d353 = f1 ();
++  double d354 = f1 ();
++  double d355 = f1 ();
++  double d356 = f1 ();
++  double d357 = f1 ();
++  double d358 = f1 ();
++  double d359 = f1 ();
++  double d360 = f1 ();
++  double d361 = f1 ();
++  double d362 = f1 ();
++  double d363 = f1 ();
++  double d364 = f1 ();
++  double d365 = f1 ();
++  double d366 = f1 ();
++  double d367 = f1 ();
++  double d368 = f1 ();
++  double d369 = f1 ();
++  double d370 = f1 ();
++  double d371 = f1 ();
++  double d372 = f1 ();
++  double d373 = f1 ();
++  double d374 = f1 ();
++  double d375 = f1 ();
++  double d376 = f1 ();
++  double d377 = f1 ();
++  double d378 = f1 ();
++  double d379 = f1 ();
++  double d380 = f1 ();
++  double d381 = f1 ();
++  double d382 = f1 ();
++  double d383 = f1 ();
++  double d384 = f1 ();
++  double d385 = f1 ();
++  double d386 = f1 ();
++  double d387 = f1 ();
++  double d388 = f1 ();
++  double d389 = f1 ();
++  double d390 = f1 ();
++  double d391 = f1 ();
++  double d392 = f1 ();
++  double d393 = f1 ();
++  double d394 = f1 ();
++  double d395 = f1 ();
++  double d396 = f1 ();
++  double d397 = f1 ();
++  double d398 = f1 ();
++  double d399 = f1 ();
++  double d400 = f1 ();
++  double d401 = f1 ();
++  double d402 = f1 ();
++  double d403 = f1 ();
++  double d404 = f1 ();
++  double d405 = f1 ();
++  double d406 = f1 ();
++  double d407 = f1 ();
++  double d408 = f1 ();
++  double d409 = f1 ();
++  double d410 = f1 ();
++  double d411 = f1 ();
++  double d412 = f1 ();
++  double d413 = f1 ();
++  double d414 = f1 ();
++  double d415 = f1 ();
++  double d416 = f1 ();
++  double d417 = f1 ();
++  double d418 = f1 ();
++  double d419 = f1 ();
++  double d420 = f1 ();
++  double d421 = f1 ();
++  double d422 = f1 ();
++  double d423 = f1 ();
++  double d424 = f1 ();
++  double d425 = f1 ();
++  double d426 = f1 ();
++  double d427 = f1 ();
++  double d428 = f1 ();
++  double d429 = f1 ();
++  double d430 = f1 ();
++  double d431 = f1 ();
++  double d432 = f1 ();
++  double d433 = f1 ();
++  double d434 = f1 ();
++  double d435 = f1 ();
++  double d436 = f1 ();
++  double d437 = f1 ();
++  double d438 = f1 ();
++  double d439 = f1 ();
++  double d440 = f1 ();
++  double d441 = f1 ();
++  double d442 = f1 ();
++  double d443 = f1 ();
++  double d444 = f1 ();
++  double d445 = f1 ();
++  double d446 = f1 ();
++  double d447 = f1 ();
++  double d448 = f1 ();
++  double d449 = f1 ();
++  double d450 = f1 ();
++  double d451 = f1 ();
++  double d452 = f1 ();
++  double d453 = f1 ();
++  double d454 = f1 ();
++  double d455 = f1 ();
++  double d456 = f1 ();
++  double d457 = f1 ();
++  double d458 = f1 ();
++  double d459 = f1 ();
++  double d460 = f1 ();
++  double d461 = f1 ();
++  double d462 = f1 ();
++  double d463 = f1 ();
++  double d464 = f1 ();
++  double d465 = f1 ();
++  double d466 = f1 ();
++  double d467 = f1 ();
++  double d468 = f1 ();
++  double d469 = f1 ();
++  double d470 = f1 ();
++  double d471 = f1 ();
++  double d472 = f1 ();
++  double d473 = f1 ();
++  double d474 = f1 ();
++  double d475 = f1 ();
++  double d476 = f1 ();
++  double d477 = f1 ();
++  double d478 = f1 ();
++  double d479 = f1 ();
++  double d480 = f1 ();
++  double d481 = f1 ();
++  double d482 = f1 ();
++  double d483 = f1 ();
++  double d484 = f1 ();
++  double d485 = f1 ();
++  double d486 = f1 ();
++  double d487 = f1 ();
++  double d488 = f1 ();
++  double d489 = f1 ();
++  double d490 = f1 ();
++  double d491 = f1 ();
++  double d492 = f1 ();
++  double d493 = f1 ();
++  double d494 = f1 ();
++  double d495 = f1 ();
++  double d496 = f1 ();
++  double d497 = f1 ();
++  double d498 = f1 ();
++  double d499 = f1 ();
++  double d500 = f1 ();
++  double d501 = f1 ();
++  double d502 = f1 ();
++  double d503 = f1 ();
++  double d504 = f1 ();
++  double d505 = f1 ();
++  double d506 = f1 ();
++  double d507 = f1 ();
++  double d508 = f1 ();
++  double d509 = f1 ();
++  double d510 = f1 ();
++  double d511 = f1 ();
++  double d512 = f1 ();
++  double d513 = f1 ();
++  double d514 = f1 ();
++  double d515 = f1 ();
++  double d516 = f1 ();
++  double d517 = f1 ();
++  double d518 = f1 ();
++  double d519 = f1 ();
++  double d520 = f1 ();
++  double d521 = f1 ();
++  double d522 = f1 ();
++  double d523 = f1 ();
++  double d524 = f1 ();
++  double d525 = f1 ();
++  double d526 = f1 ();
++  double d527 = f1 ();
++  double d528 = f1 ();
++  double d529 = f1 ();
++  double d530 = f1 ();
++  double d531 = f1 ();
++  double d532 = f1 ();
++  double d533 = f1 ();
++  double d534 = f1 ();
++  double d535 = f1 ();
++  double d536 = f1 ();
++  double d537 = f1 ();
++  double d538 = f1 ();
++  double d539 = f1 ();
++  double d540 = f1 ();
++  double d541 = f1 ();
++  double d542 = f1 ();
++  double d543 = f1 ();
++  double d544 = f1 ();
++  double d545 = f1 ();
++  double d546 = f1 ();
++  double d547 = f1 ();
++  double d548 = f1 ();
++  double d549 = f1 ();
++  double d550 = f1 ();
++  double d551 = f1 ();
++  double d552 = f1 ();
++  double d553 = f1 ();
++  double d554 = f1 ();
++  double d555 = f1 ();
++  double d556 = f1 ();
++  double d557 = f1 ();
++  double d558 = f1 ();
++  double d559 = f1 ();
++  double d560 = f1 ();
++  double d561 = f1 ();
++  double d562 = f1 ();
++  double d563 = f1 ();
++  double d564 = f1 ();
++  double d565 = f1 ();
++  double d566 = f1 ();
++  double d567 = f1 ();
++  double d568 = f1 ();
++  double d569 = f1 ();
++  double d570 = f1 ();
++  double d571 = f1 ();
++  double d572 = f1 ();
++  double d573 = f1 ();
++  double d574 = f1 ();
++  double d575 = f1 ();
++  double d576 = f1 ();
++  double d577 = f1 ();
++  double d578 = f1 ();
++  double d579 = f1 ();
++  double d580 = f1 ();
++  double d581 = f1 ();
++  double d582 = f1 ();
++  double d583 = f1 ();
++  double d584 = f1 ();
++  double d585 = f1 ();
++  double d586 = f1 ();
++  double d587 = f1 ();
++  double d588 = f1 ();
++  double d589 = f1 ();
++  double d590 = f1 ();
++  double d591 = f1 ();
++  double d592 = f1 ();
++  double d593 = f1 ();
++  double d594 = f1 ();
++  double d595 = f1 ();
++  double d596 = f1 ();
++  double d597 = f1 ();
++  double d598 = f1 ();
++  double d599 = f1 ();
++  double d600 = f1 ();
++  double d601 = f1 ();
++  double d602 = f1 ();
++  double d603 = f1 ();
++  double d604 = f1 ();
++  double d605 = f1 ();
++  double d606 = f1 ();
++  double d607 = f1 ();
++  double d608 = f1 ();
++  double d609 = f1 ();
++  double d610 = f1 ();
++  double d611 = f1 ();
++  double d612 = f1 ();
++  double d613 = f1 ();
++  double d614 = f1 ();
++  double d615 = f1 ();
++  double d616 = f1 ();
++  double d617 = f1 ();
++  double d618 = f1 ();
++  double d619 = f1 ();
++  double d620 = f1 ();
++  double d621 = f1 ();
++  double d622 = f1 ();
++  double d623 = f1 ();
++  double d624 = f1 ();
++  double d625 = f1 ();
++  double d626 = f1 ();
++  double d627 = f1 ();
++  double d628 = f1 ();
++  double d629 = f1 ();
++  double d630 = f1 ();
++  double d631 = f1 ();
++  double d632 = f1 ();
++  double d633 = f1 ();
++  double d634 = f1 ();
++  double d635 = f1 ();
++  double d636 = f1 ();
++  double d637 = f1 ();
++  double d638 = f1 ();
++  double d639 = f1 ();
++  double d640 = f1 ();
++  double d641 = f1 ();
++  double d642 = f1 ();
++  double d643 = f1 ();
++  double d644 = f1 ();
++  double d645 = f1 ();
++  double d646 = f1 ();
++  double d647 = f1 ();
++  double d648 = f1 ();
++  double d649 = f1 ();
++  double d650 = f1 ();
++  double d651 = f1 ();
++  double d652 = f1 ();
++  double d653 = f1 ();
++  double d654 = f1 ();
++  double d655 = f1 ();
++  double d656 = f1 ();
++  double d657 = f1 ();
++  double d658 = f1 ();
++  double d659 = f1 ();
++  double d660 = f1 ();
++  double d661 = f1 ();
++  double d662 = f1 ();
++  double d663 = f1 ();
++  double d664 = f1 ();
++  double d665 = f1 ();
++  double d666 = f1 ();
++  double d667 = f1 ();
++  double d668 = f1 ();
++  double d669 = f1 ();
++  double d670 = f1 ();
++  double d671 = f1 ();
++  double d672 = f1 ();
++  double d673 = f1 ();
++  double d674 = f1 ();
++  double d675 = f1 ();
++  double d676 = f1 ();
++  double d677 = f1 ();
++  double d678 = f1 ();
++  double d679 = f1 ();
++  double d680 = f1 ();
++  double d681 = f1 ();
++  double d682 = f1 ();
++  double d683 = f1 ();
++  double d684 = f1 ();
++  double d685 = f1 ();
++  double d686 = f1 ();
++  double d687 = f1 ();
++  double d688 = f1 ();
++  double d689 = f1 ();
++  double d690 = f1 ();
++  double d691 = f1 ();
++  double d692 = f1 ();
++  double d693 = f1 ();
++  double d694 = f1 ();
++  double d695 = f1 ();
++  double d696 = f1 ();
++  double d697 = f1 ();
++  double d698 = f1 ();
++  double d699 = f1 ();
++  double d700 = f1 ();
++  double d701 = f1 ();
++  double d702 = f1 ();
++  double d703 = f1 ();
++  double d704 = f1 ();
++  double d705 = f1 ();
++  double d706 = f1 ();
++  double d707 = f1 ();
++  double d708 = f1 ();
++  double d709 = f1 ();
++  double d710 = f1 ();
++  double d711 = f1 ();
++  double d712 = f1 ();
++  double d713 = f1 ();
++  double d714 = f1 ();
++  double d715 = f1 ();
++  double d716 = f1 ();
++  double d717 = f1 ();
++  double d718 = f1 ();
++  double d719 = f1 ();
++  double d720 = f1 ();
++  double d721 = f1 ();
++  double d722 = f1 ();
++  double d723 = f1 ();
++  double d724 = f1 ();
++  double d725 = f1 ();
++  double d726 = f1 ();
++  double d727 = f1 ();
++  double d728 = f1 ();
++  double d729 = f1 ();
++  double d730 = f1 ();
++  double d731 = f1 ();
++  double d732 = f1 ();
++  double d733 = f1 ();
++  double d734 = f1 ();
++  double d735 = f1 ();
++  double d736 = f1 ();
++  double d737 = f1 ();
++  double d738 = f1 ();
++  double d739 = f1 ();
++  double d740 = f1 ();
++  double d741 = f1 ();
++  double d742 = f1 ();
++  double d743 = f1 ();
++  double d744 = f1 ();
++  double d745 = f1 ();
++  double d746 = f1 ();
++  double d747 = f1 ();
++  double d748 = f1 ();
++  double d749 = f1 ();
++  double d750 = f1 ();
++  double d751 = f1 ();
++  double d752 = f1 ();
++  double d753 = f1 ();
++  double d754 = f1 ();
++  double d755 = f1 ();
++  double d756 = f1 ();
++  double d757 = f1 ();
++  double d758 = f1 ();
++  double d759 = f1 ();
++  double d760 = f1 ();
++  double d761 = f1 ();
++  double d762 = f1 ();
++  double d763 = f1 ();
++  double d764 = f1 ();
++  double d765 = f1 ();
++  double d766 = f1 ();
++  double d767 = f1 ();
++  double d768 = f1 ();
++  double d769 = f1 ();
++  double d770 = f1 ();
++  double d771 = f1 ();
++  double d772 = f1 ();
++  double d773 = f1 ();
++  double d774 = f1 ();
++  double d775 = f1 ();
++  double d776 = f1 ();
++  double d777 = f1 ();
++  double d778 = f1 ();
++  double d779 = f1 ();
++  double d780 = f1 ();
++  double d781 = f1 ();
++  double d782 = f1 ();
++  double d783 = f1 ();
++  double d784 = f1 ();
++  double d785 = f1 ();
++  double d786 = f1 ();
++  double d787 = f1 ();
++  double d788 = f1 ();
++  double d789 = f1 ();
++  double d790 = f1 ();
++  double d791 = f1 ();
++  double d792 = f1 ();
++  double d793 = f1 ();
++  double d794 = f1 ();
++  double d795 = f1 ();
++  double d796 = f1 ();
++  double d797 = f1 ();
++  double d798 = f1 ();
++  double d799 = f1 ();
++  double d800 = f1 ();
++  double d801 = f1 ();
++  double d802 = f1 ();
++  double d803 = f1 ();
++  double d804 = f1 ();
++  double d805 = f1 ();
++  double d806 = f1 ();
++  double d807 = f1 ();
++  double d808 = f1 ();
++  double d809 = f1 ();
++  double d810 = f1 ();
++  double d811 = f1 ();
++  double d812 = f1 ();
++  double d813 = f1 ();
++  double d814 = f1 ();
++  double d815 = f1 ();
++  double d816 = f1 ();
++  double d817 = f1 ();
++  double d818 = f1 ();
++  double d819 = f1 ();
++  double d820 = f1 ();
++  double d821 = f1 ();
++  double d822 = f1 ();
++  double d823 = f1 ();
++  double d824 = f1 ();
++  double d825 = f1 ();
++  double d826 = f1 ();
++  double d827 = f1 ();
++  double d828 = f1 ();
++  double d829 = f1 ();
++  double d830 = f1 ();
++  double d831 = f1 ();
++  double d832 = f1 ();
++  double d833 = f1 ();
++  double d834 = f1 ();
++  double d835 = f1 ();
++  double d836 = f1 ();
++  double d837 = f1 ();
++  double d838 = f1 ();
++  double d839 = f1 ();
++  double d840 = f1 ();
++  double d841 = f1 ();
++  double d842 = f1 ();
++  double d843 = f1 ();
++  double d844 = f1 ();
++  double d845 = f1 ();
++  double d846 = f1 ();
++  double d847 = f1 ();
++  double d848 = f1 ();
++  double d849 = f1 ();
++  double d850 = f1 ();
++  double d851 = f1 ();
++  double d852 = f1 ();
++  double d853 = f1 ();
++  double d854 = f1 ();
++  double d855 = f1 ();
++  double d856 = f1 ();
++  double d857 = f1 ();
++  double d858 = f1 ();
++  double d859 = f1 ();
++  double d860 = f1 ();
++  double d861 = f1 ();
++  double d862 = f1 ();
++  double d863 = f1 ();
++  double d864 = f1 ();
++  double d865 = f1 ();
++  double d866 = f1 ();
++  double d867 = f1 ();
++  double d868 = f1 ();
++  double d869 = f1 ();
++  double d870 = f1 ();
++  double d871 = f1 ();
++  double d872 = f1 ();
++  double d873 = f1 ();
++  double d874 = f1 ();
++  double d875 = f1 ();
++  double d876 = f1 ();
++  double d877 = f1 ();
++  double d878 = f1 ();
++  double d879 = f1 ();
++  double d880 = f1 ();
++  double d881 = f1 ();
++  double d882 = f1 ();
++  double d883 = f1 ();
++  double d884 = f1 ();
++  double d885 = f1 ();
++  double d886 = f1 ();
++  double d887 = f1 ();
++  double d888 = f1 ();
++  double d889 = f1 ();
++  double d890 = f1 ();
++  double d891 = f1 ();
++  double d892 = f1 ();
++  double d893 = f1 ();
++  double d894 = f1 ();
++  double d895 = f1 ();
++  double d896 = f1 ();
++  double d897 = f1 ();
++  double d898 = f1 ();
++  double d899 = f1 ();
++  double d900 = f1 ();
++  double d901 = f1 ();
++  double d902 = f1 ();
++  double d903 = f1 ();
++  double d904 = f1 ();
++  double d905 = f1 ();
++  double d906 = f1 ();
++  double d907 = f1 ();
++  double d908 = f1 ();
++  double d909 = f1 ();
++  double d910 = f1 ();
++  double d911 = f1 ();
++  double d912 = f1 ();
++  double d913 = f1 ();
++  double d914 = f1 ();
++  double d915 = f1 ();
++  double d916 = f1 ();
++  double d917 = f1 ();
++  double d918 = f1 ();
++  double d919 = f1 ();
++  double d920 = f1 ();
++  double d921 = f1 ();
++  double d922 = f1 ();
++  double d923 = f1 ();
++  double d924 = f1 ();
++  double d925 = f1 ();
++  double d926 = f1 ();
++  double d927 = f1 ();
++  double d928 = f1 ();
++  double d929 = f1 ();
++  double d930 = f1 ();
++  double d931 = f1 ();
++  double d932 = f1 ();
++  double d933 = f1 ();
++  double d934 = f1 ();
++  double d935 = f1 ();
++  double d936 = f1 ();
++  double d937 = f1 ();
++  double d938 = f1 ();
++  double d939 = f1 ();
++  double d940 = f1 ();
++  double d941 = f1 ();
++  double d942 = f1 ();
++  double d943 = f1 ();
++  double d944 = f1 ();
++  double d945 = f1 ();
++  double d946 = f1 ();
++  double d947 = f1 ();
++  double d948 = f1 ();
++  double d949 = f1 ();
++  double d950 = f1 ();
++  double d951 = f1 ();
++  double d952 = f1 ();
++  double d953 = f1 ();
++  double d954 = f1 ();
++  double d955 = f1 ();
++  double d956 = f1 ();
++  double d957 = f1 ();
++  double d958 = f1 ();
++  double d959 = f1 ();
++  double d960 = f1 ();
++  double d961 = f1 ();
++  double d962 = f1 ();
++  double d963 = f1 ();
++  double d964 = f1 ();
++  double d965 = f1 ();
++  double d966 = f1 ();
++  double d967 = f1 ();
++  double d968 = f1 ();
++  double d969 = f1 ();
++  double d970 = f1 ();
++  double d971 = f1 ();
++  double d972 = f1 ();
++  double d973 = f1 ();
++  double d974 = f1 ();
++  double d975 = f1 ();
++  double d976 = f1 ();
++  double d977 = f1 ();
++  double d978 = f1 ();
++  double d979 = f1 ();
++  double d980 = f1 ();
++  double d981 = f1 ();
++  double d982 = f1 ();
++  double d983 = f1 ();
++  double d984 = f1 ();
++  double d985 = f1 ();
++  double d986 = f1 ();
++  double d987 = f1 ();
++  double d988 = f1 ();
++  double d989 = f1 ();
++  double d990 = f1 ();
++  double d991 = f1 ();
++  double d992 = f1 ();
++  double d993 = f1 ();
++  double d994 = f1 ();
++  double d995 = f1 ();
++  double d996 = f1 ();
++  double d997 = f1 ();
++  double d998 = f1 ();
++  double d999 = f1 ();
++
++  double x = 0;
++  x = f2 (x, d000);
++  x = f2 (x, d001);
++  x = f2 (x, d002);
++  x = f2 (x, d003);
++  x = f2 (x, d004);
++  x = f2 (x, d005);
++  x = f2 (x, d006);
++  x = f2 (x, d007);
++  x = f2 (x, d008);
++  x = f2 (x, d009);
++  x = f2 (x, d010);
++  x = f2 (x, d011);
++  x = f2 (x, d012);
++  x = f2 (x, d013);
++  x = f2 (x, d014);
++  x = f2 (x, d015);
++  x = f2 (x, d016);
++  x = f2 (x, d017);
++  x = f2 (x, d018);
++  x = f2 (x, d019);
++  x = f2 (x, d020);
++  x = f2 (x, d021);
++  x = f2 (x, d022);
++  x = f2 (x, d023);
++  x = f2 (x, d024);
++  x = f2 (x, d025);
++  x = f2 (x, d026);
++  x = f2 (x, d027);
++  x = f2 (x, d028);
++  x = f2 (x, d029);
++  x = f2 (x, d030);
++  x = f2 (x, d031);
++  x = f2 (x, d032);
++  x = f2 (x, d033);
++  x = f2 (x, d034);
++  x = f2 (x, d035);
++  x = f2 (x, d036);
++  x = f2 (x, d037);
++  x = f2 (x, d038);
++  x = f2 (x, d039);
++  x = f2 (x, d040);
++  x = f2 (x, d041);
++  x = f2 (x, d042);
++  x = f2 (x, d043);
++  x = f2 (x, d044);
++  x = f2 (x, d045);
++  x = f2 (x, d046);
++  x = f2 (x, d047);
++  x = f2 (x, d048);
++  x = f2 (x, d049);
++  x = f2 (x, d050);
++  x = f2 (x, d051);
++  x = f2 (x, d052);
++  x = f2 (x, d053);
++  x = f2 (x, d054);
++  x = f2 (x, d055);
++  x = f2 (x, d056);
++  x = f2 (x, d057);
++  x = f2 (x, d058);
++  x = f2 (x, d059);
++  x = f2 (x, d060);
++  x = f2 (x, d061);
++  x = f2 (x, d062);
++  x = f2 (x, d063);
++  x = f2 (x, d064);
++  x = f2 (x, d065);
++  x = f2 (x, d066);
++  x = f2 (x, d067);
++  x = f2 (x, d068);
++  x = f2 (x, d069);
++  x = f2 (x, d070);
++  x = f2 (x, d071);
++  x = f2 (x, d072);
++  x = f2 (x, d073);
++  x = f2 (x, d074);
++  x = f2 (x, d075);
++  x = f2 (x, d076);
++  x = f2 (x, d077);
++  x = f2 (x, d078);
++  x = f2 (x, d079);
++  x = f2 (x, d080);
++  x = f2 (x, d081);
++  x = f2 (x, d082);
++  x = f2 (x, d083);
++  x = f2 (x, d084);
++  x = f2 (x, d085);
++  x = f2 (x, d086);
++  x = f2 (x, d087);
++  x = f2 (x, d088);
++  x = f2 (x, d089);
++  x = f2 (x, d090);
++  x = f2 (x, d091);
++  x = f2 (x, d092);
++  x = f2 (x, d093);
++  x = f2 (x, d094);
++  x = f2 (x, d095);
++  x = f2 (x, d096);
++  x = f2 (x, d097);
++  x = f2 (x, d098);
++  x = f2 (x, d099);
++  x = f2 (x, d100);
++  x = f2 (x, d101);
++  x = f2 (x, d102);
++  x = f2 (x, d103);
++  x = f2 (x, d104);
++  x = f2 (x, d105);
++  x = f2 (x, d106);
++  x = f2 (x, d107);
++  x = f2 (x, d108);
++  x = f2 (x, d109);
++  x = f2 (x, d110);
++  x = f2 (x, d111);
++  x = f2 (x, d112);
++  x = f2 (x, d113);
++  x = f2 (x, d114);
++  x = f2 (x, d115);
++  x = f2 (x, d116);
++  x = f2 (x, d117);
++  x = f2 (x, d118);
++  x = f2 (x, d119);
++  x = f2 (x, d120);
++  x = f2 (x, d121);
++  x = f2 (x, d122);
++  x = f2 (x, d123);
++  x = f2 (x, d124);
++  x = f2 (x, d125);
++  x = f2 (x, d126);
++  x = f2 (x, d127);
++  x = f2 (x, d128);
++  x = f2 (x, d129);
++  x = f2 (x, d130);
++  x = f2 (x, d131);
++  x = f2 (x, d132);
++  x = f2 (x, d133);
++  x = f2 (x, d134);
++  x = f2 (x, d135);
++  x = f2 (x, d136);
++  x = f2 (x, d137);
++  x = f2 (x, d138);
++  x = f2 (x, d139);
++  x = f2 (x, d140);
++  x = f2 (x, d141);
++  x = f2 (x, d142);
++  x = f2 (x, d143);
++  x = f2 (x, d144);
++  x = f2 (x, d145);
++  x = f2 (x, d146);
++  x = f2 (x, d147);
++  x = f2 (x, d148);
++  x = f2 (x, d149);
++  x = f2 (x, d150);
++  x = f2 (x, d151);
++  x = f2 (x, d152);
++  x = f2 (x, d153);
++  x = f2 (x, d154);
++  x = f2 (x, d155);
++  x = f2 (x, d156);
++  x = f2 (x, d157);
++  x = f2 (x, d158);
++  x = f2 (x, d159);
++  x = f2 (x, d160);
++  x = f2 (x, d161);
++  x = f2 (x, d162);
++  x = f2 (x, d163);
++  x = f2 (x, d164);
++  x = f2 (x, d165);
++  x = f2 (x, d166);
++  x = f2 (x, d167);
++  x = f2 (x, d168);
++  x = f2 (x, d169);
++  x = f2 (x, d170);
++  x = f2 (x, d171);
++  x = f2 (x, d172);
++  x = f2 (x, d173);
++  x = f2 (x, d174);
++  x = f2 (x, d175);
++  x = f2 (x, d176);
++  x = f2 (x, d177);
++  x = f2 (x, d178);
++  x = f2 (x, d179);
++  x = f2 (x, d180);
++  x = f2 (x, d181);
++  x = f2 (x, d182);
++  x = f2 (x, d183);
++  x = f2 (x, d184);
++  x = f2 (x, d185);
++  x = f2 (x, d186);
++  x = f2 (x, d187);
++  x = f2 (x, d188);
++  x = f2 (x, d189);
++  x = f2 (x, d190);
++  x = f2 (x, d191);
++  x = f2 (x, d192);
++  x = f2 (x, d193);
++  x = f2 (x, d194);
++  x = f2 (x, d195);
++  x = f2 (x, d196);
++  x = f2 (x, d197);
++  x = f2 (x, d198);
++  x = f2 (x, d199);
++  x = f2 (x, d200);
++  x = f2 (x, d201);
++  x = f2 (x, d202);
++  x = f2 (x, d203);
++  x = f2 (x, d204);
++  x = f2 (x, d205);
++  x = f2 (x, d206);
++  x = f2 (x, d207);
++  x = f2 (x, d208);
++  x = f2 (x, d209);
++  x = f2 (x, d210);
++  x = f2 (x, d211);
++  x = f2 (x, d212);
++  x = f2 (x, d213);
++  x = f2 (x, d214);
++  x = f2 (x, d215);
++  x = f2 (x, d216);
++  x = f2 (x, d217);
++  x = f2 (x, d218);
++  x = f2 (x, d219);
++  x = f2 (x, d220);
++  x = f2 (x, d221);
++  x = f2 (x, d222);
++  x = f2 (x, d223);
++  x = f2 (x, d224);
++  x = f2 (x, d225);
++  x = f2 (x, d226);
++  x = f2 (x, d227);
++  x = f2 (x, d228);
++  x = f2 (x, d229);
++  x = f2 (x, d230);
++  x = f2 (x, d231);
++  x = f2 (x, d232);
++  x = f2 (x, d233);
++  x = f2 (x, d234);
++  x = f2 (x, d235);
++  x = f2 (x, d236);
++  x = f2 (x, d237);
++  x = f2 (x, d238);
++  x = f2 (x, d239);
++  x = f2 (x, d240);
++  x = f2 (x, d241);
++  x = f2 (x, d242);
++  x = f2 (x, d243);
++  x = f2 (x, d244);
++  x = f2 (x, d245);
++  x = f2 (x, d246);
++  x = f2 (x, d247);
++  x = f2 (x, d248);
++  x = f2 (x, d249);
++  x = f2 (x, d250);
++  x = f2 (x, d251);
++  x = f2 (x, d252);
++  x = f2 (x, d253);
++  x = f2 (x, d254);
++  x = f2 (x, d255);
++  x = f2 (x, d256);
++  x = f2 (x, d257);
++  x = f2 (x, d258);
++  x = f2 (x, d259);
++  x = f2 (x, d260);
++  x = f2 (x, d261);
++  x = f2 (x, d262);
++  x = f2 (x, d263);
++  x = f2 (x, d264);
++  x = f2 (x, d265);
++  x = f2 (x, d266);
++  x = f2 (x, d267);
++  x = f2 (x, d268);
++  x = f2 (x, d269);
++  x = f2 (x, d270);
++  x = f2 (x, d271);
++  x = f2 (x, d272);
++  x = f2 (x, d273);
++  x = f2 (x, d274);
++  x = f2 (x, d275);
++  x = f2 (x, d276);
++  x = f2 (x, d277);
++  x = f2 (x, d278);
++  x = f2 (x, d279);
++  x = f2 (x, d280);
++  x = f2 (x, d281);
++  x = f2 (x, d282);
++  x = f2 (x, d283);
++  x = f2 (x, d284);
++  x = f2 (x, d285);
++  x = f2 (x, d286);
++  x = f2 (x, d287);
++  x = f2 (x, d288);
++  x = f2 (x, d289);
++  x = f2 (x, d290);
++  x = f2 (x, d291);
++  x = f2 (x, d292);
++  x = f2 (x, d293);
++  x = f2 (x, d294);
++  x = f2 (x, d295);
++  x = f2 (x, d296);
++  x = f2 (x, d297);
++  x = f2 (x, d298);
++  x = f2 (x, d299);
++  x = f2 (x, d300);
++  x = f2 (x, d301);
++  x = f2 (x, d302);
++  x = f2 (x, d303);
++  x = f2 (x, d304);
++  x = f2 (x, d305);
++  x = f2 (x, d306);
++  x = f2 (x, d307);
++  x = f2 (x, d308);
++  x = f2 (x, d309);
++  x = f2 (x, d310);
++  x = f2 (x, d311);
++  x = f2 (x, d312);
++  x = f2 (x, d313);
++  x = f2 (x, d314);
++  x = f2 (x, d315);
++  x = f2 (x, d316);
++  x = f2 (x, d317);
++  x = f2 (x, d318);
++  x = f2 (x, d319);
++  x = f2 (x, d320);
++  x = f2 (x, d321);
++  x = f2 (x, d322);
++  x = f2 (x, d323);
++  x = f2 (x, d324);
++  x = f2 (x, d325);
++  x = f2 (x, d326);
++  x = f2 (x, d327);
++  x = f2 (x, d328);
++  x = f2 (x, d329);
++  x = f2 (x, d330);
++  x = f2 (x, d331);
++  x = f2 (x, d332);
++  x = f2 (x, d333);
++  x = f2 (x, d334);
++  x = f2 (x, d335);
++  x = f2 (x, d336);
++  x = f2 (x, d337);
++  x = f2 (x, d338);
++  x = f2 (x, d339);
++  x = f2 (x, d340);
++  x = f2 (x, d341);
++  x = f2 (x, d342);
++  x = f2 (x, d343);
++  x = f2 (x, d344);
++  x = f2 (x, d345);
++  x = f2 (x, d346);
++  x = f2 (x, d347);
++  x = f2 (x, d348);
++  x = f2 (x, d349);
++  x = f2 (x, d350);
++  x = f2 (x, d351);
++  x = f2 (x, d352);
++  x = f2 (x, d353);
++  x = f2 (x, d354);
++  x = f2 (x, d355);
++  x = f2 (x, d356);
++  x = f2 (x, d357);
++  x = f2 (x, d358);
++  x = f2 (x, d359);
++  x = f2 (x, d360);
++  x = f2 (x, d361);
++  x = f2 (x, d362);
++  x = f2 (x, d363);
++  x = f2 (x, d364);
++  x = f2 (x, d365);
++  x = f2 (x, d366);
++  x = f2 (x, d367);
++  x = f2 (x, d368);
++  x = f2 (x, d369);
++  x = f2 (x, d370);
++  x = f2 (x, d371);
++  x = f2 (x, d372);
++  x = f2 (x, d373);
++  x = f2 (x, d374);
++  x = f2 (x, d375);
++  x = f2 (x, d376);
++  x = f2 (x, d377);
++  x = f2 (x, d378);
++  x = f2 (x, d379);
++  x = f2 (x, d380);
++  x = f2 (x, d381);
++  x = f2 (x, d382);
++  x = f2 (x, d383);
++  x = f2 (x, d384);
++  x = f2 (x, d385);
++  x = f2 (x, d386);
++  x = f2 (x, d387);
++  x = f2 (x, d388);
++  x = f2 (x, d389);
++  x = f2 (x, d390);
++  x = f2 (x, d391);
++  x = f2 (x, d392);
++  x = f2 (x, d393);
++  x = f2 (x, d394);
++  x = f2 (x, d395);
++  x = f2 (x, d396);
++  x = f2 (x, d397);
++  x = f2 (x, d398);
++  x = f2 (x, d399);
++  x = f2 (x, d400);
++  x = f2 (x, d401);
++  x = f2 (x, d402);
++  x = f2 (x, d403);
++  x = f2 (x, d404);
++  x = f2 (x, d405);
++  x = f2 (x, d406);
++  x = f2 (x, d407);
++  x = f2 (x, d408);
++  x = f2 (x, d409);
++  x = f2 (x, d410);
++  x = f2 (x, d411);
++  x = f2 (x, d412);
++  x = f2 (x, d413);
++  x = f2 (x, d414);
++  x = f2 (x, d415);
++  x = f2 (x, d416);
++  x = f2 (x, d417);
++  x = f2 (x, d418);
++  x = f2 (x, d419);
++  x = f2 (x, d420);
++  x = f2 (x, d421);
++  x = f2 (x, d422);
++  x = f2 (x, d423);
++  x = f2 (x, d424);
++  x = f2 (x, d425);
++  x = f2 (x, d426);
++  x = f2 (x, d427);
++  x = f2 (x, d428);
++  x = f2 (x, d429);
++  x = f2 (x, d430);
++  x = f2 (x, d431);
++  x = f2 (x, d432);
++  x = f2 (x, d433);
++  x = f2 (x, d434);
++  x = f2 (x, d435);
++  x = f2 (x, d436);
++  x = f2 (x, d437);
++  x = f2 (x, d438);
++  x = f2 (x, d439);
++  x = f2 (x, d440);
++  x = f2 (x, d441);
++  x = f2 (x, d442);
++  x = f2 (x, d443);
++  x = f2 (x, d444);
++  x = f2 (x, d445);
++  x = f2 (x, d446);
++  x = f2 (x, d447);
++  x = f2 (x, d448);
++  x = f2 (x, d449);
++  x = f2 (x, d450);
++  x = f2 (x, d451);
++  x = f2 (x, d452);
++  x = f2 (x, d453);
++  x = f2 (x, d454);
++  x = f2 (x, d455);
++  x = f2 (x, d456);
++  x = f2 (x, d457);
++  x = f2 (x, d458);
++  x = f2 (x, d459);
++  x = f2 (x, d460);
++  x = f2 (x, d461);
++  x = f2 (x, d462);
++  x = f2 (x, d463);
++  x = f2 (x, d464);
++  x = f2 (x, d465);
++  x = f2 (x, d466);
++  x = f2 (x, d467);
++  x = f2 (x, d468);
++  x = f2 (x, d469);
++  x = f2 (x, d470);
++  x = f2 (x, d471);
++  x = f2 (x, d472);
++  x = f2 (x, d473);
++  x = f2 (x, d474);
++  x = f2 (x, d475);
++  x = f2 (x, d476);
++  x = f2 (x, d477);
++  x = f2 (x, d478);
++  x = f2 (x, d479);
++  x = f2 (x, d480);
++  x = f2 (x, d481);
++  x = f2 (x, d482);
++  x = f2 (x, d483);
++  x = f2 (x, d484);
++  x = f2 (x, d485);
++  x = f2 (x, d486);
++  x = f2 (x, d487);
++  x = f2 (x, d488);
++  x = f2 (x, d489);
++  x = f2 (x, d490);
++  x = f2 (x, d491);
++  x = f2 (x, d492);
++  x = f2 (x, d493);
++  x = f2 (x, d494);
++  x = f2 (x, d495);
++  x = f2 (x, d496);
++  x = f2 (x, d497);
++  x = f2 (x, d498);
++  x = f2 (x, d499);
++  x = f2 (x, d500);
++  x = f2 (x, d501);
++  x = f2 (x, d502);
++  x = f2 (x, d503);
++  x = f2 (x, d504);
++  x = f2 (x, d505);
++  x = f2 (x, d506);
++  x = f2 (x, d507);
++  x = f2 (x, d508);
++  x = f2 (x, d509);
++  x = f2 (x, d510);
++  x = f2 (x, d511);
++  x = f2 (x, d512);
++  x = f2 (x, d513);
++  x = f2 (x, d514);
++  x = f2 (x, d515);
++  x = f2 (x, d516);
++  x = f2 (x, d517);
++  x = f2 (x, d518);
++  x = f2 (x, d519);
++  x = f2 (x, d520);
++  x = f2 (x, d521);
++  x = f2 (x, d522);
++  x = f2 (x, d523);
++  x = f2 (x, d524);
++  x = f2 (x, d525);
++  x = f2 (x, d526);
++  x = f2 (x, d527);
++  x = f2 (x, d528);
++  x = f2 (x, d529);
++  x = f2 (x, d530);
++  x = f2 (x, d531);
++  x = f2 (x, d532);
++  x = f2 (x, d533);
++  x = f2 (x, d534);
++  x = f2 (x, d535);
++  x = f2 (x, d536);
++  x = f2 (x, d537);
++  x = f2 (x, d538);
++  x = f2 (x, d539);
++  x = f2 (x, d540);
++  x = f2 (x, d541);
++  x = f2 (x, d542);
++  x = f2 (x, d543);
++  x = f2 (x, d544);
++  x = f2 (x, d545);
++  x = f2 (x, d546);
++  x = f2 (x, d547);
++  x = f2 (x, d548);
++  x = f2 (x, d549);
++  x = f2 (x, d550);
++  x = f2 (x, d551);
++  x = f2 (x, d552);
++  x = f2 (x, d553);
++  x = f2 (x, d554);
++  x = f2 (x, d555);
++  x = f2 (x, d556);
++  x = f2 (x, d557);
++  x = f2 (x, d558);
++  x = f2 (x, d559);
++  x = f2 (x, d560);
++  x = f2 (x, d561);
++  x = f2 (x, d562);
++  x = f2 (x, d563);
++  x = f2 (x, d564);
++  x = f2 (x, d565);
++  x = f2 (x, d566);
++  x = f2 (x, d567);
++  x = f2 (x, d568);
++  x = f2 (x, d569);
++  x = f2 (x, d570);
++  x = f2 (x, d571);
++  x = f2 (x, d572);
++  x = f2 (x, d573);
++  x = f2 (x, d574);
++  x = f2 (x, d575);
++  x = f2 (x, d576);
++  x = f2 (x, d577);
++  x = f2 (x, d578);
++  x = f2 (x, d579);
++  x = f2 (x, d580);
++  x = f2 (x, d581);
++  x = f2 (x, d582);
++  x = f2 (x, d583);
++  x = f2 (x, d584);
++  x = f2 (x, d585);
++  x = f2 (x, d586);
++  x = f2 (x, d587);
++  x = f2 (x, d588);
++  x = f2 (x, d589);
++  x = f2 (x, d590);
++  x = f2 (x, d591);
++  x = f2 (x, d592);
++  x = f2 (x, d593);
++  x = f2 (x, d594);
++  x = f2 (x, d595);
++  x = f2 (x, d596);
++  x = f2 (x, d597);
++  x = f2 (x, d598);
++  x = f2 (x, d599);
++  x = f2 (x, d600);
++  x = f2 (x, d601);
++  x = f2 (x, d602);
++  x = f2 (x, d603);
++  x = f2 (x, d604);
++  x = f2 (x, d605);
++  x = f2 (x, d606);
++  x = f2 (x, d607);
++  x = f2 (x, d608);
++  x = f2 (x, d609);
++  x = f2 (x, d610);
++  x = f2 (x, d611);
++  x = f2 (x, d612);
++  x = f2 (x, d613);
++  x = f2 (x, d614);
++  x = f2 (x, d615);
++  x = f2 (x, d616);
++  x = f2 (x, d617);
++  x = f2 (x, d618);
++  x = f2 (x, d619);
++  x = f2 (x, d620);
++  x = f2 (x, d621);
++  x = f2 (x, d622);
++  x = f2 (x, d623);
++  x = f2 (x, d624);
++  x = f2 (x, d625);
++  x = f2 (x, d626);
++  x = f2 (x, d627);
++  x = f2 (x, d628);
++  x = f2 (x, d629);
++  x = f2 (x, d630);
++  x = f2 (x, d631);
++  x = f2 (x, d632);
++  x = f2 (x, d633);
++  x = f2 (x, d634);
++  x = f2 (x, d635);
++  x = f2 (x, d636);
++  x = f2 (x, d637);
++  x = f2 (x, d638);
++  x = f2 (x, d639);
++  x = f2 (x, d640);
++  x = f2 (x, d641);
++  x = f2 (x, d642);
++  x = f2 (x, d643);
++  x = f2 (x, d644);
++  x = f2 (x, d645);
++  x = f2 (x, d646);
++  x = f2 (x, d647);
++  x = f2 (x, d648);
++  x = f2 (x, d649);
++  x = f2 (x, d650);
++  x = f2 (x, d651);
++  x = f2 (x, d652);
++  x = f2 (x, d653);
++  x = f2 (x, d654);
++  x = f2 (x, d655);
++  x = f2 (x, d656);
++  x = f2 (x, d657);
++  x = f2 (x, d658);
++  x = f2 (x, d659);
++  x = f2 (x, d660);
++  x = f2 (x, d661);
++  x = f2 (x, d662);
++  x = f2 (x, d663);
++  x = f2 (x, d664);
++  x = f2 (x, d665);
++  x = f2 (x, d666);
++  x = f2 (x, d667);
++  x = f2 (x, d668);
++  x = f2 (x, d669);
++  x = f2 (x, d670);
++  x = f2 (x, d671);
++  x = f2 (x, d672);
++  x = f2 (x, d673);
++  x = f2 (x, d674);
++  x = f2 (x, d675);
++  x = f2 (x, d676);
++  x = f2 (x, d677);
++  x = f2 (x, d678);
++  x = f2 (x, d679);
++  x = f2 (x, d680);
++  x = f2 (x, d681);
++  x = f2 (x, d682);
++  x = f2 (x, d683);
++  x = f2 (x, d684);
++  x = f2 (x, d685);
++  x = f2 (x, d686);
++  x = f2 (x, d687);
++  x = f2 (x, d688);
++  x = f2 (x, d689);
++  x = f2 (x, d690);
++  x = f2 (x, d691);
++  x = f2 (x, d692);
++  x = f2 (x, d693);
++  x = f2 (x, d694);
++  x = f2 (x, d695);
++  x = f2 (x, d696);
++  x = f2 (x, d697);
++  x = f2 (x, d698);
++  x = f2 (x, d699);
++  x = f2 (x, d700);
++  x = f2 (x, d701);
++  x = f2 (x, d702);
++  x = f2 (x, d703);
++  x = f2 (x, d704);
++  x = f2 (x, d705);
++  x = f2 (x, d706);
++  x = f2 (x, d707);
++  x = f2 (x, d708);
++  x = f2 (x, d709);
++  x = f2 (x, d710);
++  x = f2 (x, d711);
++  x = f2 (x, d712);
++  x = f2 (x, d713);
++  x = f2 (x, d714);
++  x = f2 (x, d715);
++  x = f2 (x, d716);
++  x = f2 (x, d717);
++  x = f2 (x, d718);
++  x = f2 (x, d719);
++  x = f2 (x, d720);
++  x = f2 (x, d721);
++  x = f2 (x, d722);
++  x = f2 (x, d723);
++  x = f2 (x, d724);
++  x = f2 (x, d725);
++  x = f2 (x, d726);
++  x = f2 (x, d727);
++  x = f2 (x, d728);
++  x = f2 (x, d729);
++  x = f2 (x, d730);
++  x = f2 (x, d731);
++  x = f2 (x, d732);
++  x = f2 (x, d733);
++  x = f2 (x, d734);
++  x = f2 (x, d735);
++  x = f2 (x, d736);
++  x = f2 (x, d737);
++  x = f2 (x, d738);
++  x = f2 (x, d739);
++  x = f2 (x, d740);
++  x = f2 (x, d741);
++  x = f2 (x, d742);
++  x = f2 (x, d743);
++  x = f2 (x, d744);
++  x = f2 (x, d745);
++  x = f2 (x, d746);
++  x = f2 (x, d747);
++  x = f2 (x, d748);
++  x = f2 (x, d749);
++  x = f2 (x, d750);
++  x = f2 (x, d751);
++  x = f2 (x, d752);
++  x = f2 (x, d753);
++  x = f2 (x, d754);
++  x = f2 (x, d755);
++  x = f2 (x, d756);
++  x = f2 (x, d757);
++  x = f2 (x, d758);
++  x = f2 (x, d759);
++  x = f2 (x, d760);
++  x = f2 (x, d761);
++  x = f2 (x, d762);
++  x = f2 (x, d763);
++  x = f2 (x, d764);
++  x = f2 (x, d765);
++  x = f2 (x, d766);
++  x = f2 (x, d767);
++  x = f2 (x, d768);
++  x = f2 (x, d769);
++  x = f2 (x, d770);
++  x = f2 (x, d771);
++  x = f2 (x, d772);
++  x = f2 (x, d773);
++  x = f2 (x, d774);
++  x = f2 (x, d775);
++  x = f2 (x, d776);
++  x = f2 (x, d777);
++  x = f2 (x, d778);
++  x = f2 (x, d779);
++  x = f2 (x, d780);
++  x = f2 (x, d781);
++  x = f2 (x, d782);
++  x = f2 (x, d783);
++  x = f2 (x, d784);
++  x = f2 (x, d785);
++  x = f2 (x, d786);
++  x = f2 (x, d787);
++  x = f2 (x, d788);
++  x = f2 (x, d789);
++  x = f2 (x, d790);
++  x = f2 (x, d791);
++  x = f2 (x, d792);
++  x = f2 (x, d793);
++  x = f2 (x, d794);
++  x = f2 (x, d795);
++  x = f2 (x, d796);
++  x = f2 (x, d797);
++  x = f2 (x, d798);
++  x = f2 (x, d799);
++  x = f2 (x, d800);
++  x = f2 (x, d801);
++  x = f2 (x, d802);
++  x = f2 (x, d803);
++  x = f2 (x, d804);
++  x = f2 (x, d805);
++  x = f2 (x, d806);
++  x = f2 (x, d807);
++  x = f2 (x, d808);
++  x = f2 (x, d809);
++  x = f2 (x, d810);
++  x = f2 (x, d811);
++  x = f2 (x, d812);
++  x = f2 (x, d813);
++  x = f2 (x, d814);
++  x = f2 (x, d815);
++  x = f2 (x, d816);
++  x = f2 (x, d817);
++  x = f2 (x, d818);
++  x = f2 (x, d819);
++  x = f2 (x, d820);
++  x = f2 (x, d821);
++  x = f2 (x, d822);
++  x = f2 (x, d823);
++  x = f2 (x, d824);
++  x = f2 (x, d825);
++  x = f2 (x, d826);
++  x = f2 (x, d827);
++  x = f2 (x, d828);
++  x = f2 (x, d829);
++  x = f2 (x, d830);
++  x = f2 (x, d831);
++  x = f2 (x, d832);
++  x = f2 (x, d833);
++  x = f2 (x, d834);
++  x = f2 (x, d835);
++  x = f2 (x, d836);
++  x = f2 (x, d837);
++  x = f2 (x, d838);
++  x = f2 (x, d839);
++  x = f2 (x, d840);
++  x = f2 (x, d841);
++  x = f2 (x, d842);
++  x = f2 (x, d843);
++  x = f2 (x, d844);
++  x = f2 (x, d845);
++  x = f2 (x, d846);
++  x = f2 (x, d847);
++  x = f2 (x, d848);
++  x = f2 (x, d849);
++  x = f2 (x, d850);
++  x = f2 (x, d851);
++  x = f2 (x, d852);
++  x = f2 (x, d853);
++  x = f2 (x, d854);
++  x = f2 (x, d855);
++  x = f2 (x, d856);
++  x = f2 (x, d857);
++  x = f2 (x, d858);
++  x = f2 (x, d859);
++  x = f2 (x, d860);
++  x = f2 (x, d861);
++  x = f2 (x, d862);
++  x = f2 (x, d863);
++  x = f2 (x, d864);
++  x = f2 (x, d865);
++  x = f2 (x, d866);
++  x = f2 (x, d867);
++  x = f2 (x, d868);
++  x = f2 (x, d869);
++  x = f2 (x, d870);
++  x = f2 (x, d871);
++  x = f2 (x, d872);
++  x = f2 (x, d873);
++  x = f2 (x, d874);
++  x = f2 (x, d875);
++  x = f2 (x, d876);
++  x = f2 (x, d877);
++  x = f2 (x, d878);
++  x = f2 (x, d879);
++  x = f2 (x, d880);
++  x = f2 (x, d881);
++  x = f2 (x, d882);
++  x = f2 (x, d883);
++  x = f2 (x, d884);
++  x = f2 (x, d885);
++  x = f2 (x, d886);
++  x = f2 (x, d887);
++  x = f2 (x, d888);
++  x = f2 (x, d889);
++  x = f2 (x, d890);
++  x = f2 (x, d891);
++  x = f2 (x, d892);
++  x = f2 (x, d893);
++  x = f2 (x, d894);
++  x = f2 (x, d895);
++  x = f2 (x, d896);
++  x = f2 (x, d897);
++  x = f2 (x, d898);
++  x = f2 (x, d899);
++  x = f2 (x, d900);
++  x = f2 (x, d901);
++  x = f2 (x, d902);
++  x = f2 (x, d903);
++  x = f2 (x, d904);
++  x = f2 (x, d905);
++  x = f2 (x, d906);
++  x = f2 (x, d907);
++  x = f2 (x, d908);
++  x = f2 (x, d909);
++  x = f2 (x, d910);
++  x = f2 (x, d911);
++  x = f2 (x, d912);
++  x = f2 (x, d913);
++  x = f2 (x, d914);
++  x = f2 (x, d915);
++  x = f2 (x, d916);
++  x = f2 (x, d917);
++  x = f2 (x, d918);
++  x = f2 (x, d919);
++  x = f2 (x, d920);
++  x = f2 (x, d921);
++  x = f2 (x, d922);
++  x = f2 (x, d923);
++  x = f2 (x, d924);
++  x = f2 (x, d925);
++  x = f2 (x, d926);
++  x = f2 (x, d927);
++  x = f2 (x, d928);
++  x = f2 (x, d929);
++  x = f2 (x, d930);
++  x = f2 (x, d931);
++  x = f2 (x, d932);
++  x = f2 (x, d933);
++  x = f2 (x, d934);
++  x = f2 (x, d935);
++  x = f2 (x, d936);
++  x = f2 (x, d937);
++  x = f2 (x, d938);
++  x = f2 (x, d939);
++  x = f2 (x, d940);
++  x = f2 (x, d941);
++  x = f2 (x, d942);
++  x = f2 (x, d943);
++  x = f2 (x, d944);
++  x = f2 (x, d945);
++  x = f2 (x, d946);
++  x = f2 (x, d947);
++  x = f2 (x, d948);
++  x = f2 (x, d949);
++  x = f2 (x, d950);
++  x = f2 (x, d951);
++  x = f2 (x, d952);
++  x = f2 (x, d953);
++  x = f2 (x, d954);
++  x = f2 (x, d955);
++  x = f2 (x, d956);
++  x = f2 (x, d957);
++  x = f2 (x, d958);
++  x = f2 (x, d959);
++  x = f2 (x, d960);
++  x = f2 (x, d961);
++  x = f2 (x, d962);
++  x = f2 (x, d963);
++  x = f2 (x, d964);
++  x = f2 (x, d965);
++  x = f2 (x, d966);
++  x = f2 (x, d967);
++  x = f2 (x, d968);
++  x = f2 (x, d969);
++  x = f2 (x, d970);
++  x = f2 (x, d971);
++  x = f2 (x, d972);
++  x = f2 (x, d973);
++  x = f2 (x, d974);
++  x = f2 (x, d975);
++  x = f2 (x, d976);
++  x = f2 (x, d977);
++  x = f2 (x, d978);
++  x = f2 (x, d979);
++  x = f2 (x, d980);
++  x = f2 (x, d981);
++  x = f2 (x, d982);
++  x = f2 (x, d983);
++  x = f2 (x, d984);
++  x = f2 (x, d985);
++  x = f2 (x, d986);
++  x = f2 (x, d987);
++  x = f2 (x, d988);
++  x = f2 (x, d989);
++  x = f2 (x, d990);
++  x = f2 (x, d991);
++  x = f2 (x, d992);
++  x = f2 (x, d993);
++  x = f2 (x, d994);
++  x = f2 (x, d995);
++  x = f2 (x, d996);
++  x = f2 (x, d997);
++  x = f2 (x, d998);
++  x = f2 (x, d999);
++  return x;
++}
++
++/* { dg-final { scan-rtl-dump-times "Stack clash inline probes" 1 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 1 "pro_and_epilogue" } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 1 "pro_and_epilogue" } } */
++
++/* f3 is not a leaf
++/* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 1 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */
++/* { dg-final { scan-rtl-dump-times "Stack clash frame pointer needed" 1 "pro_and_epilogue" { target { frame_pointer_for_non_leaf } } } } */
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index 1000f15358b..8dbec663b18 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8385,11 +8385,15 @@ proc check_effective_target_arm_coproc4_ok { } {
+ proc check_effective_target_supports_stack_clash_protection { } {
+ 
+    # Temporary until the target bits are fully ACK'd.
+-#  if { [istarget aarch*-*-*] || [istarget x86_64-*-*]
+-#       || [istarget i?86-*-*] || [istarget s390*-*-*]
++#  if { [istarget aarch*-*-*]
++#       || [istarget s390*-*-*]
+ #       || [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
+ #	return 1
+ #  }
++
++    if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
++	return 1
++    }
+   return 0
+ }
+ 

diff --git a/gcc7-rh1512529-6.patch b/gcc7-rh1512529-6.patch
new file mode 100644
index 0000000..dd13635
--- /dev/null
+++ b/gcc7-rh1512529-6.patch
@@ -0,0 +1,118 @@
+commit e7519110827a59eb7275591db640bdbdfd31ba15
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 05:43:28 2017 +0000
+
+            * combine-stack-adj.c (combine_stack_adjustments_for_block): Do
+            nothing for stack adjustments with REG_STACK_CHECK.
+            * sched-deps.c (parse_add_or_inc): Reject insns with
+            REG_STACK_CHECK from dependency breaking.
+            * config/i386/i386.c (pro_epilogue_adjust_stack): Return insn.
+            (ix86_adjust_satck_and_probe_stack_clash): Add REG_STACK_NOTEs.
+            * reg-notes.def (STACK_CHECK): New note.
+    
+            * gcc.target/i386/stack-check-11.c: New test.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@252999 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
+index 9ec14a3e443..82d6dba856f 100644
+--- a/gcc/combine-stack-adj.c
++++ b/gcc/combine-stack-adj.c
+@@ -508,6 +508,8 @@ combine_stack_adjustments_for_block (basic_block bb)
+ 	continue;
+ 
+       set = single_set_for_csa (insn);
++      if (set && find_reg_note (insn, REG_STACK_CHECK, NULL_RTX))
++	set = NULL_RTX;
+       if (set)
+ 	{
+ 	  rtx dest = SET_DEST (set);
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 088dca2001f..5aff9b9d113 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -12900,7 +12900,7 @@ ix86_add_queued_cfa_restore_notes (rtx insn)
+    zero if %r11 register is live and cannot be freely used and positive
+    otherwise.  */
+ 
+-static void
++static rtx
+ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset,
+ 			   int style, bool set_cfa)
+ {
+@@ -12987,6 +12987,7 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset,
+       m->fs.sp_offset = ooffset - INTVAL (offset);
+       m->fs.sp_valid = valid;
+     }
++  return insn;
+ }
+ 
+ /* Find an available register to be used as dynamic realign argument
+@@ -13333,9 +13334,11 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+       for (i = probe_interval; i <= size; i += probe_interval)
+ 	{
+ 	  /* Allocate PROBE_INTERVAL bytes.  */
+-	  pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+-				     GEN_INT (-probe_interval), -1,
+-				     m->fs.cfa_reg == stack_pointer_rtx);
++	  rtx insn
++	    = pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++					 GEN_INT (-PROBE_INTERVAL), -1,
++					 m->fs.cfa_reg == stack_pointer_rtx);
++	  add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
+ 
+ 	  /* And probe at *sp.  */
+ 	  emit_stack_probe (stack_pointer_rtx);
+diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
+index 8734d26e5b4..18cf7e3cfc0 100644
+--- a/gcc/reg-notes.def
++++ b/gcc/reg-notes.def
+@@ -223,6 +223,10 @@ REG_NOTE (ARGS_SIZE)
+    pseudo reg.  */
+ REG_NOTE (RETURNED)
+ 
++/* Indicates the instruction is a stack check probe that should not
++   be combined with other stack adjustments.  */
++REG_NOTE (STACK_CHECK)
++
+ /* Used to mark a call with the function decl called by the call.
+    The decl might not be available in the call due to splitting of the call
+    insn.  This note is a SYMBOL_REF.  */
+diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
+index b2393bf28fb..564f3fb1559 100644
+--- a/gcc/sched-deps.c
++++ b/gcc/sched-deps.c
+@@ -4717,6 +4717,11 @@ parse_add_or_inc (struct mem_inc_info *mii, rtx_insn *insn, bool before_mem)
+   if (RTX_FRAME_RELATED_P (insn) || !pat)
+     return false;
+ 
++  /* Do not allow breaking data dependencies for insns that are marked
++     with REG_STACK_CHECK.  */
++  if (find_reg_note (insn, REG_STACK_CHECK, NULL))
++    return false;
++
+   /* Result must be single reg.  */
+   if (!REG_P (SET_DEST (pat)))
+     return false;
+diff --git a/gcc/testsuite/gcc.target/i386/stack-check-11.c b/gcc/testsuite/gcc.target/i386/stack-check-11.c
+new file mode 100644
+index 00000000000..183103f01e5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/stack-check-11.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fstack-clash-protection" } */
++/* { dg-require-effective-target supports_stack_clash_protection } */
++
++extern void arf (unsigned long int *, unsigned long int *);
++void
++frob ()
++{
++  unsigned long int num[859];
++  unsigned long int den[859];
++  arf (den, num);
++}
++
++/* { dg-final { scan-assembler-times "subq" 4 } } */
++/* { dg-final { scan-assembler-times "orq" 3 } } */
++

diff --git a/gcc7-rh1512529-7.patch b/gcc7-rh1512529-7.patch
new file mode 100644
index 0000000..0510dcd
--- /dev/null
+++ b/gcc7-rh1512529-7.patch
@@ -0,0 +1,88 @@
+commit 919262bedfe78b0d4f9fddbd980b85243a83bf28
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Wed Sep 20 21:59:50 2017 +0000
+
+            * explow.c (compute_stack_clash_protection_loop_data): Use
+            CONST_INT_P instead of explicit test.  Verify object is a
+            CONST_INT_P before looking at INTVAL.
+            (anti_adjust_stack_and_probe_stack_clash): Use CONST_INT_P
+            instead of explicit test.
+    
+            * gcc.target/i386/stack-check-11.c: Update test and regexp
+            so that it works for both i?86 and x86_64.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253034 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/explow.c b/gcc/explow.c
+index 2a73414ab22..6af6355fe30 100644
+--- a/gcc/explow.c
++++ b/gcc/explow.c
+@@ -1822,11 +1822,11 @@ compute_stack_clash_protection_loop_data (rtx *rounded_size, rtx *last_addr,
+       if (*rounded_size == CONST0_RTX (Pmode))
+ 	fprintf (dump_file,
+ 		 "Stack clash skipped dynamic allocation and probing loop.\n");
+-      else if (GET_CODE (*rounded_size) == CONST_INT
++      else if (CONST_INT_P (*rounded_size)
+ 	       && INTVAL (*rounded_size) <= 4 * *probe_interval)
+ 	fprintf (dump_file,
+ 		 "Stack clash dynamic allocation and probing inline.\n");
+-      else if (GET_CODE (*rounded_size) == CONST_INT)
++      else if (CONST_INT_P (*rounded_size))
+ 	fprintf (dump_file,
+ 		 "Stack clash dynamic allocation and probing in "
+ 		 "rotated loop.\n");
+@@ -1924,7 +1924,8 @@ anti_adjust_stack_and_probe_stack_clash (rtx size)
+ 
+   if (rounded_size != CONST0_RTX (Pmode))
+     {
+-      if (INTVAL (rounded_size) <= 4 * probe_interval)
++      if (CONST_INT_P (rounded_size)
++	  && INTVAL (rounded_size) <= 4 * probe_interval)
+ 	{
+ 	  for (HOST_WIDE_INT i = 0;
+ 	       i < INTVAL (rounded_size);
+@@ -1944,7 +1945,7 @@ anti_adjust_stack_and_probe_stack_clash (rtx size)
+       else
+ 	{
+ 	  rtx loop_lab, end_loop;
+-	  bool rotate_loop = GET_CODE (rounded_size) == CONST_INT;
++	  bool rotate_loop = CONST_INT_P (rounded_size);
+ 	  emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop,
+ 							last_addr, rotate_loop);
+ 
+@@ -1982,7 +1983,7 @@ anti_adjust_stack_and_probe_stack_clash (rtx size)
+ 	 might hold live data.  So probe at *sp if we know that
+ 	 an allocation was made, otherwise probe into the red zone
+ 	 which is obviously undesirable.  */
+-      if (GET_CODE (size) == CONST_INT)
++      if (CONST_INT_P (size))
+ 	{
+ 	  emit_stack_probe (stack_pointer_rtx);
+ 	  emit_insn (gen_blockage ());
+diff --git a/gcc/testsuite/gcc.target/i386/stack-check-11.c b/gcc/testsuite/gcc.target/i386/stack-check-11.c
+index 183103f01e5..fe5b2c2b844 100644
+--- a/gcc/testsuite/gcc.target/i386/stack-check-11.c
++++ b/gcc/testsuite/gcc.target/i386/stack-check-11.c
+@@ -2,15 +2,17 @@
+ /* { dg-options "-O2 -fstack-clash-protection" } */
+ /* { dg-require-effective-target supports_stack_clash_protection } */
+ 
+-extern void arf (unsigned long int *, unsigned long int *);
++#include <stdint.h>
++
++extern void arf (uint64_t *, uint64_t *);
+ void
+ frob ()
+ {
+-  unsigned long int num[859];
+-  unsigned long int den[859];
++  uint64_t num[859];
++  uint64_t den[859];
+   arf (den, num);
+ }
+ 
+-/* { dg-final { scan-assembler-times "subq" 4 } } */
+-/* { dg-final { scan-assembler-times "orq" 3 } } */
++/* { dg-final { scan-assembler-times "sub\[ql\]" 4 } } */
++/* { dg-final { scan-assembler-times "or\[ql\]" 3 } } */
+ 

diff --git a/gcc7-rh1512529-8.patch b/gcc7-rh1512529-8.patch
new file mode 100644
index 0000000..a59a8ee
--- /dev/null
+++ b/gcc7-rh1512529-8.patch
@@ -0,0 +1,388 @@
+commit a63af926db1d6109011e4dd81c750ecf784ab6c1
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Thu Sep 21 04:30:16 2017 +0000
+
+            * config/s390/s390.c (MIN_UNROLL_PROBES): Define.
+            (allocate_stack_space): New function, partially extracted from
+            s390_emit_prologue.
+            (s390_emit_prologue): Track offset to most recent stack probe.
+            Code to allocate space moved into allocate_stack_space.
+            Dump actions when no stack is allocated.
+            (s390_prologue_plus_offset): New function.
+            (s390_emit_stack_probe): Likewise.
+    
+            * gcc.dg/stack-check-5.c:  Add argument for s390.
+            * lib/target-supports.exp:
+            (check_effective_target_supports_stack_clash_protection): Enable for
+            s390/s390x targets.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253049 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
+index c408d59efd2..c78f1456daa 100644
+--- a/gcc/config/s390/s390.c
++++ b/gcc/config/s390/s390.c
+@@ -10974,6 +10974,183 @@ pass_s390_early_mach::execute (function *fun)
+ 
+ } // anon namespace
+ 
++/* Calculate TARGET = REG + OFFSET as s390_emit_prologue would do it.
++   - push too big immediates to the literal pool and annotate the refs
++   - emit frame related notes for stack pointer changes.  */
++
++static rtx
++s390_prologue_plus_offset (rtx target, rtx reg, rtx offset, bool frame_related_p)
++{
++  rtx insn;
++  rtx orig_offset = offset;
++
++  gcc_assert (REG_P (target));
++  gcc_assert (REG_P (reg));
++  gcc_assert (CONST_INT_P (offset));
++
++  if (offset == const0_rtx)                               /* lr/lgr */
++    {
++      insn = emit_move_insn (target, reg);
++    }
++  else if (DISP_IN_RANGE (INTVAL (offset)))               /* la */
++    {
++      insn = emit_move_insn (target, gen_rtx_PLUS (Pmode, reg,
++						   offset));
++    }
++  else
++    {
++      if (!satisfies_constraint_K (offset)                /* ahi/aghi */
++	  && (!TARGET_EXTIMM
++	      || (!satisfies_constraint_Op (offset)       /* alfi/algfi */
++		  && !satisfies_constraint_On (offset)))) /* slfi/slgfi */
++	offset = force_const_mem (Pmode, offset);
++
++      if (target != reg)
++	{
++	  insn = emit_move_insn (target, reg);
++	  RTX_FRAME_RELATED_P (insn) = frame_related_p ? 1 : 0;
++	}
++
++      insn = emit_insn (gen_add2_insn (target, offset));
++
++      if (!CONST_INT_P (offset))
++	{
++	  annotate_constant_pool_refs (&PATTERN (insn));
++
++	  if (frame_related_p)
++	    add_reg_note (insn, REG_FRAME_RELATED_EXPR,
++			  gen_rtx_SET (target,
++				       gen_rtx_PLUS (Pmode, target,
++						     orig_offset)));
++	}
++    }
++
++  RTX_FRAME_RELATED_P (insn) = frame_related_p ? 1 : 0;
++
++  /* If this is a stack adjustment and we are generating a stack clash
++     prologue, then add a REG_STACK_CHECK note to signal that this insn
++     should be left alone.  */
++  if (flag_stack_clash_protection && target == stack_pointer_rtx)
++    add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
++
++  return insn;
++}
++
++/* Emit a compare instruction with a volatile memory access as stack
++   probe.  It does not waste store tags and does not clobber any
++   registers apart from the condition code.  */
++static void
++s390_emit_stack_probe (rtx addr)
++{
++  rtx tmp = gen_rtx_MEM (Pmode, addr);
++  MEM_VOLATILE_P (tmp) = 1;
++  s390_emit_compare (EQ, gen_rtx_REG (Pmode, 0), tmp);
++  emit_insn (gen_blockage ());
++}
++
++/* Use a runtime loop if we have to emit more probes than this.  */
++#define MIN_UNROLL_PROBES 3
++
++/* Allocate SIZE bytes of stack space, using TEMP_REG as a temporary
++   if necessary.  LAST_PROBE_OFFSET contains the offset of the closest
++   probe relative to the stack pointer.
++
++   Note that SIZE is negative.
++
++   The return value is true if TEMP_REG has been clobbered.  */
++static bool
++allocate_stack_space (rtx size, HOST_WIDE_INT last_probe_offset,
++		      rtx temp_reg)
++{
++  bool temp_reg_clobbered_p = false;
++  HOST_WIDE_INT probe_interval
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  HOST_WIDE_INT guard_size
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE);
++
++  if (flag_stack_clash_protection)
++    {
++      if (last_probe_offset + -INTVAL (size) < guard_size)
++	dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++      else
++	{
++	  rtx offset = GEN_INT (probe_interval - UNITS_PER_LONG);
++	  HOST_WIDE_INT rounded_size = -INTVAL (size) & -probe_interval;
++	  HOST_WIDE_INT num_probes = rounded_size / probe_interval;
++	  HOST_WIDE_INT residual = -INTVAL (size) - rounded_size;
++
++	  if (num_probes < MIN_UNROLL_PROBES)
++	    {
++	      /* Emit unrolled probe statements.  */
++
++	      for (unsigned int i = 0; i < num_probes; i++)
++		{
++		  s390_prologue_plus_offset (stack_pointer_rtx,
++					     stack_pointer_rtx,
++					     GEN_INT (-probe_interval), true);
++		  s390_emit_stack_probe (gen_rtx_PLUS (Pmode,
++						       stack_pointer_rtx,
++						       offset));
++		}
++	      dump_stack_clash_frame_info (PROBE_INLINE, residual != 0);
++	    }
++	  else
++	    {
++	      /* Emit a loop probing the pages.  */
++
++	      rtx_code_label *loop_start_label = gen_label_rtx ();
++
++	      /* From now on temp_reg will be the CFA register.  */
++	      s390_prologue_plus_offset (temp_reg, stack_pointer_rtx,
++					 GEN_INT (-rounded_size), true);
++	      emit_label (loop_start_label);
++
++	      s390_prologue_plus_offset (stack_pointer_rtx,
++					 stack_pointer_rtx,
++					 GEN_INT (-probe_interval), false);
++	      s390_emit_stack_probe (gen_rtx_PLUS (Pmode,
++						   stack_pointer_rtx,
++						   offset));
++	      emit_cmp_and_jump_insns (stack_pointer_rtx, temp_reg,
++				       GT, NULL_RTX,
++				       Pmode, 1, loop_start_label);
++
++	      /* Without this make_edges ICEes.  */
++	      JUMP_LABEL (get_last_insn ()) = loop_start_label;
++	      LABEL_NUSES (loop_start_label) = 1;
++
++	      /* That's going to be a NOP since stack pointer and
++		 temp_reg are supposed to be the same here.  We just
++		 emit it to set the CFA reg back to r15.  */
++	      s390_prologue_plus_offset (stack_pointer_rtx, temp_reg,
++					 const0_rtx, true);
++	      temp_reg_clobbered_p = true;
++	      dump_stack_clash_frame_info (PROBE_LOOP, residual != 0);
++	    }
++
++	  /* Handle any residual allocation request.  */
++	  s390_prologue_plus_offset (stack_pointer_rtx,
++				     stack_pointer_rtx,
++				     GEN_INT (-residual), true);
++	  last_probe_offset += residual;
++	  if (last_probe_offset >= probe_interval)
++	    s390_emit_stack_probe (gen_rtx_PLUS (Pmode,
++						 stack_pointer_rtx,
++						 GEN_INT (residual
++							  - UNITS_PER_LONG)));
++
++	  return temp_reg_clobbered_p;
++	}
++    }
++
++  /* Subtract frame size from stack pointer.  */
++  s390_prologue_plus_offset (stack_pointer_rtx,
++			     stack_pointer_rtx,
++			     size, true);
++
++  return temp_reg_clobbered_p;
++}
++
+ /* Expand the prologue into a bunch of separate insns.  */
+ 
+ void
+@@ -10998,6 +11175,19 @@ s390_emit_prologue (void)
+   else
+     temp_reg = gen_rtx_REG (Pmode, 1);
+ 
++  /* When probing for stack-clash mitigation, we have to track the distance
++     between the stack pointer and closest known reference.
++
++     Most of the time we have to make a worst cast assumption.  The
++     only exception is when TARGET_BACKCHAIN is active, in which case
++     we know *sp (offset 0) was written.  */
++  HOST_WIDE_INT probe_interval
++    = 1 << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL);
++  HOST_WIDE_INT last_probe_offset
++    = (TARGET_BACKCHAIN
++       ? (TARGET_PACKED_STACK ? STACK_POINTER_OFFSET - UNITS_PER_LONG : 0)
++       : probe_interval - (STACK_BOUNDARY / UNITS_PER_WORD));
++
+   s390_save_gprs_to_fprs ();
+ 
+   /* Save call saved gprs.  */
+@@ -11009,6 +11199,14 @@ s390_emit_prologue (void)
+ 					  - cfun_frame_layout.first_save_gpr_slot),
+ 			cfun_frame_layout.first_save_gpr,
+ 			cfun_frame_layout.last_save_gpr);
++
++      /* This is not 100% correct.  If we have more than one register saved,
++	 then LAST_PROBE_OFFSET can move even closer to sp.  */
++      last_probe_offset
++	= (cfun_frame_layout.gprs_offset +
++	   UNITS_PER_LONG * (cfun_frame_layout.first_save_gpr
++			     - cfun_frame_layout.first_save_gpr_slot));
++
+       emit_insn (insn);
+     }
+ 
+@@ -11025,6 +11223,8 @@ s390_emit_prologue (void)
+       if (cfun_fpr_save_p (i))
+ 	{
+ 	  save_fpr (stack_pointer_rtx, offset, i);
++	  if (offset < last_probe_offset)
++	    last_probe_offset = offset;
+ 	  offset += 8;
+ 	}
+       else if (!TARGET_PACKED_STACK || cfun->stdarg)
+@@ -11038,6 +11238,8 @@ s390_emit_prologue (void)
+       if (cfun_fpr_save_p (i))
+ 	{
+ 	  insn = save_fpr (stack_pointer_rtx, offset, i);
++	  if (offset < last_probe_offset)
++	    last_probe_offset = offset;
+ 	  offset += 8;
+ 
+ 	  /* If f4 and f6 are call clobbered they are saved due to
+@@ -11060,6 +11262,8 @@ s390_emit_prologue (void)
+ 	if (cfun_fpr_save_p (i))
+ 	  {
+ 	    insn = save_fpr (stack_pointer_rtx, offset, i);
++	    if (offset < last_probe_offset)
++	      last_probe_offset = offset;
+ 
+ 	    RTX_FRAME_RELATED_P (insn) = 1;
+ 	    offset -= 8;
+@@ -11079,10 +11283,11 @@ s390_emit_prologue (void)
+   if (cfun_frame_layout.frame_size > 0)
+     {
+       rtx frame_off = GEN_INT (-cfun_frame_layout.frame_size);
+-      rtx real_frame_off;
++      rtx_insn *stack_pointer_backup_loc;
++      bool temp_reg_clobbered_p;
+ 
+       if (s390_stack_size)
+-  	{
++	{
+ 	  HOST_WIDE_INT stack_guard;
+ 
+ 	  if (s390_stack_guard)
+@@ -11148,35 +11353,36 @@ s390_emit_prologue (void)
+       if (s390_warn_dynamicstack_p && cfun->calls_alloca)
+ 	warning (0, "%qs uses dynamic stack allocation", current_function_name ());
+ 
+-      /* Save incoming stack pointer into temp reg.  */
+-      if (TARGET_BACKCHAIN || next_fpr)
+-	insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
++      /* Save the location where we could backup the incoming stack
++	 pointer.  */
++      stack_pointer_backup_loc = get_last_insn ();
+ 
+-      /* Subtract frame size from stack pointer.  */
++      temp_reg_clobbered_p = allocate_stack_space (frame_off, last_probe_offset,
++						   temp_reg);
+ 
+-      if (DISP_IN_RANGE (INTVAL (frame_off)))
+-	{
+-	  insn = gen_rtx_SET (stack_pointer_rtx,
+-			      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+-					    frame_off));
+-	  insn = emit_insn (insn);
+-	}
+-      else
++      if (TARGET_BACKCHAIN || next_fpr)
+ 	{
+-	  if (!CONST_OK_FOR_K (INTVAL (frame_off)))
+-	    frame_off = force_const_mem (Pmode, frame_off);
+-
+-          insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
+-	  annotate_constant_pool_refs (&PATTERN (insn));
++	  if (temp_reg_clobbered_p)
++	    {
++	      /* allocate_stack_space had to make use of temp_reg and
++		 we need it to hold a backup of the incoming stack
++		 pointer.  Calculate back that value from the current
++		 stack pointer.  */
++	      s390_prologue_plus_offset (temp_reg, stack_pointer_rtx,
++					 GEN_INT (cfun_frame_layout.frame_size),
++					 false);
++	    }
++	  else
++	    {
++	      /* allocate_stack_space didn't actually required
++		 temp_reg.  Insert the stack pointer backup insn
++		 before the stack pointer decrement code - knowing now
++		 that the value will survive.  */
++	      emit_insn_after (gen_move_insn (temp_reg, stack_pointer_rtx),
++			       stack_pointer_backup_loc);
++	    }
+ 	}
+ 
+-      RTX_FRAME_RELATED_P (insn) = 1;
+-      real_frame_off = GEN_INT (-cfun_frame_layout.frame_size);
+-      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+-		    gen_rtx_SET (stack_pointer_rtx,
+-				 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+-					       real_frame_off)));
+-
+       /* Set backchain.  */
+ 
+       if (TARGET_BACKCHAIN)
+@@ -11200,6 +11406,8 @@ s390_emit_prologue (void)
+ 	  emit_clobber (addr);
+ 	}
+     }
++  else if (flag_stack_clash_protection)
++    dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
+ 
+   /* Save fprs 8 - 15 (64 bit ABI).  */
+ 
+diff --git a/gcc/testsuite/gcc.dg/stack-check-5.c b/gcc/testsuite/gcc.dg/stack-check-5.c
+index 2171d9b6c23..3178f5d8ce5 100644
+--- a/gcc/testsuite/gcc.dg/stack-check-5.c
++++ b/gcc/testsuite/gcc.dg/stack-check-5.c
+@@ -3,6 +3,10 @@
+ /* { dg-require-effective-target supports_stack_clash_protection } */
+ 
+ 
++/* Otherwise the S/390 back-end might save the stack pointer in f2 ()
++   into an FPR.  */
++/* { dg-additional-options "-msoft-float" { target { s390x-*-* } } } */
++
+ extern void foo (char *);
+ extern void bar (void);
+ 
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index 8dbec663b18..e9f03886ca6 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8386,12 +8386,12 @@ proc check_effective_target_supports_stack_clash_protection { } {
+ 
+    # Temporary until the target bits are fully ACK'd.
+ #  if { [istarget aarch*-*-*]
+-#       || [istarget s390*-*-*]
+ #       || [istarget powerpc*-*-*] || [istarget rs6000*-*-*] } {
+ #	return 1
+ #  }
+ 
+-    if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
++    if { [istarget x86_64-*-*] || [istarget i?86-*-*] 
++	  || [istarget s390*-*-*] } {
+ 	return 1
+     }
+   return 0

diff --git a/gcc7-rh1512529-9.patch b/gcc7-rh1512529-9.patch
new file mode 100644
index 0000000..9c1f260
--- /dev/null
+++ b/gcc7-rh1512529-9.patch
@@ -0,0 +1,49 @@
+commit 233a9def5cd0b70f1288ff57ce67d9d5d5d7f845
+Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date:   Thu Sep 21 22:03:59 2017 +0000
+
+            * config/i386/i386.c (ix86_adjust_stack_and_probe_stack_clash):
+            Fix dump output if the only stack space is for pushed registers.
+    
+            * lib/target-supports.exp
+            (check_effective_target_frame_pointer_for_non_leaf): Add
+            case for x86 Solaris.
+    
+    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@253082 138bc75d-0d04-0410-961f-82ee72b054a4
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 5aff9b9d113..086848b2c73 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -13287,7 +13287,13 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size)
+      no probes are needed.  */
+   if (!size)
+     {
+-      dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
++      /* However, the allocation of space via pushes for register
++	 saves could be viewed as allocating space, but without the
++	 need to probe.  */
++      if (m->frame.nregs || m->frame.nsseregs || frame_pointer_needed)
++        dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
++      else
++	dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
+       return;
+     }
+ 
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index e9f03886ca6..cb58a2be35f 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -8403,6 +8403,12 @@ proc check_effective_target_frame_pointer_for_non_leaf { } {
+   if { [istarget aarch*-*-*] } {
+ 	return 1
+   }
++
++  # Solaris/x86 defaults to -fno-omit-frame-pointer.
++  if { [istarget i?86-*-solaris*] || [istarget x86_64-*-solaris*] } {
++    return 1
++  }
++
+   return 0
+ }
+ 

                 reply	other threads:[~2026-06-29 12:27 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178273605857.1.7396222920870365489.rpms-gcc-e987aff0a2c5@fedoraproject.org \
    --to=law@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox