Hi, when expanding code for struct a {short a,b,c,d;} *a; a->c; we first produce correct BLKmode MEM rtx representing the whole structure *a, then we use adjust_address to turn it into HImode MEM and finally extract_bitfield is used to offset it by 32 bits to get correct value.
The catch is that adjust_address updates memory attributes, too, and it sets size to 2 and clears MEM_EXPR on this occasion. According to Richard this is only correct behaviour because the size must represent size of memory load (and thus has meaning only for BLKmodes). This patch simply drops the original cast, because as far as I can tell all the following paths that does handle MEM also will update the mode once the location was correclty offseted. (It is bit hard to follow all possible paths as it goes down to different ways of bitfield processing, but if some path is missing and not tested by x86_64 bootstrap, we should update it to change the mode later). This significantly improves alignment tracking. Bootstrapped/regstested x86_64-linux (including Ada), OK? expr.c (expand_assignment): Do not change memory mode. Index: expr.c =================================================================== --- expr.c (revision 240109) +++ expr.c (working copy) @@ -5010,18 +5010,6 @@ expand_assignment (tree to, tree from, b } to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); - - /* If the field has a mode, we want to access it in the - field's mode, not the computed mode. - If a MEM has VOIDmode (external with incomplete type), - use BLKmode for it instead. */ - if (MEM_P (to_rtx)) - { - if (mode1 != VOIDmode) - to_rtx = adjust_address (to_rtx, mode1, 0); - else if (GET_MODE (to_rtx) == VOIDmode) - to_rtx = adjust_address (to_rtx, BLKmode, 0); - } if (offset != 0) {