Commit 030d03b8 by Richard Earnshaw Committed by Richard Earnshaw

re PR target/59780 (ICE in aarch64_split_128bit_move)

	PR target/59780
	* aarch64.c (aarch64_split_128bit_move): Don't lookup REGNO on
	non-register objects.  Use gen_(high/low)part more consistently.
	Fix assertions.

From-SVN: r206671
parent e78f06a8
2014-01-16 Richard Earnshaw <rearnsha@arm.com>
PR target/59780
* aarch64.c (aarch64_split_128bit_move): Don't lookup REGNO on
non-register objects. Use gen_(high/low)part more consistently.
Fix assertions.
2014-01-16 Michael Meissner <meissner@linux.vnet.ibm.com> 2014-01-16 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/59844 PR target/59844
......
...@@ -680,89 +680,81 @@ aarch64_emit_move (rtx dest, rtx src) ...@@ -680,89 +680,81 @@ aarch64_emit_move (rtx dest, rtx src)
: emit_move_insn_1 (dest, src)); : emit_move_insn_1 (dest, src));
} }
/* Split a 128-bit move operation into two 64-bit move operations,
taking care to handle partial overlap of register to register
copies. Special cases are needed when moving between GP regs and
FP regs. SRC can be a register, constant or memory; DST a register
or memory. If either operand is memory it must not have any side
effects. */
void void
aarch64_split_128bit_move (rtx dst, rtx src) aarch64_split_128bit_move (rtx dst, rtx src)
{ {
rtx low_dst; rtx dst_lo, dst_hi;
rtx src_lo, src_hi;
enum machine_mode src_mode = GET_MODE (src); enum machine_mode mode = GET_MODE (dst);
enum machine_mode dst_mode = GET_MODE (dst);
int src_regno = REGNO (src);
int dst_regno = REGNO (dst);
gcc_assert (dst_mode == TImode || dst_mode == TFmode); gcc_assert (mode == TImode || mode == TFmode);
gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
if (REG_P (dst) && REG_P (src)) if (REG_P (dst) && REG_P (src))
{ {
gcc_assert (src_mode == TImode || src_mode == TFmode); int src_regno = REGNO (src);
int dst_regno = REGNO (dst);
/* Handle r -> w, w -> r. */ /* Handle FP <-> GP regs. */
if (FP_REGNUM_P (dst_regno) && GP_REGNUM_P (src_regno)) if (FP_REGNUM_P (dst_regno) && GP_REGNUM_P (src_regno))
{ {
switch (src_mode) { src_lo = gen_lowpart (word_mode, src);
case TImode: src_hi = gen_highpart (word_mode, src);
emit_insn
(gen_aarch64_movtilow_di (dst, gen_lowpart (word_mode, src))); if (mode == TImode)
emit_insn {
(gen_aarch64_movtihigh_di (dst, gen_highpart (word_mode, src))); emit_insn (gen_aarch64_movtilow_di (dst, src_lo));
return; emit_insn (gen_aarch64_movtihigh_di (dst, src_hi));
case TFmode:
emit_insn
(gen_aarch64_movtflow_di (dst, gen_lowpart (word_mode, src)));
emit_insn
(gen_aarch64_movtfhigh_di (dst, gen_highpart (word_mode, src)));
return;
default:
gcc_unreachable ();
} }
else
{
emit_insn (gen_aarch64_movtflow_di (dst, src_lo));
emit_insn (gen_aarch64_movtfhigh_di (dst, src_hi));
}
return;
} }
else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno)) else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno))
{ {
switch (src_mode) { dst_lo = gen_lowpart (word_mode, dst);
case TImode: dst_hi = gen_highpart (word_mode, dst);
emit_insn
(gen_aarch64_movdi_tilow (gen_lowpart (word_mode, dst), src)); if (mode == TImode)
emit_insn {
(gen_aarch64_movdi_tihigh (gen_highpart (word_mode, dst), src)); emit_insn (gen_aarch64_movdi_tilow (dst_lo, src));
return; emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src));
case TFmode:
emit_insn
(gen_aarch64_movdi_tflow (gen_lowpart (word_mode, dst), src));
emit_insn
(gen_aarch64_movdi_tfhigh (gen_highpart (word_mode, dst), src));
return;
default:
gcc_unreachable ();
} }
else
{
emit_insn (gen_aarch64_movdi_tflow (dst_lo, src));
emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src));
} }
/* Fall through to r -> r cases. */ return;
} }
}
dst_lo = gen_lowpart (word_mode, dst);
dst_hi = gen_highpart (word_mode, dst);
src_lo = gen_lowpart (word_mode, src);
src_hi = gen_highpart_mode (word_mode, mode, src);
switch (dst_mode) { /* At most one pairing may overlap. */
case TImode: if (reg_overlap_mentioned_p (dst_lo, src_hi))
low_dst = gen_lowpart (word_mode, dst);
if (REG_P (low_dst)
&& reg_overlap_mentioned_p (low_dst, src))
{ {
aarch64_emit_move (gen_highpart (word_mode, dst), aarch64_emit_move (dst_hi, src_hi);
gen_highpart_mode (word_mode, TImode, src)); aarch64_emit_move (dst_lo, src_lo);
aarch64_emit_move (low_dst, gen_lowpart (word_mode, src));
} }
else else
{ {
aarch64_emit_move (low_dst, gen_lowpart (word_mode, src)); aarch64_emit_move (dst_lo, src_lo);
aarch64_emit_move (gen_highpart (word_mode, dst), aarch64_emit_move (dst_hi, src_hi);
gen_highpart_mode (word_mode, TImode, src));
}
return;
case TFmode:
emit_move_insn (gen_rtx_REG (DFmode, dst_regno),
gen_rtx_REG (DFmode, src_regno));
emit_move_insn (gen_rtx_REG (DFmode, dst_regno + 1),
gen_rtx_REG (DFmode, src_regno + 1));
return;
default:
gcc_unreachable ();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment