]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[arm] Avoid STRD with odd register for TARGET_ARM in output_move_double
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 1 Oct 2018 12:39:43 +0000 (12:39 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 1 Oct 2018 12:39:43 +0000 (12:39 +0000)
2018-10-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

Backport from mainline
2018-06-29  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

* config/arm/arm.c (output_move_double): Don't allow STRD instructions
if starting source register is not even.

Backport from mainline
2018-07-02  Christophe Lyon  <christophe.lyon@linaro.org>

* gcc.target/arm/arm-soft-strd-even.c: Skip if -mfloat-abi is
overriden.
2018-06-29  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

* gcc.target/arm/arm-soft-strd-even.c: New test.

From-SVN: r264746

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c [new file with mode: 0644]

index 243391fe835ec2531075dae2ca474e62660dfaf6..5931c2641f2d28cf1c98d4fbe8b68c2c2cc2673a 100644 (file)
@@ -1,3 +1,11 @@
+2018-10-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       Backport from mainline
+       2018-06-29  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/arm/arm.c (output_move_double): Don't allow STRD instructions
+       if starting source register is not even.
+
 2018-09-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/87467
index 886bcfa98b9251f3eb4e348083b2d393c9e93842..f0058a2722d2b3f50a789c3693b28e0e90b430c4 100644 (file)
@@ -18187,12 +18187,18 @@ output_move_double (rtx *operands, bool emit, int *count)
       gcc_assert ((REGNO (operands[1]) != IP_REGNUM)
                   || (TARGET_ARM && TARGET_LDRD));
 
+      /* For TARGET_ARM the first source register of an STRD
+        must be even.  This is usually the case for double-word
+        values but user assembly constraints can force an odd
+        starting register.  */
+      bool allow_strd = TARGET_LDRD
+                        && !(TARGET_ARM && (REGNO (operands[1]) & 1) == 1);
       switch (GET_CODE (XEXP (operands[0], 0)))
         {
        case REG:
          if (emit)
            {
-             if (TARGET_LDRD)
+             if (allow_strd)
                output_asm_insn ("strd%?\t%1, [%m0]", operands);
              else
                output_asm_insn ("stm%?\t%m0, %M1", operands);
@@ -18200,7 +18206,7 @@ output_move_double (rtx *operands, bool emit, int *count)
          break;
 
         case PRE_INC:
-         gcc_assert (TARGET_LDRD);
+         gcc_assert (allow_strd);
          if (emit)
            output_asm_insn ("strd%?\t%1, [%m0, #8]!", operands);
          break;
@@ -18208,7 +18214,7 @@ output_move_double (rtx *operands, bool emit, int *count)
         case PRE_DEC:
          if (emit)
            {
-             if (TARGET_LDRD)
+             if (allow_strd)
                output_asm_insn ("strd%?\t%1, [%m0, #-8]!", operands);
              else
                output_asm_insn ("stmdb%?\t%m0!, %M1", operands);
@@ -18218,7 +18224,7 @@ output_move_double (rtx *operands, bool emit, int *count)
         case POST_INC:
          if (emit)
            {
-             if (TARGET_LDRD)
+             if (allow_strd)
                output_asm_insn ("strd%?\t%1, [%m0], #8", operands);
              else
                output_asm_insn ("stm%?\t%m0!, %M1", operands);
@@ -18226,7 +18232,7 @@ output_move_double (rtx *operands, bool emit, int *count)
          break;
 
         case POST_DEC:
-         gcc_assert (TARGET_LDRD);
+         gcc_assert (allow_strd);
          if (emit)
            output_asm_insn ("strd%?\t%1, [%m0], #-8", operands);
          break;
@@ -18237,8 +18243,8 @@ output_move_double (rtx *operands, bool emit, int *count)
          otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0);
          otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1);
 
-         /* IWMMXT allows offsets larger than ldrd can handle,
-            fix these up with a pair of ldr.  */
+         /* IWMMXT allows offsets larger than strd can handle,
+            fix these up with a pair of str.  */
          if (!TARGET_THUMB2
              && CONST_INT_P (otherops[2])
              && (INTVAL(otherops[2]) <= -256
@@ -18303,7 +18309,7 @@ output_move_double (rtx *operands, bool emit, int *count)
                  return "";
                }
            }
-         if (TARGET_LDRD
+         if (allow_strd
              && (REG_P (otherops[2])
                  || TARGET_THUMB2
                  || (CONST_INT_P (otherops[2])
index d7c87183e3e7df06a9ff53f053ad8c2a5ab7bdbf..92e8f439cf224bb2157ce80ada3817bd9ed00a12 100644 (file)
@@ -1,3 +1,14 @@
+2018-10-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       Backport from mainline
+       2018-07-02  Christophe Lyon  <christophe.lyon@linaro.org>
+
+       * gcc.target/arm/arm-soft-strd-even.c: Skip if -mfloat-abi is
+       overriden.
+       2018-06-29  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/arm/arm-soft-strd-even.c: New test.
+
 2018-09-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/87467
diff --git a/gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c b/gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c
new file mode 100644 (file)
index 0000000..4ef3dd8
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=soft" } } */
+/* { dg-options "-O2 -marm -mfloat-abi=soft" } */
+
+/* Check that we don't try to emit STRD in ARM state with
+   odd starting register.  */
+
+struct S {
+  double M0;
+} __attribute((aligned)) __attribute((packed));
+
+void bar(void *);
+
+void foo(int x, struct S y) {
+  asm("" : : : "r1", "r8", "r7", "r4");
+  y.M0 ?: bar(0);
+  bar(__builtin_alloca(8));
+}