aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlan Lawrence <alan.lawrence@arm.com>2015-07-06 16:21:55 +0000
committerAlan Lawrence <alalaw01@gcc.gnu.org>2015-07-06 16:21:55 +0000
commit9c769a65e92b891c96d6f9088b55a450164964c3 (patch)
treee89a49b58b3d30c98f501e1a6fc0fddf8c985b0d /gcc
parent385e3f0c2b92341efb1654e14968a9996f4e9720 (diff)
downloadgcc-9c769a65e92b891c96d6f9088b55a450164964c3.zip
gcc-9c769a65e92b891c96d6f9088b55a450164964c3.tar.gz
gcc-9c769a65e92b891c96d6f9088b55a450164964c3.tar.bz2
[ARM] fix movdi expander to avoid illegal ldrd/strd
* config/arm/arm.md (movdi): Avoid odd-number ldrd/strd in ARM state. From-SVN: r225461
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/arm/arm.md36
2 files changed, 40 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d3929fa..8275549 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2015-07-06 Alan Lawrence <alan.lawrence@arm.com>
+
+ * config/arm/arm.md (movdi): Avoid odd-number ldrd/strd in ARM state.
+
2015-07-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/66772
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 1ac8af0..be51c77 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -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;
+ }
"
)