https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86968
--- Comment #8 from Thomas Preud'homme <thopre01 at gcc dot gnu.org> ---
(In reply to Thomas Preud'homme from comment #7)
> (In reply to Thomas Preud'homme from comment #6)
> > Happens at expand time. Diving in.
>
> There's a giant if in expand_expr_real_1 with the following comment:
>
> /* In cases where an aligned union has an unaligned object
> as a field, we might be extracting a BLKmode value from
> an integer-mode (e.g., SImode) object. Handle this case
> by doing the extract into an object as wide as the field
> (which we know to be the width of a basic mode), then
> storing into memory, and changing the mode to BLKmode. */
>
> The "if" is entered in the big endian unaligned case but not in the other
> case. In the aligned case, it continues after the if until the call to
> flip_storage_order which will generate the bswap.
In the aligned case, the if is not taken because alignment of the memory Vs
access is sufficient. There is provision to call flip_storage_order but only if
the access is a RECORD and here the mode class is INT.
Therefore unaligned access are handled by extract_bit_field. This in turns call
extract_bit_field_1 and later extract_integral_bit_field where things are
different between little endian and big endian. For little endian, it goes in
the following if block:
/* If OP0 is a memory, try copying it to a register and seeing if a
cheap register alternative is available. */
if (MEM_P (op0) & !reverse)
For big endian it continues and calls extract_fixed_bit_field. I'm wondering if
an extra call to flip_storage_order when reverse is true would solve the issue.
Need to understand better whe is it safe to call flip_storage_order.