@@ -15288,12 +15288,23 @@ operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rn, HOST_WIDE_INT offset,
return true;
}
+/* Return true if a 64-bit access with alignment ALIGN and with a
+ constant offset OFFSET from the base pointer is permitted on this
+ architecture. */
+static bool
+align_ok_ldrd_strd (HOST_WIDE_INT align, HOST_WIDE_INT offset)
+{
+ return (unaligned_access
+ ? (align >= BITS_PER_WORD && (offset & 3) == 0)
+ : (align >= 2 * BITS_PER_WORD && (offset & 7) == 0));
+}
+
/* Helper for gen_operands_ldrd_strd. Returns true iff the memory
operand MEM's address contains an immediate offset from the base
- register and has no side effects, in which case it sets BASE and
- OFFSET accordingly. */
+ register and has no side effects, in which case it sets BASE,
+ OFFSET and ALIGN accordingly. */
static bool
-mem_ok_for_ldrd_strd (rtx mem, rtx *base, rtx *offset)
+mem_ok_for_ldrd_strd (rtx mem, rtx *base, rtx *offset, HOST_WIDE_INT *align)
{
rtx addr;
@@ -15312,6 +15323,7 @@ mem_ok_for_ldrd_strd (rtx mem, rtx *base, rtx *offset)
gcc_assert (MEM_P (mem));
*offset = const0_rtx;
+ *align = MEM_ALIGN (mem);
addr = XEXP (mem, 0);
@@ -15352,7 +15364,7 @@ gen_operands_ldrd_strd (rtx *operands, bool load,
bool const_store, bool commute)
{
int nops = 2;
- HOST_WIDE_INT offsets[2], offset;
+ HOST_WIDE_INT offsets[2], offset, align[2];
rtx base = NULL_RTX;
rtx cur_base, cur_offset, tmp;
int i, gap;
@@ -15364,7 +15376,8 @@ gen_operands_ldrd_strd (rtx *operands, bool load,
registers, and the corresponding memory offsets. */
for (i = 0; i < nops; i++)
{
- if (!mem_ok_for_ldrd_strd (operands[nops+i], &cur_base, &cur_offset))
+ if (!mem_ok_for_ldrd_strd (operands[nops+i], &cur_base, &cur_offset,
+ &align[i]))
return false;
if (i == 0)
@@ -15478,6 +15491,7 @@ gen_operands_ldrd_strd (rtx *operands, bool load,
/* Swap the instructions such that lower memory is accessed first. */
std::swap (operands[0], operands[1]);
std::swap (operands[2], operands[3]);
+ std::swap (align[0], align[1]);
if (const_store)
std::swap (operands[4], operands[5]);
}
@@ -15491,6 +15505,9 @@ gen_operands_ldrd_strd (rtx *operands, bool load,
if (gap != 4)
return false;
+ if (!align_ok_ldrd_strd (align[0], offset))
+ return false;
+
/* Make sure we generate legal instructions. */
if (operands_ok_ldrd_strd (operands[0], operands[1], base, offset,
false, load))
@@ -8,4 +8,4 @@ int foo(int a, int b, int* p, int *q)
*p = a;
return a;
}
-/* { dg-final { scan-assembler "ldrd" } } */
+/* { dg-final { scan-assembler "ldrd\\t" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_prefer_ldrd_strd } */
+/* { dg-options "-O2 -mno-unaligned-access" } */
+int foo(int a, int b, int* p, int *q)
+{
+ a = p[2] + p[3];
+ *q = a;
+ *p = a;
+ return a;
+}
+/* { dg-final { scan-assembler-not "ldrd\\t" } } */
@@ -6,4 +6,4 @@ void foo(int a, int b, int* p)
p[2] = a;
p[3] = b;
}
-/* { dg-final { scan-assembler "strd" } } */
+/* { dg-final { scan-assembler "strd\\t" } } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_prefer_ldrd_strd } */
+/* { dg-options "-O2 -mno-unaligned-access" } */
+void foo(int a, int b, int* p)
+{
+ p[2] = a;
+ p[3] = b;
+}
+/* { dg-final { scan-assembler-not "strd\\t" } } */