aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2008-05-26 13:59:56 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2008-05-26 06:59:56 -0700
commit76fe54f07ae1d8e9a8a3bbc54dd9aaeee4105d18 (patch)
treebb649ed6b0709e0e99f74f303514800816a201fe /gcc
parente94a83856fa29fc559ab6bfe013ea6cf16f401fa (diff)
downloadgcc-76fe54f07ae1d8e9a8a3bbc54dd9aaeee4105d18.zip
gcc-76fe54f07ae1d8e9a8a3bbc54dd9aaeee4105d18.tar.gz
gcc-76fe54f07ae1d8e9a8a3bbc54dd9aaeee4105d18.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/caller-save.c10
-rw-r--r--gcc/cfgexpand.c4
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c23
-rw-r--r--gcc/config/i386/i386.h17
-rw-r--r--gcc/defaults.h9
-rw-r--r--gcc/doc/tm.texi15
-rw-r--r--gcc/function.c58
9 files changed, 122 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f12440f..a6fad4f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 7976fd5..c6a685b 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 69a911e..ffe2366 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 aee90eb..6fdea06 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 369ae58..6cac18a 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 0b5ca13..ef8da17 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 ff5b5c0..392d22c 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 8c0de3b..eeb744b 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 f5a6740..845017f 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