| From ad5bf450aef2ffee6d57ed193fabc5f72f8eaa65 Mon Sep 17 00:00:00 2001 |
| From: rearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4> |
| Date: Thu, 19 Oct 2017 13:16:42 +0000 |
| Subject: [PATCH] [ARM] PR 82445 - suppress 32-bit aligned ldrd/strd peepholing |
| with -mno-unaligned-access |
| |
| Peephole patterns exist in the arm backend to spot load/store |
| operations to adjacent memory operations in order to convert them into |
| ldrd/strd instructions. However, when we have strict alignment |
| enforced, then we can only do this if the accesses are known to be |
| 64-bit aligned; this is unlikely to be the case for most loads. The |
| patch adds some alignment checking to the code that validates the |
| addresses for use in the peephole patterns. This should also fix |
| incorrect generation of ldrd/strd with unaligned accesses that could |
| previously have occurred on ARMv5e where all such operations must be |
| 64-bit aligned. |
| |
| I've added some new tests as well. In doing so I discovered that the |
| ldrd/strd peephole tests could never fail since they would match the |
| source file name in the scanned assembly as well as any instructions |
| of the intended type. I've fixed those by tightening the scan results |
| slightly. |
| |
| gcc: |
| |
| * config/arm/arm.c (align_ok_ldrd_strd): New function. |
| (mem_ok_for_ldrd_strd): New parameter align. Extract the alignment of the |
| mem into it. |
| (gen_operands_ldrd_strd): Validate the alignment of the accesses. |
| |
| testsuite: |
| |
| * gcc.target/arm/peep-ldrd-1.c: Tighten test scan pattern. |
| * gcc.target/arm/peep-strd-1.c: Likewise. |
| * gcc.target/arm/peep-ldrd-2.c: New test. |
| * gcc.target/arm/peep-strd-2.c: New test. |
| |
| |
| |
| git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-6-branch@253892 138bc75d-0d04-0410-961f-82ee72b054a4 |
| --- |
| Upstream-Status: Backport |
| Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| |
| gcc/ChangeLog | 8 +++++++ |
| gcc/config/arm/arm.c | 27 ++++++++++++++++++---- |
| gcc/testsuite/ChangeLog | 8 +++++++ |
| gcc/testsuite/gcc.target/arm/peep-ldrd-1.c | 2 +- |
| .../arm/{peep-ldrd-1.c => peep-ldrd-2.c} | 4 ++-- |
| gcc/testsuite/gcc.target/arm/peep-strd-1.c | 2 +- |
| .../arm/{peep-strd-1.c => peep-strd-2.c} | 4 ++-- |
| 7 files changed, 44 insertions(+), 11 deletions(-) |
| copy gcc/testsuite/gcc.target/arm/{peep-ldrd-1.c => peep-ldrd-2.c} (63%) |
| copy gcc/testsuite/gcc.target/arm/{peep-strd-1.c => peep-strd-2.c} (58%) |
| |
| diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c |
| index 9c0813d598d..e3da9f77fb6 100644 |
| --- a/gcc/config/arm/arm.c |
| +++ b/gcc/config/arm/arm.c |
| @@ -15926,12 +15926,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; |
| |
| @@ -15950,6 +15961,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); |
| |
| @@ -15990,7 +16002,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; |
| @@ -16002,7 +16014,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) |
| @@ -16114,6 +16127,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]); |
| } |
| @@ -16127,6 +16141,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)) |
| diff --git a/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c b/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c |
| index eb2b86ee7b6..d49eff6b87e 100644 |
| --- a/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c |
| +++ b/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c |
| @@ -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" } } */ |
| diff --git a/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c b/gcc/testsuite/gcc.target/arm/peep-ldrd-2.c |
| similarity index 63% |
| copy from gcc/testsuite/gcc.target/arm/peep-ldrd-1.c |
| copy to gcc/testsuite/gcc.target/arm/peep-ldrd-2.c |
| index eb2b86ee7b6..6822c2b1454 100644 |
| --- a/gcc/testsuite/gcc.target/arm/peep-ldrd-1.c |
| +++ b/gcc/testsuite/gcc.target/arm/peep-ldrd-2.c |
| @@ -1,6 +1,6 @@ |
| /* { dg-do compile } */ |
| /* { dg-require-effective-target arm_prefer_ldrd_strd } */ |
| -/* { dg-options "-O2" } */ |
| +/* { dg-options "-O2 -mno-unaligned-access" } */ |
| int foo(int a, int b, int* p, int *q) |
| { |
| a = p[2] + p[3]; |
| @@ -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-not "ldrd\\t" } } */ |
| diff --git a/gcc/testsuite/gcc.target/arm/peep-strd-1.c b/gcc/testsuite/gcc.target/arm/peep-strd-1.c |
| index bd330769599..fe1beac7229 100644 |
| --- a/gcc/testsuite/gcc.target/arm/peep-strd-1.c |
| +++ b/gcc/testsuite/gcc.target/arm/peep-strd-1.c |
| @@ -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" } } */ |
| diff --git a/gcc/testsuite/gcc.target/arm/peep-strd-1.c b/gcc/testsuite/gcc.target/arm/peep-strd-2.c |
| similarity index 58% |
| copy from gcc/testsuite/gcc.target/arm/peep-strd-1.c |
| copy to gcc/testsuite/gcc.target/arm/peep-strd-2.c |
| index bd330769599..bfc5ebe9eec 100644 |
| --- a/gcc/testsuite/gcc.target/arm/peep-strd-1.c |
| +++ b/gcc/testsuite/gcc.target/arm/peep-strd-2.c |
| @@ -1,9 +1,9 @@ |
| /* { dg-do compile } */ |
| /* { dg-require-effective-target arm_prefer_ldrd_strd } */ |
| -/* { dg-options "-O2" } */ |
| +/* { dg-options "-O2 -mno-unaligned-access" } */ |
| void foo(int a, int b, int* p) |
| { |
| p[2] = a; |
| p[3] = b; |
| } |
| -/* { dg-final { scan-assembler "strd" } } */ |
| +/* { dg-final { scan-assembler-not "strd\\t" } } */ |
| -- |
| 2.15.0 |
| |