I noticed that, when a variable-sized object declared on the stack turns out to be of fixed size, the optimizer can replace the call to __builtin_alloca by the declaration of fixed-size local array. Now, even if the alignment of the object is explicitly preserved, the alignment of its type is not since the type of the local array is always unsigned char. On RISC targets (STRICT_ALIGNMENT / SLOW_UNALIGNED_ACCESS to be precise), this causes any read larger than unsigned char to go through the bitfield expansion circuitry, because expand_expr_real_1 has: /* If the field isn't aligned enough to fetch as a memref, fetch it as a bit field. */ || (mode1 != BLKmode && (((TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode) || (bitpos % GET_MODE_ALIGNMENT (mode) != 0) || (MEM_P (op0) && (MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1) || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0)))) && modifier != EXPAND_MEMORY && ((modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER) ? STRICT_ALIGNMENT : SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0)))) In other words, even if the alignment of the MEM is sufficient (and it is), the test on TYPE_ALIGN (TREE_TYPE (tem)) is true since TREE_TYPE (tem) is unsigned char. I think that the test on TYPE_ALIGN (TREE_TYPE (tem)) is superfluous when op0 is a MEM because the second part of the test is more precise and sufficient, so the attached patchlet uses a conditional expression to implement that. Bootstrapped/regtested on SPARC/Solaris, SPARC64/Linux, PowerPC64/Linux and Aarch64/Linux, applied on the mainline as obvious. 2017-06-29 Eric Botcazou * expr.c (expand_expr) : When testing for unaligned objects, take into account only the alignment of 'op0' and 'mode1' if 'op0' is a MEM. -- Eric Botcazou