diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/function.c | 8 | ||||
-rw-r--r-- | gcc/function.h | 2 | ||||
-rw-r--r-- | gcc/lra-spills.c | 70 |
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++; |