summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/i386/i386.h40
-rw-r--r--gcc/function.c99
-rw-r--r--gcc/stmt.c7
-rw-r--r--gcc/tm.texi12
5 files changed, 143 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 65d743af9d3..92da3b23e7c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+Thu Feb 11 00:08:17 1999 John Wehle (john@feith.com)
+
+ * function.c (assign_stack_temp_for_type): Clear best_p
+ when an exact match is found.
+
+ * i386.h (LOCAL_ALIGNMENT): Define.
+ * function.c (assign_stack_local, assign_outer_stack_local): Use it.
+ (assign_stack_temp_for_type): New function based on assign_stack_temp.
+ (assign_stack_temp): Call it.
+ (assign_temp): Use assign_stack_temp_for_type, not assign_stack_temp.
+ * stmt.c: Use assign_temp, not assign_stack_temp.
+ * tm.texi: Document LOCAL_ALIGNMENT.
+
Wed Feb 10 23:28:28 1999 Jeffrey A Law (law@cygnus.com)
* reorg.c: Finish deleting half-deleted comment.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 9e1150b0be3..718c7191817 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -502,6 +502,46 @@ extern int ix86_arch;
: (ALIGN)) \
: (ALIGN))
+/* If defined, a C expression to 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.
+
+ If this macro is not defined, then ALIGN is used.
+
+ 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) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ ? ((TYPE_MODE (TREE_TYPE (TYPE)) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TREE_TYPE (TYPE)) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : TREE_CODE (TYPE) == COMPLEX_TYPE \
+ ? ((TYPE_MODE (TYPE) == DCmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TYPE) == XCmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : ((TREE_CODE (TYPE) == RECORD_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == QUAL_UNION_TYPE) \
+ && TYPE_FIELDS (TYPE)) \
+ ? ((DECL_MODE (TYPE_FIELDS (TYPE)) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (DECL_MODE (TYPE_FIELDS (TYPE)) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : TREE_CODE (TYPE) == REAL_TYPE \
+ ? ((TYPE_MODE (TYPE) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TYPE) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : (ALIGN))
+
/* Set this non-zero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 0
diff --git a/gcc/function.c b/gcc/function.c
index c9ec569c570..a14a886d4e8 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -65,6 +65,10 @@ Boston, MA 02111-1307, USA. */
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
#endif
+#ifndef LOCAL_ALIGNMENT
+#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
+#endif
+
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@@ -386,6 +390,8 @@ struct temp_slot
/* The rtx used to represent the address if not the address of the
slot above. May be an EXPR_LIST if multiple addresses exist. */
rtx address;
+ /* The alignment (in bits) of the slot. */
+ int align;
/* The size, in units, of the slot. */
HOST_WIDE_INT size;
/* The value of `sequence_rtl_expr' when this temporary is allocated. */
@@ -440,6 +446,8 @@ struct fixup_replacement
static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
int, struct function *));
+static rtx assign_stack_temp_for_type PROTO ((enum machine_mode, HOST_WIDE_INT,
+ int, tree));
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
@@ -716,9 +724,19 @@ assign_stack_local (mode, size, align)
if (align == 0)
{
- alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ tree type;
+
+ alignment = GET_MODE_ALIGNMENT (mode);
if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ alignment = BIGGEST_ALIGNMENT;
+
+ /* Allow the target to (possibly) increase the alignment of this
+ stack slot. */
+ type = type_for_mode (mode, 0);
+ if (type)
+ alignment = LOCAL_ALIGNMENT (type, alignment);
+
+ alignment /= BITS_PER_UNIT;
}
else if (align == -1)
{
@@ -791,9 +809,19 @@ assign_outer_stack_local (mode, size, align, function)
if (align == 0)
{
- alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ tree type;
+
+ alignment = GET_MODE_ALIGNMENT (mode);
if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ alignment = BIGGEST_ALIGNMENT;
+
+ /* Allow the target to (possibly) increase the alignment of this
+ stack slot. */
+ type = type_for_mode (mode, 0);
+ if (type)
+ alignment = LOCAL_ALIGNMENT (type, alignment);
+
+ alignment /= BITS_PER_UNIT;
}
else if (align == -1)
{
@@ -849,12 +877,14 @@ assign_outer_stack_local (mode, size, align, function)
if we are to allocate something at an inner level to be treated as
a variable in the block (e.g., a SAVE_EXPR). */
-rtx
-assign_stack_temp (mode, size, keep)
+static rtx
+assign_stack_temp_for_type (mode, size, keep, type)
enum machine_mode mode;
HOST_WIDE_INT size;
int keep;
+ tree type;
{
+ int align;
struct temp_slot *p, *best_p = 0;
/* If SIZE is -1 it means that somebody tried to allocate a temporary
@@ -862,19 +892,31 @@ assign_stack_temp (mode, size, keep)
if (size == -1)
abort ();
- /* First try to find an available, already-allocated temporary that is the
- exact size we require. */
- for (p = temp_slots; p; p = p->next)
- if (p->size == size && GET_MODE (p->slot) == mode && ! p->in_use)
- break;
+ align = GET_MODE_ALIGNMENT (mode);
+ if (mode == BLKmode)
+ align = BIGGEST_ALIGNMENT;
- /* If we didn't find, one, try one that is larger than what we want. We
- find the smallest such. */
- if (p == 0)
- for (p = temp_slots; p; p = p->next)
- if (p->size > size && GET_MODE (p->slot) == mode && ! p->in_use
- && (best_p == 0 || best_p->size > p->size))
+ if (! type)
+ type = type_for_mode (mode, 0);
+ if (type)
+ align = LOCAL_ALIGNMENT (type, align);
+
+ /* Try to find an available, already-allocated temporary of the proper
+ mode which meets the size and alignment requirements. Choose the
+ smallest one with the closest alignment. */
+ for (p = temp_slots; p; p = p->next)
+ if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
+ && ! p->in_use
+ && (best_p == 0 || best_p->size > p->size
+ || (best_p->size == p->size && best_p->align > p->align)))
+ {
+ if (p->align == align && p->size == size)
+ {
+ best_p = 0;
+ break;
+ }
best_p = p;
+ }
/* Make our best, if any, the one to use. */
if (best_p)
@@ -884,7 +926,7 @@ assign_stack_temp (mode, size, keep)
for BLKmode slots, so that we can be sure of the alignment. */
if (GET_MODE (best_p->slot) == BLKmode)
{
- int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ int alignment = best_p->align / BITS_PER_UNIT;
HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
if (best_p->size - rounded_size >= alignment)
@@ -897,6 +939,7 @@ assign_stack_temp (mode, size, keep)
p->slot = gen_rtx_MEM (BLKmode,
plus_constant (XEXP (best_p->slot, 0),
rounded_size));
+ p->align = best_p->align;
p->address = 0;
p->rtl_expr = 0;
p->next = temp_slots;
@@ -920,9 +963,9 @@ assign_stack_temp (mode, size, keep)
p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
- /* If the temp slot mode doesn't indicate the alignment,
- use the largest possible, so no one will be disappointed. */
- p->slot = assign_stack_local (mode, size, mode == BLKmode ? -1 : 0);
+ p->slot = assign_stack_local (mode, size, align);
+
+ p->align = align;
/* The following slot size computation is necessary because we don't
know the actual size of the temporary slot until assign_stack_local
@@ -978,6 +1021,18 @@ assign_stack_temp (mode, size, keep)
MEM_ALIAS_SET (p->slot) = 0;
return p->slot;
}
+
+/* Allocate a temporary stack slot and record it for possible later
+ reuse. First three arguments are same as in preceding function. */
+
+rtx
+assign_stack_temp (mode, size, keep)
+ enum machine_mode mode;
+ HOST_WIDE_INT size;
+ int keep;
+{
+ return assign_stack_temp_for_type (mode, size, keep, NULL_TREE);
+}
/* Assign a temporary of given TYPE.
KEEP is as for assign_stack_temp.
@@ -1010,7 +1065,7 @@ assign_temp (type, keep, memory_required, dont_promote)
&& TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST)
size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
- tmp = assign_stack_temp (mode, size, keep);
+ tmp = assign_stack_temp_for_type (mode, size, keep, type);
MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type));
return tmp;
}
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 62f880dd4d2..a565adf6402 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -3495,12 +3495,7 @@ expand_decl (decl)
oldaddr = XEXP (DECL_RTL (decl), 0);
}
- DECL_RTL (decl)
- = assign_stack_temp (DECL_MODE (decl),
- ((TREE_INT_CST_LOW (DECL_SIZE (decl))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT),
- 1);
+ DECL_RTL (decl) = assign_temp (TREE_TYPE (decl), 1, 1, 1);
MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
AGGREGATE_TYPE_P (TREE_TYPE (decl)));
diff --git a/gcc/tm.texi b/gcc/tm.texi
index 2e2f688f793..d3dac9fd938 100644
--- a/gcc/tm.texi
+++ b/gcc/tm.texi
@@ -873,6 +873,18 @@ The typical use of this macro is to increase alignment for string
constants to be word aligned so that @code{strcpy} calls that copy
constants can be done inline.
+@findex LOCAL_ALIGNMENT
+@item LOCAL_ALIGNMENT (@var{type}, @var{basic-align})
+If defined, a C expression to compute the alignment for a variables in
+the local store. @var{type} is the data type, and @var{basic-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.
+
+If this macro is not defined, then @var{basic-align} is used.
+
+One use of this macro is to increase alignment of medium-size data to
+make it all fit in fewer cache lines.
+
@findex EMPTY_FIELD_BOUNDARY
@item EMPTY_FIELD_BOUNDARY
Alignment in bits to be given to a structure bit field that follows an