diff options
author | Alan Lawrence <alan.lawrence@arm.com> | 2015-07-06 16:21:55 +0000 |
---|---|---|
committer | Alan Lawrence <alalaw01@gcc.gnu.org> | 2015-07-06 16:21:55 +0000 |
commit | 9c769a65e92b891c96d6f9088b55a450164964c3 (patch) | |
tree | e89a49b58b3d30c98f501e1a6fc0fddf8c985b0d /gcc | |
parent | 385e3f0c2b92341efb1654e14968a9996f4e9720 (diff) | |
download | gcc-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/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 36 |
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; + } " ) |