This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 2/2][ARM] fix movdi expander to avoid illegal ldrd/strd
- From: Richard Earnshaw <Richard dot Earnshaw at foss dot arm dot com>
- To: Alan Lawrence <alan dot lawrence at arm dot com>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 03 Jul 2015 17:16:44 +0100
- Subject: Re: [PATCH 2/2][ARM] fix movdi expander to avoid illegal ldrd/strd
- Authentication-results: sourceware.org; auth=none
- References: <5596A9C7 dot 3040109 at arm dot com>
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.
R.
> arm_overalign_2.patch
>
>
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 164ac13a26289bf755c89e78a8a5f751883c6039..c6718282d2555f8cf9a4e9111b1393e1f7704983 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -5415,6 +5415,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 LDRD's into 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;
> + }
> "
> )
>
>