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" } */