re PR middle-end/36253 (Caller-save stack slot may not have proper alignment)

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.

From-SVN: r135927
This commit is contained in:
H.J. Lu 2008-05-26 13:59:56 +00:00 committed by H.J. Lu
parent e94a83856f
commit 76fe54f07a
9 changed files with 122 additions and 42 deletions

View File

@ -1,3 +1,28 @@
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

View File

@ -704,6 +704,11 @@ insert_restore (struct insn_chain *chain, int before_p, int regno,
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);
@ -776,6 +781,11 @@ insert_save (struct insn_chain *chain, int before_p, int regno,
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));

View File

@ -86,10 +86,6 @@ failed:
}
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
#endif
#ifndef STACK_ALIGNMENT_NEEDED
#define STACK_ALIGNMENT_NEEDED 1
#endif

View File

@ -187,7 +187,8 @@ extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
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 *);

View File

@ -16996,14 +16996,25 @@ ix86_data_alignment (tree type, int align)
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)

View File

@ -902,7 +902,22 @@ enum target_cpu_default
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

View File

@ -940,4 +940,13 @@ along with GCC; see the file COPYING3. If not see
#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 */

View File

@ -1172,6 +1172,21 @@ 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 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;}.

View File

@ -69,10 +69,6 @@ along with GCC; see the file COPYING3. If not see
/* 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
@ -325,6 +321,26 @@ frame_offset_overflow (HOST_WIDE_INT offset, tree func)
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.
@ -341,24 +357,12 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
{
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)
@ -378,8 +382,10 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
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. */
@ -432,6 +438,7 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
frame_offset += size;
x = gen_rtx_MEM (mode, addr);
set_mem_align (x, alignment_in_bits);
MEM_NOTRAP_P (x) = 1;
stack_slot_list
@ -544,16 +551,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
/* 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