aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/function.c8
-rw-r--r--gcc/function.h2
-rw-r--r--gcc/lra-spills.c70
4 files changed, 51 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5c8e785..fefba90 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -2,6 +2,17 @@
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
+ * function.h (spill_slot_alignment): Declare.
+ * function.c (spill_slot_alignment): New function.
+ * lra-spills.c (slot): Add align and size fields.
+ (assign_mem_slot): Use them in the call to assign_stack_local.
+ (add_pseudo_to_slot): Update the fields.
+ (assign_stack_slot_num_and_sort_pseudos): Initialise the fields.
+
+2016-11-25 Richard Sandiford <richard.sandiford@arm.com>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
* stor-layout.c (layout_type): Allow the caller to set the mode of
a float type. Only choose one here if the mode is still VOIDmode.
* tree.c (build_common_tree_nodes): Set the type mode of decimal
diff --git a/gcc/function.c b/gcc/function.c
index f191b57..c5a538f 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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
diff --git a/gcc/function.h b/gcc/function.h
index 1aebd90..74bd6ab 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -570,6 +570,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);
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index 6e044cd..9f1d5e9 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -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++;