@@ -246,6 +246,14 @@ frame_offset_overflow (HOST_WIDE_INT offset, tree func)
return FALSE;
}
+/* Return the minimum spill slot alignment for a register of mode MODE. */
+
+unsigned int
+spill_slot_alignment (machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return STACK_SLOT_ALIGNMENT (NULL_TREE, mode, GET_MODE_ALIGNMENT (mode));
+}
+
/* Return stack slot alignment in bits for TYPE and MODE. */
static unsigned int
@@ -567,6 +567,8 @@ extern HOST_WIDE_INT get_frame_size (void);
return FALSE. */
extern bool frame_offset_overflow (HOST_WIDE_INT, tree);
+extern unsigned int spill_slot_alignment (machine_mode);
+
extern rtx assign_stack_local_1 (machine_mode, HOST_WIDE_INT, int, int);
extern rtx assign_stack_local (machine_mode, HOST_WIDE_INT, int);
extern rtx assign_stack_temp_for_type (machine_mode, HOST_WIDE_INT, tree);
@@ -104,6 +104,10 @@ struct slot
/* Hard reg into which the slot pseudos are spilled. The value is
negative for pseudos spilled into memory. */
int hard_regno;
+ /* Maximum alignment required by all users of the slot. */
+ unsigned int align;
+ /* Maximum size required by all users of the slot. */
+ HOST_WIDE_INT size;
/* Memory representing the all stack slot. It can be different from
memory representing a pseudo belonging to give stack slot because
pseudo can be placed in a part of the corresponding stack slot.
@@ -128,51 +132,23 @@ assign_mem_slot (int i)
{
rtx x = NULL_RTX;
machine_mode mode = GET_MODE (regno_reg_rtx[i]);
- unsigned int inherent_size = PSEUDO_REGNO_BYTES (i);
- unsigned int inherent_align = GET_MODE_ALIGNMENT (mode);
- unsigned int max_ref_width = GET_MODE_SIZE (lra_reg_info[i].biggest_mode);
- unsigned int total_size = MAX (inherent_size, max_ref_width);
- unsigned int min_align = max_ref_width * BITS_PER_UNIT;
- int adjust = 0;
+ HOST_WIDE_INT inherent_size = PSEUDO_REGNO_BYTES (i);
+ machine_mode wider_mode
+ = (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (lra_reg_info[i].biggest_mode)
+ ? mode : lra_reg_info[i].biggest_mode);
+ HOST_WIDE_INT total_size = GET_MODE_SIZE (wider_mode);
+ HOST_WIDE_INT adjust = 0;
lra_assert (regno_reg_rtx[i] != NULL_RTX && REG_P (regno_reg_rtx[i])
&& lra_reg_info[i].nrefs != 0 && reg_renumber[i] < 0);
- x = slots[pseudo_slots[i].slot_num].mem;
-
- /* We can use a slot already allocated because it is guaranteed the
- slot provides both enough inherent space and enough total
- space. */
- if (x)
- ;
- /* Each pseudo has an inherent size which comes from its own mode,
- and a total size which provides room for paradoxical subregs
- which refer to the pseudo reg in wider modes. We allocate a new
- slot, making sure that it has enough inherent space and total
- space. */
- else
+ unsigned int slot_num = pseudo_slots[i].slot_num;
+ x = slots[slot_num].mem;
+ if (!x)
{
- rtx stack_slot;
-
- /* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (mode, total_size,
- min_align > inherent_align
- || total_size > inherent_size ? -1 : 0);
- stack_slot = x;
- /* Cancel the big-endian correction done in assign_stack_local.
- Get the address of the beginning of the slot. This is so we
- can do a big-endian correction unconditionally below. */
- if (BYTES_BIG_ENDIAN)
- {
- adjust = inherent_size - total_size;
- if (adjust)
- stack_slot
- = adjust_address_nv (x,
- mode_for_size (total_size * BITS_PER_UNIT,
- MODE_INT, 1),
- adjust);
- }
- slots[pseudo_slots[i].slot_num].mem = stack_slot;
+ x = assign_stack_local (BLKmode, slots[slot_num].size,
+ slots[slot_num].align);
+ slots[slot_num].mem = x;
}
/* On a big endian machine, the "address" of the slot is the address
@@ -335,6 +311,18 @@ add_pseudo_to_slot (int regno, int slot_num)
{
struct pseudo_slot *first;
+ /* Each pseudo has an inherent size which comes from its own mode,
+ and a total size which provides room for paradoxical subregs.
+ We need to make sure the size and alignment of the slot are
+ sufficient for both. */
+ machine_mode mode = (GET_MODE_SIZE (PSEUDO_REGNO_MODE (regno))
+ >= GET_MODE_SIZE (lra_reg_info[regno].biggest_mode)
+ ? PSEUDO_REGNO_MODE (regno)
+ : lra_reg_info[regno].biggest_mode);
+ unsigned int align = spill_slot_alignment (mode);
+ slots[slot_num].align = MAX (slots[slot_num].align, align);
+ slots[slot_num].size = MAX (slots[slot_num].size, GET_MODE_SIZE (mode));
+
if (slots[slot_num].regno < 0)
{
/* It is the first pseudo in the slot. */
@@ -385,6 +373,8 @@ assign_stack_slot_num_and_sort_pseudos (int *pseudo_regnos, int n)
{
/* New slot. */
slots[j].live_ranges = NULL;
+ slots[j].size = 0;
+ slots[j].align = BITS_PER_UNIT;
slots[j].regno = slots[j].hard_regno = -1;
slots[j].mem = NULL_RTX;
slots_num++;