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; > + } > " > ) > >