[Bug target/82445] ARM target generates unaligned STRD instruction
rguenth at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Oct 6 10:08:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82445
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2017-10-06
Ever confirmed|0 |1
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
To answer myself, yes, -fno-store-merging fixes it. RTL expansion is ok:
;; MEM[(void *)unknown_glyph.0_1 + 4B] = 1048584;
(insn 7 6 8 (set (reg:SI 112)
(const_int 1048584 [0x100008])) "strd.c":50 -1
(nil))
(insn 8 7 0 (set (mem:SI (plus:SI (reg/f:SI 110 [ unknown_glyph.0_1 ])
(const_int 4 [0x4])) [0 MEM[(void *)unknown_glyph.0_1 + 4B]+0
S4 A32])
(reg:SI 112)) "strd.c":50 -1
(nil))
;; MEM[(void *)unknown_glyph.0_1 + 8B] = 4294770688;
(insn 9 8 10 (set (reg:SI 113)
(const_int -196608 [0xfffffffffffd0000])) "strd.c":51 -1
(nil))
(insn 10 9 0 (set (mem:SI (plus:SI (reg/f:SI 110 [ unknown_glyph.0_1 ])
(const_int 8 [0x8])) [0 MEM[(void *)unknown_glyph.0_1 + 8B]+0
S4 A32])
(reg:SI 113)) "strd.c":51 -1
(nil))
;; MEM[(void *)unknown_glyph.0_1 + 12B] = 8;
(insn 11 10 12 (set (reg:SI 115)
(const_int 8 [0x8])) "strd.c":53 -1
(nil))
(insn 12 11 13 (set (reg:HI 114)
(subreg:HI (reg:SI 115) 0)) "strd.c":53 -1
(expr_list:REG_EQUAL (const_int 8 [0x8])
(nil)))
(insn 13 12 0 (set (mem:HI (plus:SI (reg/f:SI 110 [ unknown_glyph.0_1 ])
(const_int 12 [0xc])) [0 MEM[(void *)unknown_glyph.0_1 + 12B]+0
S2 A32])
(reg:HI 114)) "strd.c":53 -1
(nil))
The DI move is introduced by peephole2:
Splitting with gen_peephole2_12
which is ldrdstrd.md:
(define_peephole2 ; strd
[(set (match_operand:SI 2 "memory_operand" "")
(match_operand:SI 0 "arm_general_register_operand" ""))
(set (match_operand:SI 3 "memory_operand" "")
(match_operand:SI 1 "arm_general_register_operand" ""))]
"TARGET_LDRD"
[(const_int 0)]
{
if (!gen_operands_ldrd_strd (operands, false, false, false))
FAIL;
else if (TARGET_ARM)
{
/* In ARM state, the destination registers of LDRD/STRD must be
consecutive. We emit DImode access. */
operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
operands[2] = adjust_address (operands[2], DImode, 0);
/* Emit [(set (match_dup 2) (match_dup 0))] */
emit_insn (gen_rtx_SET (operands[2], operands[0]));
DONE;
}
else if (TARGET_THUMB2)
{
/* Emit the pattern:
[(parallel [(set (match_dup 2) (match_dup 0))
(set (match_dup 3) (match_dup 1))])] */
rtx t1 = gen_rtx_SET (operands[2], operands[0]);
rtx t2 = gen_rtx_SET (operands[3], operands[1]);
emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
DONE;
}
})
but this doesn't at all consider alignment of the MEMs it merges.
More information about the Gcc-bugs
mailing list