* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@149513
138bc75d-0d04-0410-961f-
82ee72b054a4
2009-07-11 Jakub Jelinek <jakub@redhat.com>
+ 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
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)
{
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 *);
}
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;
+}
\f
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
#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
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
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;}.
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
{
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);