This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Spill slot alignment


gcc.c-torture/execute/20050121-1.c fails for 64-bit multilibs of
mipsisa64-elf.  The problem is that we have a CSImode register that is
sometimes accessed using a DImode subreg, and the register is spilled to
the stack.  The CSImode accesses only need the spill slot to have 4-byte
alignment, but the DImode accesses need it to have 8.

reload already caters for cases like these if the subregs are
paradoxical.  However, because in this case the subreg mode is
the same size as the register mode, reload assumes that the
register's usual CSImode alignment will be enough.

The current code can pass one of two alignment values to
assign_stack_local:

  - 0, to get the "natural" alignment for the register's mode,
    possibly modified by the backend.

  - -1, to get the biggest useful alignment.

Although it might be useful to specify a particular alignment when 0
isn't enough, I think that any such change should be done separately
from a bug fix, and isn't really stage 3 material.

The patch below therefore just uses -1 if the register's natural
alignment isn't enough, just as we do when its natural size isn't
enough.  For simplicity, and to avoid creating too many variables,
the patch assumes that we need reg_max_ref_width[i] bytes of alignment,
and makes sure that reg_max_ref_width really is the maximum reference
width (it isn't at present).  I think this approach is reasonable because:

  (a) if the maximum reference width is greater than the
      register width, we'll be passing an alignment of -1 anyway.

  (b) if the maximum reference width is less than or equal to
      the register width, but is greater than the register mode's
      alignment, all subregs should be integer modes.

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also regression-tested
on mipsisa64-elf, where it fixes gcc.c-torture/execute/20050121-1.c and
gcc.dg/compat/scalar-return-3.c.  OK to install?

Richard


gcc/
	* reload1.c (alter_reg): Require the alignment of the stack slot to
	be at least reg_max_ref_width bytes.
	(scan_paradoxical_subregs): Record the largest width in
	reg_max_ref_width.

Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	(revision 117059)
+++ gcc/reload1.c	(working copy)
@@ -1982,8 +1982,11 @@ alter_reg (int i, int from_reg)
       && reg_equiv_memory_loc[i] == 0)
     {
       rtx x;
+      enum 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 total_size = MAX (inherent_size, reg_max_ref_width[i]);
+      unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
       /* Each pseudo reg has an inherent size which comes from its own mode,
@@ -1997,8 +2000,9 @@ alter_reg (int i, int from_reg)
       if (from_reg == -1)
 	{
 	  /* No known place to spill from => no slot to reuse.  */
-	  x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size,
-				  inherent_size == total_size ? 0 : -1);
+	  x = assign_stack_local (mode, total_size,
+				  min_align > inherent_align
+				  || total_size > inherent_size ? -1 : 0);
 	  if (BYTES_BIG_ENDIAN)
 	    /* Cancel the  big-endian correction done in assign_stack_local.
 	       Get the address of the beginning of the slot.
@@ -2014,7 +2018,8 @@ alter_reg (int i, int from_reg)
       else if (spill_stack_slot[from_reg] != 0
 	       && spill_stack_slot_width[from_reg] >= total_size
 	       && (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
-		   >= inherent_size))
+		   >= inherent_size)
+	       && MEM_ALIGN (spill_stack_slot[from_reg]) >= min_align)
 	x = spill_stack_slot[from_reg];
 
       /* Allocate a bigger slot.  */
@@ -2022,7 +2027,6 @@ alter_reg (int i, int from_reg)
 	{
 	  /* Compute maximum size needed, both for inherent size
 	     and for total size.  */
-	  enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
 	  rtx stack_slot;
 
 	  if (spill_stack_slot[from_reg])
@@ -2032,11 +2036,14 @@ alter_reg (int i, int from_reg)
 		mode = GET_MODE (spill_stack_slot[from_reg]);
 	      if (spill_stack_slot_width[from_reg] > total_size)
 		total_size = spill_stack_slot_width[from_reg];
+	      if (MEM_ALIGN (spill_stack_slot[from_reg]) > min_align)
+		min_align = MEM_ALIGN (spill_stack_slot[from_reg]);
 	    }
 
 	  /* Make a slot with that size.  */
 	  x = assign_stack_local (mode, total_size,
-				  inherent_size == total_size ? 0 : -1);
+				  min_align > inherent_align
+				  || total_size > inherent_size ? -1 : 0);
 	  stack_slot = x;
 
 	  /* All pseudos mapped to this slot can alias each other.  */
@@ -3814,7 +3821,8 @@ scan_paradoxical_subregs (rtx x)
 
     case SUBREG:
       if (REG_P (SUBREG_REG (x))
-	  && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+	  && (GET_MODE_SIZE (GET_MODE (x))
+	      > reg_max_ref_width[REGNO (SUBREG_REG (x))]))
 	reg_max_ref_width[REGNO (SUBREG_REG (x))]
 	  = GET_MODE_SIZE (GET_MODE (x));
       return;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]