If the number of integer callee-saves is odd, any FP callee-saves use 8-byte aligned...
authorWilco Dijkstra <wdijkstr@arm.com>
Fri, 21 Oct 2016 17:04:21 +0000 (17:04 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Fri, 21 Oct 2016 17:04:21 +0000 (17:04 +0000)
If the number of integer callee-saves is odd, any FP callee-saves use 8-byte
aligned LDP/STP.  Since 16-byte alignment may be faster on some CPUs, align
the FP callee-saves to 16 bytes and use the alignment gap for the last FP
callee-save when possible.

    gcc/
        * config/aarch64/aarch64.c (aarch64_layout_frame):
        Align FP callee-saves.

From-SVN: r241419

gcc/ChangeLog
gcc/config/aarch64/aarch64.c

index 6102719..0625c00 100644 (file)
@@ -1,3 +1,8 @@
+2016-10-21  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       * config/aarch64/aarch64.c (aarch64_layout_frame):
+       Align FP callee-saves.
+
 2016-10-21  Jakub Jelinek  <jakub@redhat.com>
 
        * config/i386/adxintrin.h (_subborrow_u32, _addcarry_u32,
index 6b27309..584e1f5 100644 (file)
@@ -2734,7 +2734,7 @@ static void
 aarch64_layout_frame (void)
 {
   HOST_WIDE_INT offset = 0;
-  int regno;
+  int regno, last_fp_reg = INVALID_REGNUM;
 
   if (reload_completed && cfun->machine->frame.laid_out)
     return;
@@ -2768,7 +2768,10 @@ aarch64_layout_frame (void)
   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
     if (df_regs_ever_live_p (regno)
        && !call_used_regs[regno])
-      cfun->machine->frame.reg_offset[regno] = SLOT_REQUIRED;
+      {
+       cfun->machine->frame.reg_offset[regno] = SLOT_REQUIRED;
+       last_fp_reg = regno;
+      }
 
   if (frame_pointer_needed)
     {
@@ -2792,9 +2795,21 @@ aarch64_layout_frame (void)
        offset += UNITS_PER_WORD;
       }
 
+  HOST_WIDE_INT max_int_offset = offset;
+  offset = ROUND_UP (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+  bool has_align_gap = offset != max_int_offset;
+
   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
     if (cfun->machine->frame.reg_offset[regno] == SLOT_REQUIRED)
       {
+       /* If there is an alignment gap between integer and fp callee-saves,
+          allocate the last fp register to it if possible.  */
+       if (regno == last_fp_reg && has_align_gap && (offset & 8) == 0)
+         {
+           cfun->machine->frame.reg_offset[regno] = max_int_offset;
+           break;
+         }
+
        cfun->machine->frame.reg_offset[regno] = offset;
        if (cfun->machine->frame.wb_candidate1 == INVALID_REGNUM)
          cfun->machine->frame.wb_candidate1 = regno;