when expanding code for 
struct a {short a,b,c,d;} *a;

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)

Reply via email to