From ae58e548884f696e600966549867df23de3ff2d3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 11 Jul 2009 19:40:29 +0200 Subject: [PATCH] re PR target/40667 (stack frames are generated even with -fomit-frame-pointer) PR rtl-optimization/40667 * defaults.h (MINIMUM_ALIGNMENT): Define if not defined. * doc/tm.texi (MINIMUM_ALIGNMENT): Document it. * config/i386/i386.h (MINIMUM_ALIGNMENT): Define. * config/i386/i386.c (ix86_minimum_alignment): New function. * config/i386/i386-protos.h (ix86_minimum_alignment): New prototype. * cfgexpand.c (expand_one_var): Use MINIMIM_ALIGNMENT. * emit-rtl.c (gen_reg_rtx): Likewise. * function.c (assign_parms): Likewise. If nominal_type needs bigger alignment than FUNCTION_ARG_BOUNDARY, use its alignment rather than passed_type's alignment. From-SVN: r149513 --- gcc/ChangeLog | 12 ++++++++++++ gcc/cfgexpand.c | 6 ++++-- gcc/config/i386/i386-protos.h | 2 ++ gcc/config/i386/i386.c | 35 +++++++++++++++++++++++++++++++++++ gcc/config/i386/i386.h | 9 +++++++++ gcc/defaults.h | 4 ++++ gcc/doc/tm.texi | 8 ++++++++ gcc/emit-rtl.c | 6 +++++- gcc/function.c | 6 +++++- 9 files changed, 84 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17bb0cd..f3d298e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,17 @@ 2009-07-11 Jakub Jelinek + PR rtl-optimization/40667 + * defaults.h (MINIMUM_ALIGNMENT): Define if not defined. + * doc/tm.texi (MINIMUM_ALIGNMENT): Document it. + * config/i386/i386.h (MINIMUM_ALIGNMENT): Define. + * config/i386/i386.c (ix86_minimum_alignment): New function. + * config/i386/i386-protos.h (ix86_minimum_alignment): New prototype. + * cfgexpand.c (expand_one_var): Use MINIMIM_ALIGNMENT. + * emit-rtl.c (gen_reg_rtx): Likewise. + * function.c (assign_parms): Likewise. If nominal_type needs + bigger alignment than FUNCTION_ARG_BOUNDARY, use its alignment + rather than passed_type's alignment. + PR target/40668 * function.c (assign_parm_setup_stack): Adjust MEM_OFFSET (data->stack_parm) if promoted_mode is different diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 62b5c45..c8d19fb 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1164,9 +1164,11 @@ expand_one_var (tree var, bool toplevel, bool really_expand) variables, which won't be on stack, we collect alignment of type and ignore user specified alignment. */ if (TREE_STATIC (var) || DECL_EXTERNAL (var)) - align = TYPE_ALIGN (TREE_TYPE (var)); + align = MINIMUM_ALIGNMENT (TREE_TYPE (var), + TYPE_MODE (TREE_TYPE (var)), + TYPE_ALIGN (TREE_TYPE (var))); else - align = DECL_ALIGN (var); + align = MINIMUM_ALIGNMENT (var, DECL_MODE (var), DECL_ALIGN (var)); if (crtl->stack_alignment_estimated < align) { diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index d1d601a..2e92219 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -199,6 +199,8 @@ extern int ix86_return_pops_args (tree, tree, int); extern int ix86_data_alignment (tree, int); extern unsigned int ix86_local_alignment (tree, enum machine_mode, unsigned int); +extern unsigned int ix86_minimum_alignment (tree, enum machine_mode, + unsigned int); extern int ix86_constant_alignment (tree, int); extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *); extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6844031..f05eb5c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -20087,6 +20087,41 @@ ix86_local_alignment (tree exp, enum machine_mode mode, } return align; } + +/* Compute the minimum required alignment for dynamic stack realignment + purposes for a local variable, parameter or a stack slot. EXP is + the data type or decl itself, MODE is its mode and ALIGN is the + alignment that the object would ordinarily have. */ + +unsigned int +ix86_minimum_alignment (tree exp, enum machine_mode mode, + unsigned int align) +{ + tree type, decl; + + if (TARGET_64BIT || align != 64 || ix86_preferred_stack_boundary >= 64) + return align; + + if (exp && DECL_P (exp)) + { + type = TREE_TYPE (exp); + decl = exp; + } + else + { + type = exp; + decl = NULL; + } + + /* Don't do dynamic stack realignment for long long objects with + -mpreferred-stack-boundary=2. */ + if ((mode == DImode || (type && TYPE_MODE (type) == DImode)) + && (!type || !TYPE_USER_ALIGN (type)) + && (!decl || !DECL_USER_ALIGN (decl))) + return 32; + + return align; +} /* Emit RTL insns to initialize the variable parts of a trampoline. FNADDR is an RTX for the address of the function's pure code. diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 97483b7..f9b9dd1 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -831,6 +831,15 @@ enum target_cpu_default #define LOCAL_DECL_ALIGNMENT(DECL) \ ix86_local_alignment ((DECL), VOIDmode, DECL_ALIGN (DECL)) +/* If defined, a C expression to compute the minimum required alignment + for dynamic stack realignment purposes for EXP (a TYPE or DECL), + MODE, assuming normal alignment ALIGN. + + If this macro is not defined, then (ALIGN) will be used. */ + +#define MINIMUM_ALIGNMENT(EXP, MODE, ALIGN) \ + ix86_minimum_alignment (EXP, MODE, ALIGN) + /* If defined, a C expression that gives the alignment boundary, in bits, of an argument with the specified mode and type. If it is diff --git a/gcc/defaults.h b/gcc/defaults.h index 11873a8..b6cec4b 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -1138,6 +1138,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see LOCAL_ALIGNMENT (TREE_TYPE (DECL), DECL_ALIGN (DECL)) #endif +#ifndef MINIMUM_ALIGNMENT +#define MINIMUM_ALIGNMENT(EXP,MODE,ALIGN) (ALIGN) +#endif + /* Alignment value for attribute ((aligned)). */ #ifndef ATTRIBUTE_ALIGNED_VALUE #define ATTRIBUTE_ALIGNED_VALUE BIGGEST_ALIGNMENT diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index e328210..41ed031 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1227,6 +1227,14 @@ One use of this macro is to increase alignment of medium-size data to make it all fit in fewer cache lines. @end defmac +@defmac MINIMUM_ALIGNMENT (@var{exp}, @var{mode}, @var{align}) +If defined, a C expression to compute the minimum required alignment +for dynamic stack realignment purposes for @var{exp} (a type or decl), +@var{mode}, assuming normal alignment @var{align}. + +If this macro is not defined, then @var{align} will be used. +@end defmac + @defmac EMPTY_FIELD_BOUNDARY Alignment in bits to be given to a structure bit-field that follows an empty field such as @code{int : 0;}. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index df2b4b7..d20f2b5 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -869,7 +869,11 @@ gen_reg_rtx (enum machine_mode mode) if (SUPPORTS_STACK_ALIGNMENT && crtl->stack_alignment_estimated < align && !crtl->stack_realign_processed) - crtl->stack_alignment_estimated = align; + { + unsigned int min_align = MINIMUM_ALIGNMENT (NULL, mode, align); + if (crtl->stack_alignment_estimated < min_align) + crtl->stack_alignment_estimated = min_align; + } if (generating_concat_p && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT diff --git a/gcc/function.c b/gcc/function.c index 258f594..e31c12a 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3146,8 +3146,12 @@ assign_parms (tree fndecl) { unsigned int align = FUNCTION_ARG_BOUNDARY (data.promoted_mode, data.passed_type); + align = MINIMUM_ALIGNMENT (data.passed_type, data.promoted_mode, + align); if (TYPE_ALIGN (data.nominal_type) > align) - align = TYPE_ALIGN (data.passed_type); + align = MINIMUM_ALIGNMENT (data.nominal_type, + TYPE_MODE (data.nominal_type), + TYPE_ALIGN (data.nominal_type)); if (crtl->stack_alignment_estimated < align) { gcc_assert (!crtl->stack_realign_processed); -- 2.7.4