+2008-05-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/36253
+ * caller-save.c (insert_restore): Verify alignment of spill
+ space.
+ (insert_save): Likewise.
+
+ * cfgexpand.c (LOCAL_ALIGNMENT): Removed.
+
+ * defaults.h (LOCAL_ALIGNMENT): New. Provide default.
+ (STACK_SLOT_ALIGNMENT): Likewise.
+
+ * function.c (LOCAL_ALIGNMENT): Removed.
+ (get_stack_local_alignment): New.
+ (assign_stack_local): Use it. Set alignment on stack slot.
+ (assign_stack_temp_for_type): Use get_stack_local_alignment.
+
+ * config/i386/i386.h (LOCAL_ALIGNMENT): Updated.
+ (STACK_SLOT_ALIGNMENT): New.
+
+ * config/i386/i386.c (ix86_local_alignment): Handle caller-save
+ stack slot in XFmode.
+
+ * doc/tm.texi (STACK_SLOT_ALIGNMENT): New.
+
2008-05-26 Kai Tietz <kai.tietz@onevision.com>
PR/36321
mem = adjust_address (mem, save_mode[regno], 0);
else
mem = copy_rtx (mem);
+
+ /* Verify that the alignment of spill space is equal to or greater
+ than required. */
+ gcc_assert (GET_MODE_ALIGNMENT (GET_MODE (mem)) <= MEM_ALIGN (mem));
+
pat = gen_rtx_SET (VOIDmode,
gen_rtx_REG (GET_MODE (mem),
regno), mem);
mem = adjust_address (mem, save_mode[regno], 0);
else
mem = copy_rtx (mem);
+
+ /* Verify that the alignment of spill space is equal to or greater
+ than required. */
+ gcc_assert (GET_MODE_ALIGNMENT (GET_MODE (mem)) <= MEM_ALIGN (mem));
+
pat = gen_rtx_SET (VOIDmode, mem,
gen_rtx_REG (GET_MODE (mem),
regno));
}
-#ifndef LOCAL_ALIGNMENT
-#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
-#endif
-
#ifndef STACK_ALIGNMENT_NEEDED
#define STACK_ALIGNMENT_NEEDED 1
#endif
extern int ix86_return_pops_args (tree, tree, int);
extern int ix86_data_alignment (tree, int);
-extern int ix86_local_alignment (tree, int);
+extern unsigned int ix86_local_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 alignment for a local variable.
- TYPE is the data type, and ALIGN is the alignment that
- the object would ordinarily have. The value of this macro is used
- instead of that alignment to align the object. */
+/* Compute the alignment for a local variable or a stack slot. TYPE is
+ the data type, MODE is the widest mode available and ALIGN is the
+ alignment that the object would ordinarily have. The value of this
+ macro is used instead of that alignment to align the object. */
-int
-ix86_local_alignment (tree type, int align)
+unsigned int
+ix86_local_alignment (tree type, enum machine_mode mode,
+ unsigned int align)
{
+ /* If TYPE is NULL, we are allocating a stack slot for caller-save
+ register in MODE. We will return the largest alignment of XF
+ and DF. */
+ if (!type)
+ {
+ if (mode == XFmode && align < GET_MODE_ALIGNMENT (DFmode))
+ align = GET_MODE_ALIGNMENT (DFmode);
+ return align;
+ }
+
/* x86-64 ABI requires arrays greater than 16 bytes to be aligned
to 16byte boundary. */
if (TARGET_64BIT)
One use of this macro is to increase alignment of medium-size
data to make it all fit in fewer cache lines. */
-#define LOCAL_ALIGNMENT(TYPE, ALIGN) ix86_local_alignment ((TYPE), (ALIGN))
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ ix86_local_alignment ((TYPE), VOIDmode, (ALIGN))
+
+/* If defined, a C expression to compute the alignment for stack slot.
+ TYPE is the data type, MODE is the widest mode available, and ALIGN
+ is the alignment that the slot would ordinarily have. The value of
+ this macro is used instead of that alignment to align the slot.
+
+ If this macro is not defined, then ALIGN is used when TYPE is NULL,
+ Otherwise, LOCAL_ALIGNMENT will be used.
+
+ One use of this macro is to set alignment of stack slot to the
+ maximum alignment of all possible modes which the slot may have. */
+
+#define STACK_SLOT_ALIGNMENT(TYPE, MODE, ALIGN) \
+ ix86_local_alignment ((TYPE), (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
#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 0
#endif
+#ifndef LOCAL_ALIGNMENT
+#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
+#endif
+
+#ifndef STACK_SLOT_ALIGNMENT
+#define STACK_SLOT_ALIGNMENT(TYPE,MODE,ALIGN) \
+ ((TYPE) ? LOCAL_ALIGNMENT ((TYPE), (ALIGN)) : (ALIGN))
+#endif
+
#endif /* ! GCC_DEFAULTS_H */
make it all fit in fewer cache lines.
@end defmac
+@defmac STACK_SLOT_ALIGNMENT (@var{type}, @var{mode}, @var{basic-align})
+If defined, a C expression to compute the alignment for stack slot.
+@var{type} is the data type, @var{mode} is the widest mode available,
+and @var{basic-align} is the alignment that the slot would ordinarily
+have. The value of this macro is used instead of that alignment to
+align the slot.
+
+If this macro is not defined, then @var{basic-align} is used when
+@var{type} is @code{NULL}. Otherwise, @code{LOCAL_ALIGNMENT} will
+be used.
+
+This macro is to set alignment of stack slot to the maximum alignment
+of all possible modes which the slot may have.
+@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;}.
/* So we can assign to cfun in this file. */
#undef cfun
-#ifndef LOCAL_ALIGNMENT
-#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
-#endif
-
#ifndef STACK_ALIGNMENT_NEEDED
#define STACK_ALIGNMENT_NEEDED 1
#endif
return FALSE;
}
+/* Return stack slot alignment in bits for TYPE and MODE. */
+
+static unsigned int
+get_stack_local_alignment (tree type, enum machine_mode mode)
+{
+ unsigned int alignment;
+
+ if (mode == BLKmode)
+ alignment = BIGGEST_ALIGNMENT;
+ else
+ alignment = GET_MODE_ALIGNMENT (mode);
+
+ /* Allow the frond-end to (possibly) increase the alignment of this
+ stack slot. */
+ if (! type)
+ type = lang_hooks.types.type_for_mode (mode, 0);
+
+ return STACK_SLOT_ALIGNMENT (type, mode, alignment);
+}
+
/* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
with machine mode MODE.
{
rtx x, addr;
int bigend_correction = 0;
- unsigned int alignment;
+ unsigned int alignment, alignment_in_bits;
int frame_off, frame_alignment, frame_phase;
if (align == 0)
{
- tree type;
-
- if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT;
- else
- alignment = GET_MODE_ALIGNMENT (mode);
-
- /* Allow the target to (possibly) increase the alignment of this
- stack slot. */
- type = lang_hooks.types.type_for_mode (mode, 0);
- if (type)
- alignment = LOCAL_ALIGNMENT (type, alignment);
-
+ alignment = get_stack_local_alignment (NULL, mode);
alignment /= BITS_PER_UNIT;
}
else if (align == -1)
if (alignment * BITS_PER_UNIT > PREFERRED_STACK_BOUNDARY)
alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
- if (crtl->stack_alignment_needed < alignment * BITS_PER_UNIT)
- crtl->stack_alignment_needed = alignment * BITS_PER_UNIT;
+ alignment_in_bits = alignment * BITS_PER_UNIT;
+
+ if (crtl->stack_alignment_needed < alignment_in_bits)
+ crtl->stack_alignment_needed = alignment_in_bits;
/* Calculate how many bytes the start of local variables is off from
stack alignment. */
frame_offset += size;
x = gen_rtx_MEM (mode, addr);
+ set_mem_align (x, alignment_in_bits);
MEM_NOTRAP_P (x) = 1;
stack_slot_list
/* These are now unused. */
gcc_assert (keep <= 1);
- if (mode == BLKmode)
- align = BIGGEST_ALIGNMENT;
- else
- align = GET_MODE_ALIGNMENT (mode);
-
- if (! type)
- type = lang_hooks.types.type_for_mode (mode, 0);
-
- if (type)
- align = LOCAL_ALIGNMENT (type, align);
+ align = get_stack_local_alignment (type, mode);
/* Try to find an available, already-allocated temporary of the proper
mode which meets the size and alignment requirements. Choose the