aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2013-11-06 10:55:13 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2013-11-06 10:55:13 +0000
commit0dca9cd86cfd8221fb282b3fd858196065c10712 (patch)
tree22d0f3f446a2947d5bd7b23b793e89adfcf55670 /gcc/config
parentf054ff5b7c6afa260a9a3d07e8b59649dcf978f7 (diff)
downloadgcc-0dca9cd86cfd8221fb282b3fd858196065c10712.zip
gcc-0dca9cd86cfd8221fb282b3fd858196065c10712.tar.gz
gcc-0dca9cd86cfd8221fb282b3fd858196065c10712.tar.bz2
i386.c (ix86_expand_prologue): Optimize stack checking for leaf functions without dynamic stack allocation.
* config/i386/i386.c (ix86_expand_prologue): Optimize stack checking for leaf functions without dynamic stack allocation. * config/ia64/ia64.c (ia64_emit_probe_stack_range): Adjust. (ia64_expand_prologue): Likewise. * config/mips/mips.c (mips_expand_prologue): Likewise. * config/rs6000/rs6000.c (rs6000_emit_prologue): Likewise. * config/sparc/sparc.c (sparc_expand_prologue): Likewise. (sparc_flat_expand_prologue): Likewise. From-SVN: r204450
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c29
-rw-r--r--gcc/config/ia64/ia64.c114
-rw-r--r--gcc/config/mips/mips.c13
-rw-r--r--gcc/config/rs6000/rs6000.c15
-rw-r--r--gcc/config/sparc/sparc.c26
5 files changed, 131 insertions, 66 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1192332..0680dea 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10657,8 +10657,12 @@ ix86_expand_prologue (void)
if (STACK_CHECK_MOVING_SP)
{
- ix86_adjust_stack_and_probe (allocate);
- allocate = 0;
+ if (!(crtl->is_leaf && !cfun->calls_alloca
+ && allocate <= PROBE_INTERVAL))
+ {
+ ix86_adjust_stack_and_probe (allocate);
+ allocate = 0;
+ }
}
else
{
@@ -10668,9 +10672,26 @@ ix86_expand_prologue (void)
size = 0x80000000 - STACK_CHECK_PROTECT - 1;
if (TARGET_STACK_PROBE)
- ix86_emit_probe_stack_range (0, size + STACK_CHECK_PROTECT);
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL)
+ ix86_emit_probe_stack_range (0, size);
+ }
+ else
+ ix86_emit_probe_stack_range (0, size + STACK_CHECK_PROTECT);
+ }
else
- ix86_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ {
+ 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);
+ }
+ else
+ ix86_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
}
}
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 273cd39..971fe2f 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -3206,61 +3206,54 @@ gen_fr_restore_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
#define BACKING_STORE_SIZE(N) ((N) > 0 ? ((N) + (N)/63 + 1) * 8 : 0)
/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
- inclusive. These are offsets from the current stack pointer. SOL is the
- size of local registers. ??? This clobbers r2 and r3. */
+ inclusive. These are offsets from the current stack pointer. BS_SIZE
+ is the size of the backing store. ??? This clobbers r2 and r3. */
static void
-ia64_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size, int sol)
+ia64_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
+ int bs_size)
{
- /* On the IA-64 there is a second stack in memory, namely the Backing Store
- of the Register Stack Engine. We also need to probe it after checking
- that the 2 stacks don't overlap. */
- const int bs_size = BACKING_STORE_SIZE (sol);
rtx r2 = gen_rtx_REG (Pmode, GR_REG (2));
rtx r3 = gen_rtx_REG (Pmode, GR_REG (3));
-
- /* Detect collision of the 2 stacks if necessary. */
- if (bs_size > 0 || size > 0)
- {
- rtx p6 = gen_rtx_REG (BImode, PR_REG (6));
-
- emit_insn (gen_bsp_value (r3));
- emit_move_insn (r2, GEN_INT (-(first + size)));
-
- /* Compare current value of BSP and SP registers. */
- emit_insn (gen_rtx_SET (VOIDmode, p6,
- gen_rtx_fmt_ee (LTU, BImode,
- r3, stack_pointer_rtx)));
-
- /* Compute the address of the probe for the Backing Store (which grows
- towards higher addresses). We probe only at the first offset of
- the next page because some OS (eg Linux/ia64) only extend the
- backing store when this specific address is hit (but generate a SEGV
- on other address). Page size is the worst case (4KB). The reserve
- size is at least 4096 - (96 + 2) * 8 = 3312 bytes, which is enough.
- Also compute the address of the last probe for the memory stack
- (which grows towards lower addresses). */
- emit_insn (gen_rtx_SET (VOIDmode, r3, plus_constant (Pmode, r3, 4095)));
- emit_insn (gen_rtx_SET (VOIDmode, r2,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx, r2)));
-
- /* Compare them and raise SEGV if the former has topped the latter. */
- emit_insn (gen_rtx_COND_EXEC (VOIDmode,
- gen_rtx_fmt_ee (NE, VOIDmode, p6,
- const0_rtx),
- gen_rtx_SET (VOIDmode, p6,
- gen_rtx_fmt_ee (GEU, BImode,
- r3, r2))));
- emit_insn (gen_rtx_SET (VOIDmode,
- gen_rtx_ZERO_EXTRACT (DImode, r3, GEN_INT (12),
- const0_rtx),
- const0_rtx));
- emit_insn (gen_rtx_COND_EXEC (VOIDmode,
- gen_rtx_fmt_ee (NE, VOIDmode, p6,
- const0_rtx),
- gen_rtx_TRAP_IF (VOIDmode, const1_rtx,
- GEN_INT (11))));
- }
+ rtx p6 = gen_rtx_REG (BImode, PR_REG (6));
+
+ /* On the IA-64 there is a second stack in memory, namely the Backing Store
+ of the Register Stack Engine. We also need to probe it after checking
+ that the 2 stacks don't overlap. */
+ emit_insn (gen_bsp_value (r3));
+ emit_move_insn (r2, GEN_INT (-(first + size)));
+
+ /* Compare current value of BSP and SP registers. */
+ emit_insn (gen_rtx_SET (VOIDmode, p6,
+ gen_rtx_fmt_ee (LTU, BImode,
+ r3, stack_pointer_rtx)));
+
+ /* Compute the address of the probe for the Backing Store (which grows
+ towards higher addresses). We probe only at the first offset of
+ the next page because some OS (eg Linux/ia64) only extend the
+ backing store when this specific address is hit (but generate a SEGV
+ on other address). Page size is the worst case (4KB). The reserve
+ size is at least 4096 - (96 + 2) * 8 = 3312 bytes, which is enough.
+ Also compute the address of the last probe for the memory stack
+ (which grows towards lower addresses). */
+ emit_insn (gen_rtx_SET (VOIDmode, r3, plus_constant (Pmode, r3, 4095)));
+ emit_insn (gen_rtx_SET (VOIDmode, r2,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx, r2)));
+
+ /* Compare them and raise SEGV if the former has topped the latter. */
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_fmt_ee (NE, VOIDmode, p6, const0_rtx),
+ gen_rtx_SET (VOIDmode, p6,
+ gen_rtx_fmt_ee (GEU, BImode,
+ r3, r2))));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ gen_rtx_ZERO_EXTRACT (DImode, r3, GEN_INT (12),
+ const0_rtx),
+ const0_rtx));
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_fmt_ee (NE, VOIDmode, p6, const0_rtx),
+ gen_rtx_TRAP_IF (VOIDmode, const1_rtx,
+ GEN_INT (11))));
/* Probe the Backing Store if necessary. */
if (bs_size > 0)
@@ -3444,10 +3437,23 @@ ia64_expand_prologue (void)
current_function_static_stack_size = current_frame_info.total_size;
if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
- ia64_emit_probe_stack_range (STACK_CHECK_PROTECT,
- current_frame_info.total_size,
- current_frame_info.n_input_regs
- + current_frame_info.n_local_regs);
+ {
+ HOST_WIDE_INT size = current_frame_info.total_size;
+ int bs_size = BACKING_STORE_SIZE (current_frame_info.n_input_regs
+ + current_frame_info.n_local_regs);
+
+ 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,
+ 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 > 0)
+ ia64_emit_probe_stack_range (STACK_CHECK_PROTECT, size, bs_size);
+ }
if (dump_file)
{
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 60e5e78..c1d8f3a 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -10994,8 +10994,17 @@ mips_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ 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);
+ }
+ else if (size > 0)
+ mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
/* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP
bytes beforehand; this is enough to cover the register save area
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index a6b6681..fce8f31 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -21538,8 +21538,19 @@ rs6000_emit_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = info->total_size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && info->total_size)
- rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, info->total_size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ HOST_WIDE_INT size = info->total_size;
+
+ 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);
+ }
+ else if (size > 0)
+ rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (TARGET_FIX_AND_CONTINUE)
{
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 8ef6341..0eabd5b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -5362,8 +5362,17 @@ sparc_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ 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);
+ }
+ else if (size > 0)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (size == 0)
; /* do nothing. */
@@ -5464,8 +5473,17 @@ sparc_flat_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ 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);
+ }
+ else if (size > 0)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (sparc_save_local_in_regs_p)
emit_save_or_restore_local_in_regs (stack_pointer_rtx, SPARC_STACK_BIAS,