On Mon, 12 Mar 2012, Martin Jambor wrote:
> when we expand a misaligned MEM_REF on the LHS, we must not call the
> code in expand_expr_real_1 if the subsequent patch is applied, because
> the code generates code extracting the contents of the memory to a
> register, which is of course bad if the intent is to write into that
Then expand_expr_real_1 should be called with EXPAND_WRITE modifier,
instead of any of the others. Then it will (or should) return an lvalue.
That might still be wrong for alignment reasons, but writing into the so
returned rtx will change the original object.
> Therefore expand_assignment should expand MEM_REFs itself,
> just as it do when it encounters naked misaligned ones.
I think this goes into the wrong direction. expand_assignment shouldn't
create an lvalue rtx for any REFs itself. It should call expand_expr with
EXPAND_WRITE, and that should do the right thing (i.e. what's now done
directly in expand_assignment).
I realize the docu of EXPAND_WRITE is lacking, but here's what I think it
should do (and what I think it actually also mostly does already): Given
EXPAND_WRITE expand_expr is required to be called on an (sub)object, i.e.
an lvalue, and it should return an RTX lvalue (a REG or MEM) that if
written into is changing the originally specified tree lvalue (i.e. not
some temporary storage).
That doesn't mean that the result of expand_expr(EXPAND_WRITE) is directly
usable in a simple RTL (set) pattern as LHS in all cases. For instance it
won't be directly usable when it's misalign. Dealing with this situation
is left to the caller, i.e. expand_assignment mostly.
> - When expanding the base, the two functions differ in the
> expand_modifier they pass down to expand_expr. expand_assignment
> uses EXPAND_NORMAL while expand_expr_real_1 passes EXPAND_SUM.
> According to the comment in expr.h the latter seemed more permissive
> and so I used that, even though I admit I do not really know what
> the implications of this modifier are. Is it OK to use EXPAND_SUM
> also on a LHS?
No, but it might not matter in the situations you are facing, haven't
checked. EXPAND_SUM can return a PLUS rtx, e.g.
(plus (p60) (const_int 4))
for an offsetted address. Naturally you can't assign into such a plus
rtx. But if you only expand the base with that modifier (which for
BLKmode bases actually means expanding to a MEM containing the address of
base) you should be fine with EXPAND_SUM, it won't be used I think.