From: Eric Botcazou Date: Wed, 6 Nov 2013 10:55:13 +0000 (+0000) Subject: i386.c (ix86_expand_prologue): Optimize stack checking for leaf functions without... X-Git-Tag: releases/gcc-4.9.0~2997 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0dca9cd86cfd8221fb282b3fd858196065c10712;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 069cb506f720..677fba92c59b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2013-11-06 Eric Botcazou + + * 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. + 2013-11-06 James Greenhalgh * config/aarch64/arm_neon.h @@ -28,12 +39,12 @@ 2013-11-06 Christian Bruel - * gcc/config/sh/sh-mem.cc (sh_expand_cmpnstr, sh_expand_cmpstr): + * config/sh/sh-mem.cc (sh_expand_cmpnstr, sh_expand_cmpstr): Factorize probabilities, Use adjust_address instead of adjust_automodify_address when possible. Enable for optimize. (sh_expand_strlen): New function. - * gcc/config/sh/sh-protos.h (sh_expand_strlen): Declare. - * gcc/config/sh/sh.md (strlensi): New pattern. + * config/sh/sh-protos.h (sh_expand_strlen): Declare. + * config/sh/sh.md (strlensi): New pattern. (UNSPEC_BUILTIN_STRLEN): Define. 2013-11-06 Jakub Jelinek @@ -305,19 +316,19 @@ 2013-11-04 Wei Mi - * gcc/config/i386/i386.c (memory_address_length): Extract a part + * config/i386/i386.c (memory_address_length): Extract a part of code to rip_relative_addr_p. (rip_relative_addr_p): New Function. (ix86_macro_fusion_p): Ditto. (ix86_macro_fusion_pair_p): Ditto. - * gcc/config/i386/i386.h: Add new tune features about macro-fusion. - * gcc/config/i386/x86-tune.def (DEF_TUNE): Ditto. - * gcc/doc/tm.texi: Generated. - * gcc/doc/tm.texi.in: Ditto. - * gcc/haifa-sched.c (try_group_insn): New Function. + * config/i386/i386.h: Add new tune features about macro-fusion. + * config/i386/x86-tune.def (DEF_TUNE): Ditto. + * doc/tm.texi: Generated. + * doc/tm.texi.in: Ditto. + * haifa-sched.c (try_group_insn): New Function. (group_insns_for_macro_fusion): Ditto. (sched_init): Call group_insns_for_macro_fusion. - * gcc/target.def: Add two hooks: macro_fusion_p and + * target.def: Add two hooks: macro_fusion_p and macro_fusion_pair_p. 2013-11-04 Kostya Serebryany @@ -337,17 +348,17 @@ 2013-11-04 Wei Mi - * gcc/config/i386/i386-c.c (ix86_target_macros_internal): Separate + * config/i386/i386-c.c (ix86_target_macros_internal): Separate PROCESSOR_COREI7_AVX out from PROCESSOR_COREI7. - * gcc/config/i386/i386.c (ix86_option_override_internal): Ditto. + * config/i386/i386.c (ix86_option_override_internal): Ditto. (ix86_issue_rate): Ditto. (ix86_adjust_cost): Ditto. (ia32_multipass_dfa_lookahead): Ditto. (ix86_sched_init_global): Ditto. (get_builtin_code_for_version): Ditto. - * gcc/config/i386/i386.h (enum target_cpu_default): Ditto. + * config/i386/i386.h (enum target_cpu_default): Ditto. (enum processor_type): Ditto. - * gcc/config/i386/x86-tune.def (DEF_TUNE): Ditto. + * config/i386/x86-tune.def (DEF_TUNE): Ditto. 2013-11-04 Vladimir Makarov @@ -903,7 +914,7 @@ 2013-10-30 Tobias Burnus PR other/33426 - * gcc/tree-cfg.c (replace_loop_annotate): Replace warning by + * tree-cfg.c (replace_loop_annotate): Replace warning by warning_at. 2013-10-30 Jason Merrill @@ -1024,10 +1035,10 @@ 2013-10-30 Christian Bruel - * gcc/config/sh/sh-mem.cc (sh_expand_cmpnstr): New function. + * config/sh/sh-mem.cc (sh_expand_cmpnstr): New function. (sh_expand_cmpstr): Handle known align and schedule improvements. - * gcc/config/sh/sh-protos.h (sh_expand_cmpstrn): Declare. - * gcc/config/sh/sh.md (cmpstrnsi): New pattern. + * config/sh/sh-protos.h (sh_expand_cmpstrn): Declare. + * config/sh/sh.md (cmpstrnsi): New pattern. 2013-10-30 Martin Jambor @@ -2303,7 +2314,7 @@ 2013-10-24 Joern Rennecke - * gcc/config/arc/arc.c (arc_ccfsm_post_advance): Also handle + * config/arc/arc.c (arc_ccfsm_post_advance): Also handle TYPE_UNCOND_BRANCH. (arc_ifcvt) : Check that arc_ccfsm_post_advance changes statep->state. @@ -2335,12 +2346,12 @@ 2013-10-25 Christian Bruel * config.gcc (sh-*): Add sh-mem.o to extra_obj. - * gcc/config/sh/t-sh (sh-mem.o): New rule. - * gcc/config/sh/sh-mem.cc (expand_block_move): Moved here. + * config/sh/t-sh (sh-mem.o): New rule. + * config/sh/sh-mem.cc (expand_block_move): Moved here. (sh_expand_cmpstr): New function. - * gcc/config/sh/sh.c (force_into, expand_block_move): Move to sh-mem.c. - * gcc/config/sh/sh-protos.h (sh_expand_cmpstr): Declare. - * gcc/config/sh/sh.md (cmpstrsi, cmpstr_t): New patterns. + * config/sh/sh.c (force_into, expand_block_move): Move to sh-mem.c. + * config/sh/sh-protos.h (sh_expand_cmpstr): Declare. + * config/sh/sh.md (cmpstrsi, cmpstr_t): New patterns. (rotlhi3_8): Rename. 2013-10-24 Jan-Benedict Glaw @@ -3184,7 +3195,7 @@ 2013-10-16 Bill Schmidt - * gcc/config/rs6000/vector.md (vec_unpacks_hi_v4sf): Correct for + * config/rs6000/vector.md (vec_unpacks_hi_v4sf): Correct for endianness. (vec_unpacks_lo_v4sf): Likewise. (vec_unpacks_float_hi_v4si): Likewise. @@ -3970,8 +3981,8 @@ (anddi3_insn): Update type attribute. (xordi3_insn): Likewise. (one_cmpldi2): Likewise. - * gcc/config/arm/vfp.md (movhf_vfp_neon): Update type attribute. - * gcc/config/arm/neon.md (neon_mov): Update type attribute. + * config/arm/vfp.md (movhf_vfp_neon): Update type attribute. + * config/arm/neon.md (neon_mov): Update type attribute. (*movmisalign_neon_store): Likewise. (*movmisalign_neon_load): Likewise. (vec_set_internal): Likewise. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 119233273231..0680dea7d62a 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 273cd39065f2..971fe2f81891 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 60e5e788f902..c1d8f3a0ade7 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 a6b66816aee2..fce8f317c6a6 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 8ef634133c54..0eabd5b2b726 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,