When stack checking is entirely done by the middle-end (default if no specific 
back-end support or forced by -fstack-check=generic), the checking for the 
prologue is actually done in the caller with a default range and the hope is 
that the callee's static frame is not too large...  There are a few tricks to 
make it sort of work, but it's obviously not bullet proof so a warning will be 
issued in the problematic cases (lot of small variables).

But it is issued at the end of reload and LRA didn't replicate it, so it will 
no longer be issued e.g. for s390, as seen under PR ada/70017.  Therefore the 
attached patch moves it to the end of do_reload and also streamlines it a bit.

Tested on x86_64-suse-linux, applied on the mainline as obvious.


2016-03-01  Eric Botcazou  <ebotca...@adacore.com>

        PR ada/70017
        * ira.c (do_reload): Issue warning for generic stack checking here...
        * reload1.c (reload): ...instead of here and streamline it.


2016-03-01  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.dg/pr70017.c: New test.

-- 
Eric Botcazou
Index: ira.c
===================================================================
--- ira.c	(revision 233840)
+++ ira.c	(working copy)
@@ -5404,9 +5404,8 @@ do_reload (void)
     {
       df_set_flags (DF_NO_INSN_RESCAN);
       build_insn_chain ();
-      
-      need_dce = reload (get_insns (), ira_conflicts_p);
 
+      need_dce = reload (get_insns (), ira_conflicts_p);
     }
 
   timevar_pop (TV_RELOAD);
@@ -5484,6 +5483,20 @@ do_reload (void)
       inform (DECL_SOURCE_LOCATION (decl), "for %qD", decl);
     }
 
+  /* If we are doing generic stack checking, give a warning if this
+     function's frame size is larger than we expect.  */
+  if (flag_stack_check == GENERIC_STACK_CHECK)
+    {
+      HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+
+      for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	if (df_regs_ever_live_p (i) && !fixed_regs[i] && call_used_regs[i])
+	  size += UNITS_PER_WORD;
+
+      if (size > STACK_CHECK_MAX_FRAME_SIZE)
+	warning (0, "frame size too large for reliable stack checking");
+    }
+
   if (pic_offset_table_regno != INVALID_REGNUM)
     pic_offset_table_rtx = gen_rtx_REG (Pmode, pic_offset_table_regno);
 
Index: reload1.c
===================================================================
--- reload1.c	(revision 233840)
+++ reload1.c	(working copy)
@@ -1258,28 +1258,6 @@ reload (rtx_insn *first, int global)
 	  }
       }
 
-  /* If we are doing generic stack checking, give a warning if this
-     function's frame size is larger than we expect.  */
-  if (flag_stack_check == GENERIC_STACK_CHECK)
-    {
-      HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
-      static int verbose_warned = 0;
-
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-	if (df_regs_ever_live_p (i) && ! fixed_regs[i] && call_used_regs[i])
-	  size += UNITS_PER_WORD;
-
-      if (size > STACK_CHECK_MAX_FRAME_SIZE)
-	{
-	  warning (0, "frame size too large for reliable stack checking");
-	  if (! verbose_warned)
-	    {
-	      warning (0, "try reducing the number of local variables");
-	      verbose_warned = 1;
-	    }
-	}
-    }
-
   free (temp_pseudo_reg_arr);
 
   /* Indicate that we no longer have known memory locations or constants.  */
/* { dg-do compile } */
/* { dg-options "-fstack-check=generic" } */

/* Check that the expected warning is issued for large frames.  */

#define ONE(s) char a##s[32];
#define TEN(s) ONE(s##0) ONE(s##1) ONE(s##2) ONE(s##3) ONE(s##4) \
               ONE(s##5) ONE(s##6) ONE(s##7) ONE(s##8) ONE(s##9)
#define HUNDRED(s) TEN(s##0) TEN(s##1) TEN(s##2) TEN(s##3) TEN(s##4) \
                   TEN(s##5) TEN(s##6) TEN(s##7) TEN(s##8) TEN(s##9)

void foo(void)
{
  HUNDRED(a)
  HUNDRED(b)
} /* { dg-warning "frame size too large for reliable stack checking" } */

Reply via email to