Hi!

As mentioned in the PR, armv7hl-linux-gnueabi doesn't currently bootstrap
with --enable-checking=release (and profiledbootstrap is broken too),
the problem is that e.g. tree-ssa-sccvn.c is miscompiled.

The problem is that the various ldrdstrd.md peephole2s generate for
non-thumb{1,2} DImode loads and stores, but just use whatever alias set
and MEM_EXPR and other MEM attributes the first of the two MEMs had.
That is wrong e.g. for alias oracle and during the tree-ssa-sccvn.c
compilation sched2 because of that reorders ldrd with another store that
must not be reordered.

One possibility is to force alias set of 0 and clear MEM_EXPR, but that
pessimizes code too much (there is a patch in the PR that I've
bootstrapped/regtested and we are using temporarily in Fedora).

The following patch instead creates new patterns that keep referencing the
two original MEMs, so no unification of alias sets or MEM_EXPRs is needed.

Bootstrapped/regtested on armv7hl-linux-gnueabi (c,c++ only), distro build
(all languages) still ongoing (25 hours and hasn't even finished bootstrap),
ok for trunk?

In the PR, Matthew Malcomson suggested some changes, I'm fine e.g. with
adding && arm_legitimate_address_p (DImode, XEXP (operands[?], 0), true)
to the conditions (or add some helper function that calls this and checks
other stuff), but I really don't have access to hw where I can reasonably
test this.  There is also a question whether ldm2_* or ldrd are preferrable,
etc.  If ldrd is faster, then e.g. ldrdstrd.md is missing a peephole2 that
would handle reg1 = const1; reg2 = const2; mem1 = reg1; mem2 = reg2;,
it only handles reg1 = const1; mem1 = reg1; reg2 = const2; mem2 = reg2;
but sched1 in many cases reorders that.
Or if somebody wants to take the patch over from here, fine with me too.

As I wrote in the PR, I see also some cleanup possibilities for GCC10 in the
ARM backend, something that has been done a few years ago in x86 and
recently e.g. also in rs6000, removals of "" constraints from match_operand,
use of REG_P/MEM_P etc. macros, formatting fixes.

2019-01-31  Jakub Jelinek  <ja...@redhat.com>

        PR bootstrap/88714
        * config/arm/arm.c (gen_operands_ldrd_strd): If successful, for
        TARGET_ARM adjust operands[3] to be always PLUS of operands[2]
        and 4.  Formatting fixes.
        * config/arm/ldrdstrd.md: Handle TARGET_ARM like TARGET_THUMB2
        in all peephole2s, use peephole2 patterns where possible instead
        of generating code by hand + DONE.  Formatting fixes.
        * config/arm/arm.md (*arm_ldrd, *arm_strd): New define_insns.
        (*thumb2_ldrd, *thumb2_ldrd_base, *thumb2_ldrd_base_neg, *thumb2_strd,
        *thumb2_strd_base, *thumb2_strd_base_neg): Formatting fixes.
        * config/arm/vfd.md (*ldrd_vfp, *strd_vfp): New define_insns.
        * config/arm/iwmmxt.md (*iwmmxt_arm_ldrd, *iwmmxt_arm_strd): Likewise.

        * gcc.c-torture/execute/pr88714.c: New test.

--- gcc/config/arm/arm.c.jj     2019-01-22 23:26:46.815210588 +0100
+++ gcc/config/arm/arm.c        2019-01-30 11:31:58.626214346 +0100
@@ -15748,7 +15748,7 @@ gen_operands_ldrd_strd (rtx *operands, b
   /* Make sure we generate legal instructions.  */
   if (operands_ok_ldrd_strd (operands[0], operands[1], base, offset,
                              false, load))
-    return true;
+    goto ok;
 
   /* In Thumb state, where registers are almost unconstrained, there
      is little hope to fix it.  */
@@ -15761,7 +15761,7 @@ gen_operands_ldrd_strd (rtx *operands, b
       std::swap (operands[0], operands[1]);
       if (operands_ok_ldrd_strd (operands[0], operands[1], base, offset,
                                  false, load))
-        return true;
+        goto ok;
     }
 
   if (const_store)
@@ -15785,10 +15785,10 @@ gen_operands_ldrd_strd (rtx *operands, b
            strd r0, [r2]
       */
       if (operands_ok_ldrd_strd (operands[1], operands[0], base, offset,
-                                  false, false))
+                                false, false))
         {
           std::swap (operands[0], operands[1]);
-          return true;
+          goto ok;
         }
 
       /* Try to find a free DI register.  */
@@ -15810,13 +15810,22 @@ gen_operands_ldrd_strd (rtx *operands, b
           gcc_assert (REGNO (operands[0]) % 2 == 0);
           gcc_assert (REGNO (operands[0]) + 1 == REGNO (operands[1]));
 
-          return (operands_ok_ldrd_strd (operands[0], operands[1],
-                                         base, offset,
-                                         false, load));
+          if (operands_ok_ldrd_strd (operands[0], operands[1],
+                                    base, offset, false, load))
+           goto ok;
         }
     }
 
   return false;
+
+ ok:
+  if (TARGET_ARM)
+    {
+      rtx a = gen_rtx_PLUS (SImode, copy_rtx (XEXP (operands[nops], 0)),
+                           GEN_INT (4));
+      operands[nops + 1] = replace_equiv_address_nv (operands[nops + 1], a);
+    }
+  return true;
 }
 
 
--- gcc/config/arm/ldrdstrd.md.jj       2019-01-18 00:33:18.292022358 +0100
+++ gcc/config/arm/ldrdstrd.md  2019-01-30 11:52:00.726149716 +0100
@@ -26,34 +26,15 @@
 
 (define_peephole2 ; ldrd
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-        (match_operand:SI 2 "memory_operand" ""))
+       (match_operand:SI 2 "memory_operand" ""))
    (set (match_operand:SI 1 "arm_general_register_operand" "")
-        (match_operand:SI 3 "memory_operand" ""))]
+       (match_operand:SI 3 "memory_operand" ""))]
   "TARGET_LDRD"
-  [(const_int 0)]
+  [(parallel [(set (match_dup 0) (match_dup 2))
+             (set (match_dup 1) (match_dup 3))])]
 {
   if (!gen_operands_ldrd_strd (operands, true, false, false))
     FAIL;
-  else if (TARGET_ARM)
-  {
-    /* In ARM state, the destination registers of LDRD/STRD must be
-       consecutive. We emit DImode access.  */
-    operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
-    operands[2] = adjust_address (operands[2], DImode, 0);
-    /* Emit [(set (match_dup 0) (match_dup 2))] */
-    emit_insn (gen_rtx_SET (operands[0], operands[2]));
-    DONE;
-  }
-  else if (TARGET_THUMB2)
-  {
-    /* Emit the pattern:
-       [(parallel [(set (match_dup 0) (match_dup 2))
-                   (set (match_dup 1) (match_dup 3))])] */
-    rtx t1 = gen_rtx_SET (operands[0], operands[2]);
-    rtx t2 = gen_rtx_SET (operands[1], operands[3]);
-    emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
-    DONE;
-  }
 })
 
 (define_peephole2 ; strd
@@ -62,117 +43,50 @@ (define_peephole2 ; strd
    (set (match_operand:SI 3 "memory_operand" "")
        (match_operand:SI 1 "arm_general_register_operand" ""))]
   "TARGET_LDRD"
-  [(const_int 0)]
+  [(parallel [(set (match_dup 2) (match_dup 0))
+             (set (match_dup 3) (match_dup 1))])]
 {
   if (!gen_operands_ldrd_strd (operands, false, false, false))
     FAIL;
-  else if (TARGET_ARM)
-  {
-    /* In ARM state, the destination registers of LDRD/STRD must be
-       consecutive. We emit DImode access.  */
-    operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
-    operands[2] = adjust_address (operands[2], DImode, 0);
-    /* Emit [(set (match_dup 2) (match_dup 0))]  */
-    emit_insn (gen_rtx_SET (operands[2], operands[0]));
-    DONE;
-  }
-  else if (TARGET_THUMB2)
-  {
-    /* Emit the pattern:
-       [(parallel [(set (match_dup 2) (match_dup 0))
-                   (set (match_dup 3) (match_dup 1))])]  */
-    rtx t1 = gen_rtx_SET (operands[2], operands[0]);
-    rtx t2 = gen_rtx_SET (operands[3], operands[1]);
-    emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
-    DONE;
-  }
 })
 
 ;; The following peepholes reorder registers to enable LDRD/STRD.
 (define_peephole2 ; strd of constants
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-        (match_operand:SI 4 "const_int_operand" ""))
+       (match_operand:SI 4 "const_int_operand" ""))
    (set (match_operand:SI 2 "memory_operand" "")
-        (match_dup 0))
+       (match_dup 0))
    (set (match_operand:SI 1 "arm_general_register_operand" "")
-        (match_operand:SI 5 "const_int_operand" ""))
+       (match_operand:SI 5 "const_int_operand" ""))
    (set (match_operand:SI 3 "memory_operand" "")
-        (match_dup 1))]
+       (match_dup 1))]
   "TARGET_LDRD"
-  [(const_int 0)]
+  [(set (match_dup 0) (match_dup 4))
+   (set (match_dup 1) (match_dup 5))
+   (parallel [(set (match_dup 2) (match_dup 0))
+             (set (match_dup 3) (match_dup 1))])]
 {
   if (!gen_operands_ldrd_strd (operands, false, true, false))
     FAIL;
-  else if (TARGET_ARM)
-  {
-   rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
-   operands[2] = adjust_address (operands[2], DImode, 0);
-   /* Emit the pattern:
-      [(set (match_dup 0) (match_dup 4))
-      (set (match_dup 1) (match_dup 5))
-      (set (match_dup 2) tmp)]  */
-   emit_insn (gen_rtx_SET (operands[0], operands[4]));
-   emit_insn (gen_rtx_SET (operands[1], operands[5]));
-   emit_insn (gen_rtx_SET (operands[2], tmp));
-   DONE;
-  }
-  else if (TARGET_THUMB2)
-  {
-    /* Emit the pattern:
-       [(set (match_dup 0) (match_dup 4))
-        (set (match_dup 1) (match_dup 5))
-        (parallel [(set (match_dup 2) (match_dup 0))
-                   (set (match_dup 3) (match_dup 1))])]  */
-    emit_insn (gen_rtx_SET (operands[0], operands[4]));
-    emit_insn (gen_rtx_SET (operands[1], operands[5]));
-    rtx t1 = gen_rtx_SET (operands[2], operands[0]);
-    rtx t2 = gen_rtx_SET (operands[3], operands[1]);
-    emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
-    DONE;
-  }
 })
 
 (define_peephole2 ; strd of constants
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-        (match_operand:SI 4 "const_int_operand" ""))
+       (match_operand:SI 4 "const_int_operand" ""))
    (set (match_operand:SI 1 "arm_general_register_operand" "")
-        (match_operand:SI 5 "const_int_operand" ""))
+       (match_operand:SI 5 "const_int_operand" ""))
    (set (match_operand:SI 2 "memory_operand" "")
-        (match_dup 0))
+       (match_dup 0))
    (set (match_operand:SI 3 "memory_operand" "")
-        (match_dup 1))]
+       (match_dup 1))]
   "TARGET_LDRD"
-  [(const_int 0)]
+  [(set (match_dup 0) (match_dup 4))
+   (set (match_dup 1) (match_dup 5))
+   (parallel [(set (match_dup 2) (match_dup 0))
+             (set (match_dup 3) (match_dup 1))])]
 {
   if (!gen_operands_ldrd_strd (operands, false, true, false))
      FAIL;
-  else if (TARGET_ARM)
-  {
-   rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
-   operands[2] = adjust_address (operands[2], DImode, 0);
-   /* Emit the pattern
-      [(set (match_dup 0) (match_dup 4))
-       (set (match_dup 1) (match_dup 5))
-       (set (match_dup 2) tmp)]  */
-   emit_insn (gen_rtx_SET (operands[0], operands[4]));
-   emit_insn (gen_rtx_SET (operands[1], operands[5]));
-   emit_insn (gen_rtx_SET (operands[2], tmp));
-   DONE;
-  }
-  else if (TARGET_THUMB2)
-  {
-    /*  Emit the pattern:
-        [(set (match_dup 0) (match_dup 4))
-         (set (match_dup 1) (match_dup 5))
-         (parallel [(set (match_dup 2) (match_dup 0))
-                    (set (match_dup 3) (match_dup 1))])]  */
-    emit_insn (gen_rtx_SET (operands[0], operands[4]));
-    emit_insn (gen_rtx_SET (operands[1], operands[5]));
-    rtx t1 = gen_rtx_SET (operands[2], operands[0]);
-    rtx t2 = gen_rtx_SET (operands[3], operands[1]);
-    emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
-    DONE;
-  }
 })
 
 ;; The following two peephole optimizations are only relevant for ARM
@@ -181,67 +95,60 @@ (define_peephole2 ; strd of constants
 (define_peephole2 ; swap the destination registers of two loads
                  ; before a commutative operation.
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-        (match_operand:SI 2 "memory_operand" ""))
+       (match_operand:SI 2 "memory_operand" ""))
    (set (match_operand:SI 1 "arm_general_register_operand" "")
-        (match_operand:SI 3 "memory_operand" ""))
+       (match_operand:SI 3 "memory_operand" ""))
    (set (match_operand:SI 4 "arm_general_register_operand" "")
-        (match_operator:SI 5 "commutative_binary_operator"
-                          [(match_operand 6 "arm_general_register_operand" "")
-                           (match_operand 7 "arm_general_register_operand" "") 
]))]
+       (match_operator:SI 5 "commutative_binary_operator"
+         [(match_operand 6 "arm_general_register_operand" "")
+          (match_operand 7 "arm_general_register_operand" "")]))]
   "TARGET_LDRD && TARGET_ARM
-   && (  ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], 
operands[7])))
-        ||((rtx_equal_p(operands[0], operands[7])) && 
(rtx_equal_p(operands[1], operands[6]))))
-   && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], 
operands[4]))
-   && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], 
operands[4]))"
-  [(set (match_dup 0) (match_dup 2))
+   && ((rtx_equal_p (operands[0], operands[6])
+       && rtx_equal_p (operands[1], operands[7]))
+       || (rtx_equal_p (operands[0], operands[7])
+          && rtx_equal_p (operands[1], operands[6])))
+   && (peep2_reg_dead_p (3, operands[0])
+       || rtx_equal_p (operands[0], operands[4]))
+   && (peep2_reg_dead_p (3, operands[1])
+       || rtx_equal_p (operands[1], operands[4]))"
+  [(parallel [(set (match_dup 0) (match_dup 2))
+             (set (match_dup 1) (match_dup 3))])
    (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
-  {
-    if (!gen_operands_ldrd_strd (operands, true, false, true))
-     {
-        FAIL;
-     }
-    else
-     {
-        operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
-        operands[2] = adjust_address (operands[2], DImode, 0);
-     }
-   }
-)
+{
+  if (!gen_operands_ldrd_strd (operands, true, false, true))
+    FAIL;
+})
 
 (define_peephole2 ; swap the destination registers of two loads
                  ; before a commutative operation that sets the flags.
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-        (match_operand:SI 2 "memory_operand" ""))
+       (match_operand:SI 2 "memory_operand" ""))
    (set (match_operand:SI 1 "arm_general_register_operand" "")
-        (match_operand:SI 3 "memory_operand" ""))
+       (match_operand:SI 3 "memory_operand" ""))
    (parallel
       [(set (match_operand:SI 4 "arm_general_register_operand" "")
            (match_operator:SI 5 "commutative_binary_operator"
-                              [(match_operand 6 "arm_general_register_operand" 
"")
-                               (match_operand 7 "arm_general_register_operand" 
"") ]))
+             [(match_operand 6 "arm_general_register_operand" "")
+              (match_operand 7 "arm_general_register_operand" "")]))
        (clobber (reg:CC CC_REGNUM))])]
   "TARGET_LDRD && TARGET_ARM
-   && (  ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], 
operands[7])))
-       ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], 
operands[6]))))
-   && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], 
operands[4]))
-   && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], 
operands[4]))"
+   && ((rtx_equal_p (operands[0], operands[6])
+       && rtx_equal_p (operands[1], operands[7]))
+       || (rtx_equal_p (operands[0], operands[7])
+          && rtx_equal_p (operands[1], operands[6])))
+   && (peep2_reg_dead_p (3, operands[0])
+       || rtx_equal_p (operands[0], operands[4]))
+   && (peep2_reg_dead_p (3, operands[1])
+       || rtx_equal_p (operands[1], operands[4]))"
   [(set (match_dup 0) (match_dup 2))
    (parallel
       [(set (match_dup 4)
            (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
        (clobber (reg:CC CC_REGNUM))])]
-  {
-    if (!gen_operands_ldrd_strd (operands, true, false, true))
-     {
-        FAIL;
-     }
-    else
-     {
-        operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
-        operands[2] = adjust_address (operands[2], DImode, 0);
-     }
-   }
-)
+{
+  if (!gen_operands_ldrd_strd (operands, true, false, true))
+    FAIL;
+})
 
 ;; TODO: Handle LDRD/STRD with writeback:
 ;; (a) memory operands can be POST_INC, POST_DEC, PRE_MODIFY, POST_MODIFY
--- gcc/config/arm/arm.md.jj    2019-01-10 11:43:20.102283812 +0100
+++ gcc/config/arm/arm.md       2019-01-30 11:56:52.749274712 +0100
@@ -5940,6 +5940,44 @@ (define_split
   "
 )
 
+(define_insn "*arm_ldrd"
+  [(set (match_operand:SI 0 "s_register_operand" "=q,q")
+       (match_operand:SI 1 "memory_operand" "m,m"))
+   (set (match_operand:SI 2 "s_register_operand" "=q,q")
+       (mem:SI (plus:SI (match_operand:SI 3 "address_operand" "p,p")
+                        (const_int 4))))]
+  "TARGET_ARM && !TARGET_HARD_FLOAT && !TARGET_IWMMXT && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[0]) + 1 == REGNO (operands[2])
+   && rtx_equal_p (XEXP (operands[1], 0), operands[3])"
+{
+  rtx op[2];
+  op[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+  op[1] = adjust_address (operands[1], DImode, 0);
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "load_8")])
+
+(define_insn "*arm_strd"
+  [(set (match_operand:SI 0 "memory_operand" "=m,m")
+       (match_operand:SI 1 "s_register_operand" "q,q"))
+   (set (mem:SI (plus:SI (match_operand:SI 2 "address_operand" "p,p")
+                        (const_int 4)))
+       (match_operand:SI 3 "s_register_operand" "q,q"))]
+  "TARGET_ARM && !TARGET_HARD_FLOAT && !TARGET_IWMMXT && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[1]) + 1 == REGNO (operands[3])
+   && rtx_equal_p (XEXP (operands[0], 0), operands[2])"
+{
+  rtx op[2];
+  op[0] = adjust_address (operands[0], DImode, 0);
+  op[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "store_8")])
+
 (define_expand "movsi"
   [(set (match_operand:SI 0 "general_operand" "")
         (match_operand:SI 1 "general_operand" ""))]
@@ -11931,10 +11969,10 @@ (define_insn "*thumb2_ldrd"
         (mem:SI (plus:SI (match_dup 1)
                          (match_operand:SI 4 "const_int_operand" ""))))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
-     && (operands_ok_ldrd_strd (operands[0], operands[3],
-                                  operands[1], INTVAL (operands[2]),
-                                  false, true))"
+   && INTVAL (operands[2]) + 4 == INTVAL (operands[4])
+   && operands_ok_ldrd_strd (operands[0], operands[3],
+                            operands[1], INTVAL (operands[2]),
+                            false, true)"
   "ldrd%?\t%0, %3, [%1, %2]"
   [(set_attr "type" "load_8")
    (set_attr "predicable" "yes")])
@@ -11946,8 +11984,8 @@ (define_insn "*thumb2_ldrd_base"
         (mem:SI (plus:SI (match_dup 1)
                          (const_int 4))))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && (operands_ok_ldrd_strd (operands[0], operands[2],
-                                  operands[1], 0, false, true))"
+   && operands_ok_ldrd_strd (operands[0], operands[2],
+                            operands[1], 0, false, true)"
   "ldrd%?\t%0, %2, [%1]"
   [(set_attr "type" "load_8")
    (set_attr "predicable" "yes")])
@@ -11959,8 +11997,8 @@ (define_insn "*thumb2_ldrd_base_neg"
    (set (match_operand:SI 2 "s_register_operand" "=r")
         (mem:SI (match_dup 1)))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && (operands_ok_ldrd_strd (operands[0], operands[2],
-                                  operands[1], -4, false, true))"
+   && operands_ok_ldrd_strd (operands[0], operands[2],
+                            operands[1], -4, false, true)"
   "ldrd%?\t%0, %2, [%1, #-4]"
   [(set_attr "type" "load_8")
    (set_attr "predicable" "yes")])
@@ -11973,10 +12011,10 @@ (define_insn "*thumb2_strd"
                          (match_operand:SI 3 "const_int_operand" "")))
         (match_operand:SI 4 "s_register_operand" "r"))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
-     && (operands_ok_ldrd_strd (operands[2], operands[4],
-                                  operands[0], INTVAL (operands[1]),
-                                  false, false))"
+   && INTVAL (operands[1]) + 4 == INTVAL (operands[3])
+   && operands_ok_ldrd_strd (operands[2], operands[4],
+                            operands[0], INTVAL (operands[1]),
+                            false, false)"
   "strd%?\t%2, %4, [%0, %1]"
   [(set_attr "type" "store_8")
    (set_attr "predicable" "yes")])
@@ -11988,8 +12026,8 @@ (define_insn "*thumb2_strd_base"
                          (const_int 4)))
         (match_operand:SI 2 "s_register_operand" "r"))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && (operands_ok_ldrd_strd (operands[1], operands[2],
-                                  operands[0], 0, false, false))"
+   && operands_ok_ldrd_strd (operands[1], operands[2],
+                            operands[0], 0, false, false)"
   "strd%?\t%1, %2, [%0]"
   [(set_attr "type" "store_8")
    (set_attr "predicable" "yes")])
@@ -12001,8 +12039,8 @@ (define_insn "*thumb2_strd_base_neg"
    (set (mem:SI (match_dup 0))
         (match_operand:SI 2 "s_register_operand" "r"))]
   "TARGET_LDRD && TARGET_THUMB2 && reload_completed
-     && (operands_ok_ldrd_strd (operands[1], operands[2],
-                                  operands[0], -4, false, false))"
+   && operands_ok_ldrd_strd (operands[1], operands[2],
+                            operands[0], -4, false, false)"
   "strd%?\t%1, %2, [%0, #-4]"
   [(set_attr "type" "store_8")
    (set_attr "predicable" "yes")])
--- gcc/config/arm/vfp.md.jj    2019-01-16 09:35:03.887334295 +0100
+++ gcc/config/arm/vfp.md       2019-01-30 11:57:58.450177904 +0100
@@ -365,6 +365,47 @@ (define_insn "*movdi_vfp"
    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
 )
 
+(define_insn "*ldrd_vfp"
+  [(set (match_operand:SI 0 "s_register_operand" "=q,q")
+       (match_operand:SI 1 "memory_operand" "m,m"))
+   (set (match_operand:SI 2 "s_register_operand" "=q,q")
+       (mem:SI (plus:SI (match_operand:SI 3 "address_operand" "p,p")
+                        (const_int 4))))]
+  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[0]) + 1 == REGNO (operands[2])
+   && rtx_equal_p (XEXP (operands[1], 0), operands[3])"
+{
+  rtx op[2];
+  op[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+  op[1] = adjust_address (operands[1], DImode, 0);
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "type" "load_8")
+   (set (attr "length") (symbol_ref "arm_count_output_move_double_insns 
(operands) * 4"))
+   (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
+   (set_attr "arch" "a,t2")])
+
+(define_insn "*strd_vfp"
+  [(set (match_operand:SI 0 "memory_operand" "=m,m")
+       (match_operand:SI 1 "s_register_operand" "q,q"))
+   (set (mem:SI (plus:SI (match_operand:SI 2 "address_operand" "p,p")
+                        (const_int 4)))
+       (match_operand:SI 3 "s_register_operand" "q,q"))]
+  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[1]) + 1 == REGNO (operands[3])
+   && rtx_equal_p (XEXP (operands[0], 0), operands[2])"
+{
+  rtx op[2];
+  op[0] = adjust_address (operands[0], DImode, 0);
+  op[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "type" "store_8")
+   (set (attr "length") (symbol_ref "arm_count_output_move_double_insns 
(operands) * 4"))
+   (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))])
+
 ;; HFmode moves
 
 (define_insn "*movhf_vfp_fp16"
--- gcc/config/arm/iwmmxt.md.jj 2019-01-01 12:37:26.903815045 +0100
+++ gcc/config/arm/iwmmxt.md    2019-01-30 11:57:31.846622019 +0100
@@ -161,6 +161,44 @@ (define_insn "*iwmmxt_arm_movdi"
    (set_attr "arm_neg_pool_range" "*,*,*,1008,*,*,*,*,*,*,*,*,*,1008,*")]
 )
 
+(define_insn "*iwmmxt_arm_ldrd"
+  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+       (match_operand:SI 1 "memory_operand" "m,m"))
+   (set (match_operand:SI 2 "s_register_operand" "=r,r")
+       (mem:SI (plus:SI (match_operand:SI 3 "address_operand" "p,p")
+                        (const_int 4))))]
+  "TARGET_REALLY_IWMMXT && TARGET_ARM && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[0]) + 1 == REGNO (operands[2])
+   && rtx_equal_p (XEXP (operands[1], 0), operands[3])"
+{
+  rtx op[2];
+  op[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+  op[1] = adjust_address (operands[1], DImode, 0);
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "load_8")])
+
+(define_insn "*iwmmxt_arm_strd"
+  [(set (match_operand:SI 0 "memory_operand" "=m,m")
+       (match_operand:SI 1 "s_register_operand" "r,r"))
+   (set (mem:SI (plus:SI (match_operand:SI 2 "address_operand" "p,p")
+                        (const_int 4)))
+       (match_operand:SI 3 "s_register_operand" "r,r"))]
+  "TARGET_REALLY_IWMMXT && TARGET_ARM && TARGET_LDRD
+   && reload_completed
+   && REGNO (operands[1]) + 1 == REGNO (operands[3])
+   && rtx_equal_p (XEXP (operands[0], 0), operands[2])"
+{
+  rtx op[2];
+  op[0] = adjust_address (operands[0], DImode, 0);
+  op[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+  return output_move_double (op, true, NULL);
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "store_8")])
+
 (define_insn "*iwmmxt_movsi_insn"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk, 
m,z,r,?z,?Uy,*t, r,*t,*t  ,*Uv")
        (match_operand:SI 1 "general_operand"      " rk,I,K,j,mi,rk,r,z,Uy,  z, 
r,*t,*t,*Uvi, *t"))]
--- gcc/testsuite/gcc.c-torture/execute/pr88714.c.jj    2019-01-30 
12:08:33.534524511 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr88714.c       2019-01-30 
12:08:33.534524511 +0100
@@ -0,0 +1,43 @@
+/* PR bootstrap/88714 */
+
+struct S { int a, b, c; int *d; };
+struct T { int *e, *f, *g; } *t = 0;
+int *o = 0;
+
+__attribute__((noipa))
+void bar (int *x, int y, int z, int w)
+{
+  if (w == -1)
+    {
+      if (x != 0 || y != 0 || z != 0)
+       __builtin_abort ();
+    }
+  else if (w != 0 || x != t->g || y != 0 || z != 12)
+    __builtin_abort ();
+}
+
+__attribute__((noipa)) void
+foo (struct S *x, struct S *y, int *z, int w)
+{
+  *o = w;
+  if (w)
+    bar (0, 0, 0, -1);
+  x->d = z;
+  if (y->d)
+    y->c = y->c + y->d[0];
+  bar (t->g, 0, y->c, 0);
+}
+
+int
+main ()
+{
+  int a[4] = { 8, 9, 10, 11 };
+  struct S s = { 1, 2, 3, &a[0] };
+  struct T u = { 0, 0, &a[3] };
+  o = &a[2];
+  t = &u;
+  foo (&s, &s, &a[1], 5);
+  if (s.c != 12 || s.d != &a[1])
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to