Hi,

LRA generates an unaligned memory access for 32-bit SPARC on the attached 
testcase when it is compiled with optimization.  It's again the business of 
paradoxical subregs of memory dealt with by simplify_operand_subreg:

          /* If we change the address for a paradoxical subreg of memory, the
            address might violate the necessary alignment or the access might
             be slow.  So take this into consideration.  We need not worry
             about accesses beyond allocated memory for paradoxical memory
             subregs as we don't substitute such equiv memory (see processing
            equivalences in function lra_constraints) and because for spilled
             pseudos we allocate stack memory enough for the biggest
             corresponding paradoxical subreg.  */
          if (!(MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (mode)
                && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)))
              || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
                  && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg))))
            return true;

However the code contains a small inaccuracy: it tests the old MEM (reg) which 
has mode INNERMODE in the first branch of the condition instead of testing the 
new MEM (subst) which has mode MODE.  That's benign for little-endian targets 
since the offset doesn't change, but not for big-endian ones where it changes 
and thus also can change the alignment.

The attached fix was bootstrapped/regtested on SPARC/Solaris, OK for mainline?


2017-01-10  Eric Botcazou  <ebotca...@adacore.com>

        PR rtl-optimization/79032
        * lra-constraints.c (simplify_operand_subreg): In the MEM case, test
        the alignment of the adjusted memory reference against that of MODE,
        instead of the alignment of the original memory reference.


2017-01-10  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.c-torture/execute/20170110-1.c: New test.

-- 
Eric Botcazou
/* PR rtl-optimization/79032 */

extern void abort (void);

struct S {
  short a;
  long long b;
  short c;
  char d;
  unsigned short e;
  long *f;
};

static long foo (struct S *s) __attribute__((noclone, noinline));

static long foo (struct S *s)
{
  long a = 1;
  a /= s->e;
  s->f[a]--;
  return a;
}

int main (void)
{
  long val = 1;
  struct S s = { 0, 0, 0, 0, 2, &val };
  val = foo (&s);
  if (val != 0)
    abort ();
  return 0;
}
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 244194)
+++ lra-constraints.c	(working copy)
@@ -1505,15 +1505,15 @@ simplify_operand_subreg (int nop, machin
 				  MEM_ADDR_SPACE (subst))))
 	{
 	  /* If we change the address for a paradoxical subreg of memory, the
-	     address might violate the necessary alignment or the access might
-	     be slow.  So take this into consideration.  We need not worry
+	     new address might violate the necessary alignment or the access
+	     might be slow; take this into consideration.  We need not worry
 	     about accesses beyond allocated memory for paradoxical memory
 	     subregs as we don't substitute such equiv memory (see processing
 	     equivalences in function lra_constraints) and because for spilled
 	     pseudos we allocate stack memory enough for the biggest
 	     corresponding paradoxical subreg.  */
-	  if (!(MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (mode)
-		&& SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (reg)))
+	  if (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
+		&& SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
 	      || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
 		  && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg))))
 	    return true;

Reply via email to