diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2014-01-16 17:35:50 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2014-01-16 17:35:50 +0000 |
commit | 030d03b8c6b3e009a457aa59367d436dba4b0e57 (patch) | |
tree | d09bf18dcf3f5b5eba3f728612dad79308011f3e | |
parent | e78f06a8c35fcdab58cef654a3a2bc37a5d3c790 (diff) | |
download | gcc-030d03b8c6b3e009a457aa59367d436dba4b0e57.zip gcc-030d03b8c6b3e009a457aa59367d436dba4b0e57.tar.gz gcc-030d03b8c6b3e009a457aa59367d436dba4b0e57.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 126 |
2 files changed, 66 insertions, 67 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f17de0..7f6eb7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +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> PR target/59844 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 09966a3..96a6d23 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -680,90 +680,82 @@ aarch64_emit_move (rtx dest, rtx 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 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 dst_mode = GET_MODE (dst); - int src_regno = REGNO (src); - int dst_regno = REGNO (dst); + enum machine_mode mode = GET_MODE (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)) { - 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)) { - switch (src_mode) { - case TImode: - emit_insn - (gen_aarch64_movtilow_di (dst, gen_lowpart (word_mode, src))); - emit_insn - (gen_aarch64_movtihigh_di (dst, gen_highpart (word_mode, src))); - return; - 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 (); - } + src_lo = gen_lowpart (word_mode, src); + src_hi = gen_highpart (word_mode, src); + + if (mode == TImode) + { + emit_insn (gen_aarch64_movtilow_di (dst, src_lo)); + emit_insn (gen_aarch64_movtihigh_di (dst, src_hi)); + } + 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)) { - switch (src_mode) { - case TImode: - emit_insn - (gen_aarch64_movdi_tilow (gen_lowpart (word_mode, dst), src)); - emit_insn - (gen_aarch64_movdi_tihigh (gen_highpart (word_mode, dst), src)); - return; - 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 (); - } + dst_lo = gen_lowpart (word_mode, dst); + dst_hi = gen_highpart (word_mode, dst); + + if (mode == TImode) + { + emit_insn (gen_aarch64_movdi_tilow (dst_lo, src)); + emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src)); + } + else + { + emit_insn (gen_aarch64_movdi_tflow (dst_lo, src)); + emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src)); + } + return; } - /* Fall through to r -> r cases. */ } - switch (dst_mode) { - case TImode: - 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), - gen_highpart_mode (word_mode, TImode, src)); - aarch64_emit_move (low_dst, gen_lowpart (word_mode, src)); - } - else - { - aarch64_emit_move (low_dst, gen_lowpart (word_mode, src)); - aarch64_emit_move (gen_highpart (word_mode, dst), - 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 (); - } + 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); + + /* At most one pairing may overlap. */ + if (reg_overlap_mentioned_p (dst_lo, src_hi)) + { + aarch64_emit_move (dst_hi, src_hi); + aarch64_emit_move (dst_lo, src_lo); + } + else + { + aarch64_emit_move (dst_lo, src_lo); + aarch64_emit_move (dst_hi, src_hi); + } } bool |