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;