https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117424
--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> --- t.c:15:35: note: vect_compute_data_ref_alignment: t.c:15:35: note: force alignment of *_3 ... t.c:15:35: note: ==> examining statement: _4 = *_3; t.c:15:35: note: vect_model_load_cost: aligned. the vectorizer over-aligns 'b' in ensure_base_align but RTL expansion allocates the variable to (gdb) p $rsp + 0xc $1 = (void *) 0x7fffffffde0c besides that, tree_could_trap_p is overly optimistic: case MEM_REF: ... if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR) { ... tree size = DECL_SIZE_UNIT (base); if (size == NULL_TREE || !poly_int_tree_p (size) || maybe_le (wi::to_poly_offset (size), off)) return true; /* Now we are sure the first byte of the access is inside the object. */ return false; but taking into account alignment it could still conclude the access doesn't trap. tree_could_trap_p does not track the overall offset from all handled-components, so it can only be optimistic in case the MEM_REF would be fully within the decl. So there are two bugs here - RTL expansion not honoring stack var alignment and tree_could_trap_p being overly optimistic. RTL expansion drops user alignment on the floor by expanding the variable as a register and later we do 12147 /* Otherwise, if this is a constant or the object is not in memory 12148 and need be, put it there. */ 12149 else if (CONSTANT_P (op0) || (!MEM_P (op0) && must_force_mem)) 12150 { 12151 memloc = assign_temp (TREE_TYPE (tem), 1, 1); but that assigns a stack temp for 'int' without the required over-alignment of the MEM. This is because we go BIT_FIELD_REF expansion again which doesn't really honor an over-aligned access as we build it and later we restore the slots alignment based on the BIT_FIELD_REF type. IMO the error is again in the /* Handle expansion of non-aliased memory with non-BLKmode. That might end up in a register. */ if (mem_ref_refers_to_non_mem_p (exp)) { if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0)) { temp = assign_stack_temp (DECL_MODE (base), GET_MODE_SIZE (DECL_MODE (base))); store_expr (base, temp, 0, false, false); temp = adjust_address (temp, TYPE_MODE (type), offset); if (TYPE_MODE (type) == BLKmode) set_mem_size (temp, int_size_in_bytes (type)); return temp; } exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type), bitsize_int (offset * BITS_PER_UNIT)); REF_REVERSE_STORAGE_ORDER (exp) = reverse; return expand_expr (exp, target, tmode, modifier); path. The BIT_FIELD_REF path hopes to avoid allocating a temporary on the stack, but as seen this doesn't work with respect to alignment (neither would the mode based temporary allocation, but that could be fixed).