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