https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64516
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot
gnu.org
Target Milestone|--- |4.9.4
Summary|[4.x Regression] arm: wrong |[4.9/5/6/7 Regression] arm:
|unaligned load generated |wrong unaligned load
| |generated
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
get16_unaligned should work. Confirmed on trunk.
(insn 6 5 7 (set (reg:SI 114)
(zero_extend:SI (mem:HI (reg/v/f:SI 111 [ p ]) [1 MEM[(const struct TU2
*)p_2(D)]+0 S2 A16]))) t.c:7 -1
(nil))
This is because the MEM_REF has a wrong type/alignment on it. Ah, and it's
one folding I know is wrong for a long time ... :/
case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF)
{
tem = fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
REF_REVERSE_STORAGE_ORDER (tem) = REF_REVERSE_STORAGE_ORDER (op0);
return tem;
}
this drops alignment info.
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 237286)
+++ gcc/fold-const.c (working copy)
@@ -7964,6 +7974,8 @@ fold_unary_loc (location_t loc, enum tre
case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF)
{
+ if (TYPE_ALIGN (TREE_TYPE (op0)) != TYPE_ALIGN (type))
+ type = build_aligned_type (type, TYPE_ALIGN (TREE_TYPE (op0)));
tem = fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
REF_REVERSE_STORAGE_ORDER (tem) = REF_REVERSE_STORAGE_ORDER (op0);
then generates
get16_unaligned:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldrb r3, [r0] @ zero_extendqisi2
ldrb r0, [r0, #1] @ zero_extendqisi2
orr r0, r3, r0, lsl #8
mov pc, lr