From: Kyrylo Tkachov Date: Fri, 20 Nov 2015 15:15:31 +0000 (+0000) Subject: [ARM] PR 68149 Fix ICE in unaligned_loaddi split X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=88fdc9a66e4b14aef5aa4b873223e4d081a8824c;p=gcc.git [ARM] PR 68149 Fix ICE in unaligned_loaddi split PR target/68149 * config/arm/arm.md (unaligned_loaddi): Delete. (unaligned_storedi): Likewise. * config/arm/arm.c (gen_movmem_ldrd_strd): Don't generate unaligned DImode memory ops. Instead perform two back-to-back unaligned SImode ops. From-SVN: r230663 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 03e6993ac0b..235a3b0cdc9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-11-20 Kyrylo Tkachov + + PR target/68149 + * config/arm/arm.md (unaligned_loaddi): Delete. + (unaligned_storedi): Likewise. + * config/arm/arm.c (gen_movmem_ldrd_strd): Don't generate + unaligned DImode memory ops. Instead perform two back-to-back + unaligned SImode ops. + 2015-11-20 Nathan Sidwell James Norris diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 2075c41f522..805335ce354 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -14890,21 +14890,41 @@ gen_movmem_ldrd_strd (rtx *operands) if (!(dst_aligned || src_aligned)) return arm_gen_movmemqi (operands); - src = adjust_address (src, DImode, 0); - dst = adjust_address (dst, DImode, 0); + /* If the either src or dst is unaligned we'll be accessing it as pairs + of unaligned SImode accesses. Otherwise we can generate DImode + ldrd/strd instructions. */ + src = adjust_address (src, src_aligned ? DImode : SImode, 0); + dst = adjust_address (dst, dst_aligned ? DImode : SImode, 0); + while (len >= 8) { len -= 8; reg0 = gen_reg_rtx (DImode); + rtx low_reg = NULL_RTX; + rtx hi_reg = NULL_RTX; + + if (!src_aligned || !dst_aligned) + { + low_reg = gen_lowpart (SImode, reg0); + hi_reg = gen_highpart_mode (SImode, DImode, reg0); + } if (src_aligned) emit_move_insn (reg0, src); else - emit_insn (gen_unaligned_loaddi (reg0, src)); + { + emit_insn (gen_unaligned_loadsi (low_reg, src)); + src = next_consecutive_mem (src); + emit_insn (gen_unaligned_loadsi (hi_reg, src)); + } if (dst_aligned) emit_move_insn (dst, reg0); else - emit_insn (gen_unaligned_storedi (dst, reg0)); + { + emit_insn (gen_unaligned_storesi (dst, low_reg)); + dst = next_consecutive_mem (dst); + emit_insn (gen_unaligned_storesi (dst, hi_reg)); + } src = next_consecutive_mem (src); dst = next_consecutive_mem (dst); diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 73c308825c4..227a9bd3f3d 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4277,59 +4277,6 @@ (set_attr "predicable_short_it" "yes,no") (set_attr "type" "store1")]) -;; Unaligned double-word load and store. -;; Split after reload into two unaligned single-word accesses. -;; It prevents lower_subreg from splitting some other aligned -;; double-word accesses too early. Used for internal memcpy. - -(define_insn_and_split "unaligned_loaddi" - [(set (match_operand:DI 0 "s_register_operand" "=l,r") - (unspec:DI [(match_operand:DI 1 "memory_operand" "o,o")] - UNSPEC_UNALIGNED_LOAD))] - "unaligned_access && TARGET_32BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_LOAD)) - (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_LOAD))] - { - operands[2] = gen_highpart (SImode, operands[0]); - operands[0] = gen_lowpart (SImode, operands[0]); - operands[3] = gen_highpart (SImode, operands[1]); - operands[1] = gen_lowpart (SImode, operands[1]); - - /* If the first destination register overlaps with the base address, - swap the order in which the loads are emitted. */ - if (reg_overlap_mentioned_p (operands[0], operands[1])) - { - std::swap (operands[1], operands[3]); - std::swap (operands[0], operands[2]); - } - } - [(set_attr "arch" "t2,any") - (set_attr "length" "4,8") - (set_attr "predicable" "yes") - (set_attr "type" "load2")]) - -(define_insn_and_split "unaligned_storedi" - [(set (match_operand:DI 0 "memory_operand" "=o,o") - (unspec:DI [(match_operand:DI 1 "s_register_operand" "l,r")] - UNSPEC_UNALIGNED_STORE))] - "unaligned_access && TARGET_32BIT" - "#" - "&& reload_completed" - [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_UNALIGNED_STORE)) - (set (match_dup 2) (unspec:SI [(match_dup 3)] UNSPEC_UNALIGNED_STORE))] - { - operands[2] = gen_highpart (SImode, operands[0]); - operands[0] = gen_lowpart (SImode, operands[0]); - operands[3] = gen_highpart (SImode, operands[1]); - operands[1] = gen_lowpart (SImode, operands[1]); - } - [(set_attr "arch" "t2,any") - (set_attr "length" "4,8") - (set_attr "predicable" "yes") - (set_attr "type" "store2")]) - (define_insn "*extv_reg" [(set (match_operand:SI 0 "s_register_operand" "=r")