From: H.J. Lu Date: Mon, 26 May 2008 13:59:56 +0000 (+0000) Subject: re PR middle-end/36253 (Caller-save stack slot may not have proper alignment) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=76fe54f07ae1d8e9a8a3bbc54dd9aaeee4105d18;p=gcc.git re PR middle-end/36253 (Caller-save stack slot may not have proper alignment) 2008-05-26 H.J. Lu 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f12440f1afe..a6fad4f55ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2008-05-26 H.J. Lu + + 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 PR/36321 diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 7976fd5fd75..c6a685bde9c 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -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)); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 69a911eac8e..ffe2366a108 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -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 diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index aee90eb65bd..6fdea06c518 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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 *); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 369ae584867..6cac18ae8aa 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 0b5ca139350..ef8da17af3f 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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 diff --git a/gcc/defaults.h b/gcc/defaults.h index ff5b5c01cf3..392d22cfabb 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -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 */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 8c0de3b41de..eeb744bd60d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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;}. diff --git a/gcc/function.c b/gcc/function.c index f5a67404562..845017f7124 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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