aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@linaro.org>2016-02-18 15:58:12 +0100
committerLinaro Code Review <review@review.linaro.org>2016-03-14 13:50:24 +0000
commit42dc2c15dc21c20a56cc08f06a8587541a0c1a73 (patch)
tree79ee95f907f518298029a0132fd965c7efdc69ba
parentb924efdff5db48aba7c0687738788b13410ae675 (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.c31
-rw-r--r--gcc/testsuite/gcc.target/arm/pr62554.c51
-rw-r--r--gcc/testsuite/gcc.target/arm/pr69610-1.c14
-rw-r--r--gcc/testsuite/gcc.target/arm/pr69610-2.c33
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];
+}