aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYvan Roux <yvan.roux@linaro.org>2015-12-28 09:39:34 +0100
committerLinaro Code Review <review@review.linaro.org>2015-12-30 12:00:16 +0000
commitad214f6348e7fcb93b16501c84c786ad2771c659 (patch)
treec2d580ca2385b807e707bb7d225ed7ff6a5ca37a
parent8f98b7a3eb0f16fb59e9c4c7906c797e80560cee (diff)
gcc/
Backport from trunk r230663. 2015-11-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 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. Change-Id: I6c5ceb9997598bf349d45b494ee17e2426e261d0
-rw-r--r--gcc/config/arm/arm.c28
-rw-r--r--gcc/config/arm/arm.md53
2 files changed, 24 insertions, 57 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 79dee8ecd33..04bd1f5179d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -14872,21 +14872,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 84b04156cbe..4547188f7c5 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")