[PATCH][PR84877]Dynamically align the address for local parameter copy on the stack...
[gcc.git] / gcc / function.c
index 302438323c8761fc339bc3c7949f9c28fb6e3a54..954e9468f01f6d325bd34167f023eae374de5934 100644 (file)
@@ -377,6 +377,7 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size,
   poly_int64 bigend_correction = 0;
   poly_int64 slot_offset = 0, old_frame_offset;
   unsigned int alignment, alignment_in_bits;
+  bool dynamic_align_addr = false;
 
   if (align == 0)
     {
@@ -395,14 +396,20 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size,
 
   alignment_in_bits = alignment * BITS_PER_UNIT;
 
-  /* Ignore alignment if it exceeds MAX_SUPPORTED_STACK_ALIGNMENT.  */
   if (alignment_in_bits > MAX_SUPPORTED_STACK_ALIGNMENT)
     {
-      alignment_in_bits = MAX_SUPPORTED_STACK_ALIGNMENT;
-      alignment = alignment_in_bits / BITS_PER_UNIT;
+      /* If the required alignment exceeds MAX_SUPPORTED_STACK_ALIGNMENT and
+        it is not OK to reduce it.  Align the slot dynamically.  */
+      if (mode == BLKmode && (kind & ASLK_REDUCE_ALIGN) == 0)
+       dynamic_align_addr = true;
+      else
+       {
+         alignment_in_bits = MAX_SUPPORTED_STACK_ALIGNMENT;
+         alignment = MAX_SUPPORTED_STACK_ALIGNMENT / BITS_PER_UNIT;
+       }
     }
 
-  if (SUPPORTS_STACK_ALIGNMENT)
+  if (SUPPORTS_STACK_ALIGNMENT && !dynamic_align_addr)
     {
       if (crtl->stack_alignment_estimated < alignment_in_bits)
        {
@@ -432,10 +439,42 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size,
        }
     }
 
-  if (crtl->stack_alignment_needed < alignment_in_bits)
-    crtl->stack_alignment_needed = alignment_in_bits;
-  if (crtl->max_used_stack_slot_alignment < alignment_in_bits)
-    crtl->max_used_stack_slot_alignment = alignment_in_bits;
+  /* Handle overalignment here for parameter copy on the stack.
+     Reserved enough space for it and dynamically align the address.
+     No free frame_space is added here.  */
+  if (dynamic_align_addr)
+    {
+      rtx allocsize = gen_int_mode (size, Pmode);
+      get_dynamic_stack_size (&allocsize, 0, alignment_in_bits, NULL);
+
+      /* This is the size of space needed to accommodate required size of data
+        with given alignment.  */
+      poly_int64 len = rtx_to_poly_int64 (allocsize);
+      old_frame_offset = frame_offset;
+
+      if (FRAME_GROWS_DOWNWARD)
+       {
+         frame_offset -= len;
+         try_fit_stack_local (frame_offset, len, len,
+                              PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT,
+                              &slot_offset);
+       }
+      else
+       {
+         frame_offset += len;
+         try_fit_stack_local (old_frame_offset, len, len,
+                              PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT,
+                              &slot_offset);
+       }
+      goto found_space;
+    }
+  else
+    {
+      if (crtl->stack_alignment_needed < alignment_in_bits)
+       crtl->stack_alignment_needed = alignment_in_bits;
+      if (crtl->max_used_stack_slot_alignment < alignment_in_bits)
+       crtl->max_used_stack_slot_alignment = alignment_in_bits;
+    }
 
   if (mode != BLKmode || maybe_ne (size, 0))
     {
@@ -522,6 +561,12 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size,
                          (slot_offset + bigend_correction,
                           Pmode));
 
+  if (dynamic_align_addr)
+    {
+      addr = align_dynamic_address (addr, alignment_in_bits);
+      mark_reg_pointer (addr, alignment_in_bits);
+    }
+
   x = gen_rtx_MEM (mode, addr);
   set_mem_align (x, alignment_in_bits);
   MEM_NOTRAP_P (x) = 1;