From 9ba2de71815c0ea6cc940ecb50af7cc1a84579f7 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 30 Jan 2025 11:22:37 +0100 Subject: middle-end/118695 - missed misalign handling in MEM_REF expansion When MEM_REF expansion of a non-MEM falls back to a stack temporary we fail to handle the case where the offset adjusted reference to the temporary is not aligned according to the requirement of the mode. We have to go through bitfield extraction or movmisalign in this case. Fortunately there's a helper for this. This fixes an ICE observed on arm which has sanity checks in its move patterns for this. PR middle-end/118695 * expr.cc (expand_expr_real_1): When expanding a MEM_REF to a non-MEM by committing it to a stack temporary make sure to handle misaligned accesses correctly. * gcc.dg/pr118695.c: New testcase. --- gcc/expr.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'gcc/expr.cc') diff --git a/gcc/expr.cc b/gcc/expr.cc index 10467f8..f684e26 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -11796,6 +11796,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && known_eq (GET_MODE_BITSIZE (DECL_MODE (base)), type_size)) return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base), target, tmode, modifier); + unsigned align; if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0)) { temp = assign_stack_temp (DECL_MODE (base), @@ -11804,6 +11805,17 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, temp = adjust_address (temp, TYPE_MODE (type), offset); if (TYPE_MODE (type) == BLKmode) set_mem_size (temp, int_size_in_bytes (type)); + /* When the original ref was misaligned so will be the + access to the stack temporary. Not all targets handle + this correctly, some will ICE in sanity checking. + Handle this by doing bitfield extraction when necessary. */ + else if ((align = get_object_alignment (exp)) + < GET_MODE_ALIGNMENT (TYPE_MODE (type))) + temp + = expand_misaligned_mem_ref (temp, TYPE_MODE (type), + unsignedp, align, + modifier == EXPAND_STACK_PARM + ? NULL_RTX : target, NULL); return temp; } /* When the access is fully outside of the underlying object -- cgit v1.1