diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7865a036a21..553692dc73a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-10-19 Richard Earnshaw + + * 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. + 2017-10-19 Jakub Jelinek * flag-types.h (enum sanitize_code): Add SANITIZE_BUILTIN. Or diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 013e7d91df0..6f01021a351 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15296,12 +15296,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; @@ -15320,6 +15331,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); @@ -15360,7 +15372,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; @@ -15372,7 +15384,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) @@ -15486,6 +15499,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]); } @@ -15499,6 +15513,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/ChangeLog b/gcc/testsuite/ChangeLog index 0d812b69654..8f17115b364 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-10-19 Richard Earnshaw + + PR target/82445 + * 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. + 2017-10-19 Jakub Jelinek * c-c++-common/ubsan/builtin-1.c: New test. 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-2.c b/gcc/testsuite/gcc.target/arm/peep-ldrd-2.c new file mode 100644 index 00000000000..6822c2b1454 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/peep-ldrd-2.c @@ -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" } } */ 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-2.c b/gcc/testsuite/gcc.target/arm/peep-strd-2.c new file mode 100644 index 00000000000..bfc5ebe9eec --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/peep-strd-2.c @@ -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" } } */