Commit 76fe54f0 by H.J. Lu Committed by H.J. Lu

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
parent e94a8385
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> 2008-05-26 Kai Tietz <kai.tietz@onevision.com>
PR/36321 PR/36321
......
...@@ -704,6 +704,11 @@ insert_restore (struct insn_chain *chain, int before_p, int regno, ...@@ -704,6 +704,11 @@ insert_restore (struct insn_chain *chain, int before_p, int regno,
mem = adjust_address (mem, save_mode[regno], 0); mem = adjust_address (mem, save_mode[regno], 0);
else else
mem = copy_rtx (mem); 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, pat = gen_rtx_SET (VOIDmode,
gen_rtx_REG (GET_MODE (mem), gen_rtx_REG (GET_MODE (mem),
regno), mem); regno), mem);
...@@ -776,6 +781,11 @@ insert_save (struct insn_chain *chain, int before_p, int regno, ...@@ -776,6 +781,11 @@ insert_save (struct insn_chain *chain, int before_p, int regno,
mem = adjust_address (mem, save_mode[regno], 0); mem = adjust_address (mem, save_mode[regno], 0);
else else
mem = copy_rtx (mem); 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, pat = gen_rtx_SET (VOIDmode, mem,
gen_rtx_REG (GET_MODE (mem), gen_rtx_REG (GET_MODE (mem),
regno)); regno));
......
...@@ -86,10 +86,6 @@ failed: ...@@ -86,10 +86,6 @@ failed:
} }
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
#endif
#ifndef STACK_ALIGNMENT_NEEDED #ifndef STACK_ALIGNMENT_NEEDED
#define STACK_ALIGNMENT_NEEDED 1 #define STACK_ALIGNMENT_NEEDED 1
#endif #endif
......
...@@ -187,7 +187,8 @@ extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, ...@@ -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_return_pops_args (tree, tree, int);
extern int ix86_data_alignment (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 int ix86_constant_alignment (tree, int);
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *); extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *); extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
......
...@@ -16996,14 +16996,25 @@ ix86_data_alignment (tree type, int align) ...@@ -16996,14 +16996,25 @@ ix86_data_alignment (tree type, int align)
return align; return align;
} }
/* Compute the alignment for a local variable. /* Compute the alignment for a local variable or a stack slot. TYPE is
TYPE is the data type, and ALIGN is the alignment that the data type, MODE is the widest mode available and ALIGN is the
the object would ordinarily have. The value of this macro is used alignment that the object would ordinarily have. The value of this
instead of that alignment to align the object. */ macro is used instead of that alignment to align the object. */
int unsigned int
ix86_local_alignment (tree type, int align) 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 /* x86-64 ABI requires arrays greater than 16 bytes to be aligned
to 16byte boundary. */ to 16byte boundary. */
if (TARGET_64BIT) if (TARGET_64BIT)
......
...@@ -902,7 +902,22 @@ enum target_cpu_default ...@@ -902,7 +902,22 @@ enum target_cpu_default
One use of this macro is to increase alignment of medium-size One use of this macro is to increase alignment of medium-size
data to make it all fit in fewer cache lines. */ 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 /* If defined, a C expression that gives the alignment boundary, in
bits, of an argument with the specified mode and type. If it is bits, of an argument with the specified mode and type. If it is
......
...@@ -940,4 +940,13 @@ along with GCC; see the file COPYING3. If not see ...@@ -940,4 +940,13 @@ along with GCC; see the file COPYING3. If not see
#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 0 #define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 0
#endif #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 */ #endif /* ! GCC_DEFAULTS_H */
...@@ -1172,6 +1172,21 @@ One use of this macro is to increase alignment of medium-size data to ...@@ -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. make it all fit in fewer cache lines.
@end defmac @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 @defmac EMPTY_FIELD_BOUNDARY
Alignment in bits to be given to a structure bit-field that follows an Alignment in bits to be given to a structure bit-field that follows an
empty field such as @code{int : 0;}. empty field such as @code{int : 0;}.
......
...@@ -69,10 +69,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -69,10 +69,6 @@ along with GCC; see the file COPYING3. If not see
/* So we can assign to cfun in this file. */ /* So we can assign to cfun in this file. */
#undef cfun #undef cfun
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
#endif
#ifndef STACK_ALIGNMENT_NEEDED #ifndef STACK_ALIGNMENT_NEEDED
#define STACK_ALIGNMENT_NEEDED 1 #define STACK_ALIGNMENT_NEEDED 1
#endif #endif
...@@ -325,6 +321,26 @@ frame_offset_overflow (HOST_WIDE_INT offset, tree func) ...@@ -325,6 +321,26 @@ frame_offset_overflow (HOST_WIDE_INT offset, tree func)
return FALSE; 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 /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
with machine mode MODE. with machine mode MODE.
...@@ -341,24 +357,12 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) ...@@ -341,24 +357,12 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
{ {
rtx x, addr; rtx x, addr;
int bigend_correction = 0; int bigend_correction = 0;
unsigned int alignment; unsigned int alignment, alignment_in_bits;
int frame_off, frame_alignment, frame_phase; int frame_off, frame_alignment, frame_phase;
if (align == 0) if (align == 0)
{ {
tree type; alignment = get_stack_local_alignment (NULL, mode);
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 /= BITS_PER_UNIT; alignment /= BITS_PER_UNIT;
} }
else if (align == -1) else if (align == -1)
...@@ -378,8 +382,10 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) ...@@ -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) if (alignment * BITS_PER_UNIT > PREFERRED_STACK_BOUNDARY)
alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
if (crtl->stack_alignment_needed < alignment * BITS_PER_UNIT) alignment_in_bits = alignment * BITS_PER_UNIT;
crtl->stack_alignment_needed = 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 /* Calculate how many bytes the start of local variables is off from
stack alignment. */ stack alignment. */
...@@ -432,6 +438,7 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) ...@@ -432,6 +438,7 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
frame_offset += size; frame_offset += size;
x = gen_rtx_MEM (mode, addr); x = gen_rtx_MEM (mode, addr);
set_mem_align (x, alignment_in_bits);
MEM_NOTRAP_P (x) = 1; MEM_NOTRAP_P (x) = 1;
stack_slot_list stack_slot_list
...@@ -544,16 +551,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size, ...@@ -544,16 +551,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
/* These are now unused. */ /* These are now unused. */
gcc_assert (keep <= 1); gcc_assert (keep <= 1);
if (mode == BLKmode) align = get_stack_local_alignment (type, mode);
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);
/* Try to find an available, already-allocated temporary of the proper /* Try to find an available, already-allocated temporary of the proper
mode which meets the size and alignment requirements. Choose the mode which meets the size and alignment requirements. Choose the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment