Richard Earnshaw wrote:
On 03/07/15 16:27, Alan Lawrence wrote:
The previous patch caused a regression in
gcc.c-torture/execute/20040709-1.c at -O0 (only), and the new
align_rec2.c test fails, both outputting an illegal assembler
instruction (ldrd on an odd-numbered reg) from output_move_double in
arm.c. Most routes have checks against such an illegal instruction, but
expanding a function call can directly name such impossible register
(pairs), bypassing the normal checks.

gcc/ChangeLog:

    * config/arm/arm.md (movdi): Avoid odd-number ldrd/strd in ARM state.


OK.

Both patches, plus Jakub's test, pushed onto trunk (r221461/5/6), and gcc-5-branch (r225467/9/70), with an obvious comment fix to the movdi patch (LDRD's into, STRD's from), as below.

Cheers, Alan


Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md       (revision 225457)
+++ gcc/config/arm/arm.md       (working copy)
@@ -5481,6 +5481,42 @@
       if (!REG_P (operands[0]))
        operands[1] = force_reg (DImode, operands[1]);
     }
+  if (REG_P (operands[0]) && REGNO (operands[0]) < FIRST_VIRTUAL_REGISTER
+      && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
+    {
+      /* Avoid LDRD's into an odd-numbered register pair in ARM state
+        when expanding function calls.  */
+      gcc_assert (can_create_pseudo_p ());
+      if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
+       {
+         /* Perform load into legal reg pair first, then move.  */
+         rtx reg = gen_reg_rtx (DImode);
+         emit_insn (gen_movdi (reg, operands[1]));
+         operands[1] = reg;
+       }
+      emit_move_insn (gen_lowpart (SImode, operands[0]),
+                     gen_lowpart (SImode, operands[1]));
+      emit_move_insn (gen_highpart (SImode, operands[0]),
+                     gen_highpart (SImode, operands[1]));
+      DONE;
+    }
+  else if (REG_P (operands[1]) && REGNO (operands[1]) < FIRST_VIRTUAL_REGISTER
+          && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
+    {
+      /* Avoid STRD's from an odd-numbered register pair in ARM state
+        when expanding function prologue.  */
+      gcc_assert (can_create_pseudo_p ());
+      rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
+                      ? gen_reg_rtx (DImode)
+                      : operands[0];
+      emit_move_insn (gen_lowpart (SImode, split_dest),
+                     gen_lowpart (SImode, operands[1]));
+      emit_move_insn (gen_highpart (SImode, split_dest),
+                     gen_highpart (SImode, operands[1]));
+      if (split_dest != operands[0])
+       emit_insn (gen_movdi (operands[0], split_dest));
+      DONE;
+    }
   "
 )


Reply via email to