diff options
author | Christophe Lyon <christophe.lyon@linaro.org> | 2016-02-18 15:58:12 +0100 |
---|---|---|
committer | Linaro Code Review <review@review.linaro.org> | 2016-03-14 13:50:24 +0000 |
commit | 42dc2c15dc21c20a56cc08f06a8587541a0c1a73 (patch) | |
tree | 79ee95f907f518298029a0132fd965c7efdc69ba | |
parent | b924efdff5db48aba7c0687738788b13410ae675 (diff) |
gcc/
Backport from trunk r233518.
2016-02-18 Nick Clifton <nickc@redhat.com>
PR target/62254
PR target/69610
* config/arm/arm.c (arm_option_override_internal): Disable
interworking if the target does not support thumb instructions.
(arm_reload_in_hi): Handle the case where a register to register
move needs reloading because there is no simple pattern to handle
it.
(arm_reload_out_hi): Likewise.
gcc/testsuite/
Backport from trunk r233518.
2016-02-18 Nick Clifton <nickc@redhat.com>
PR target/62254
PR target/69610
* gcc.target/arm/pr62554.c: New test.
* gcc.target/arm/pr69610-1.c: New test.
* gcc.target/arm/pr69610-2.c: New test.
Change-Id: Ie85ad94742a222e98f84ad14e17d24c5490f875e
-rw-r--r-- | gcc/config/arm/arm.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pr62554.c | 51 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pr69610-1.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pr69610-2.c | 33 |
4 files changed, 129 insertions, 0 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 1f4fbfbded4..58f2f113d01 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -2841,6 +2841,14 @@ static void arm_option_override_internal (struct gcc_options *opts, struct gcc_options *opts_set) { + if (TARGET_INTERWORK && !ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB)) + { + /* The default is to enable interworking, so this warning message would + be confusing to users who have just compiled with, eg, -march=armv3. */ + /* warning (0, "ignoring -minterwork because target CPU does not support THUMB"); */ + opts->x_target_flags &= ~MASK_INTERWORK; + } + if (TARGET_THUMB_P (opts->x_target_flags) && !(ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB))) { @@ -15388,6 +15396,17 @@ arm_reload_in_hi (rtx *operands) else /* The slot is out of range, or was dressed up in a SUBREG. */ base = reg_equiv_address (REGNO (ref)); + + /* PR 62554: If there is no equivalent memory location then just move + the value as an SImode register move. This happens when the target + architecture variant does not have an HImode register move. */ + if (base == NULL) + { + gcc_assert (REG_P (operands[0])); + emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, operands[0], 0), + gen_rtx_SUBREG (SImode, ref, 0))); + return; + } } else base = find_replacement (&XEXP (ref, 0)); @@ -15505,6 +15524,17 @@ arm_reload_out_hi (rtx *operands) else /* The slot is out of range, or was dressed up in a SUBREG. */ base = reg_equiv_address (REGNO (ref)); + + /* PR 62554: If there is no equivalent memory location then just move + the value as an SImode register move. This happens when the target + architecture variant does not have an HImode register move. */ + if (base == NULL) + { + gcc_assert (REG_P (outval)); + emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, ref, 0), + gen_rtx_SUBREG (SImode, outval, 0))); + return; + } } else base = find_replacement (&XEXP (ref, 0)); @@ -19570,6 +19600,7 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, break; case ARM_FT_INTERWORKED: + gcc_assert (arm_arch5 || arm_arch4t); sprintf (instr, "bx%s\t%%|lr", conditional); break; diff --git a/gcc/testsuite/gcc.target/arm/pr62554.c b/gcc/testsuite/gcc.target/arm/pr62554.c new file mode 100644 index 00000000000..4d6501cba1f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr62554.c @@ -0,0 +1,51 @@ +/* Check that pre ARMv4 compilation still works. */ +/* { dg-do compile } */ +/* { dg-options "-marm -march=armv3 -O" } */ +/* { dg-require-effective-target arm_arm_ok } */ + +typedef struct +{ + char bits; + short val; +} code; + +union uu +{ + short us; + char b[2]; +}; + +int a, b, c, f, g, h; +code *d; + +code e; + +int +fn1 (void) +{ + char i; + do + if (e.bits) + { + dodist: + f = c; + if (e.bits & 6) + { + ++i; + if (g) + do + { + union uu j; + j.b[1] = a; + h = j.us; + } + while (fn1); + } + else + { + e = d[b]; + goto dodist; + } + } + while (i); +} diff --git a/gcc/testsuite/gcc.target/arm/pr69610-1.c b/gcc/testsuite/gcc.target/arm/pr69610-1.c new file mode 100644 index 00000000000..a671b93392b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr69610-1.c @@ -0,0 +1,14 @@ +/* Check that pre ARMv4 compilation still works. */ +/* { dg-do compile } */ +/* { dg-options "-marm -march=armv3 -ftree-ter" } */ +/* { dg-require-effective-target arm_arm_ok } */ + +typedef unsigned short v16u16 __attribute__ ((vector_size (16))); +typedef unsigned int v16u32 __attribute__ ((vector_size (16))); + +unsigned short +foo (v16u16 v16u16_1, v16u32 v16u32_1) +{ + v16u16_1 += (v16u16) v16u32_1; + return v16u16_1[5] + v16u32_1[1]; +} diff --git a/gcc/testsuite/gcc.target/arm/pr69610-2.c b/gcc/testsuite/gcc.target/arm/pr69610-2.c new file mode 100644 index 00000000000..e932c63b639 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr69610-2.c @@ -0,0 +1,33 @@ +/* Check that pre ARMv4 compilation still works. */ +/* { dg-do compile } */ +/* { dg-options "-marm -march=armv3 -O2 -fno-forward-propagate" } */ +/* { dg-require-effective-target arm_arm_ok } */ + +typedef short v16u16 __attribute__ ((vector_size (16))); +typedef unsigned v16u32 __attribute__ ((vector_size (16))); +typedef long long v16u64 __attribute__ ((vector_size (16))); + +unsigned +foo + (int + u16_0, + unsigned + u32_0, + int + u64_0, + int + u16_1, + unsigned + u64_1, + v16u16 + v16u16_0, + v16u32 + v16u32_0, + v16u64 v16u64_0, v16u16 v16u16_1, v16u32 v16u32_1, v16u64 v16u64_1) +{ + v16u16_1[3] -= v16u32_0[0]; + v16u16_0 -= (v16u16) v16u32_0; + return u16_0 + u32_0 + u64_0 + u16_1 + + v16u16_0[0] + v16u16_0[2] + v16u16_0[3] + v16u16_0[4] + v16u16_0[5] + v16u32_0[0] + v16u32_0[1] + v16u32_0[3] + v16u64_0[1] + + v16u16_1[2] + v16u16_1[3] + v16u16_1[5] + v16u16_1[7] + v16u32_1[0] + v16u32_1[3] + v16u64_1[0] + v16u64_1[1]; +} |