Hello Segher, Jeff,
- The machine is indeed such that for each operation there is only one
non-register operand possible.
- Take a first example, to describe the problem with the combine:
void set_to_one(int *a)
{
*a = 1 ;
}
In the machine, this becomes:
R30 = 1 // move immediate to register
[R20] = R30 // move to *a
return
Now, to get this, there is not one movsi - pattern, because if there is
only one,
combine will combine both moves into something like
[R20] = 1
and this does not exist, and combine crashes. So, there are 2 moves:
/movesi_internal_fromreg/ (moving from a register to memory or register)
/movesi_internal_toreg/ (moving from immediate, memory, register to
register).
This is all nice and fine, until the reload step. In case the number of
internal registers is
exceeded, stuff needs to go on the stack. Now, suppose I have the operation
R30 = 1
and the compiler wants to put R30 on the stack, it sees this is not
possible, and will make a
helper move :
R30 = 1 (old one)
R100 = R30
and then, it will try to put R100 on the stack. Now, to do the move,
R100 = R30, it calls the
/movsi/ pattern in the machine description. Only, it declares in the RTX
R100 as a register operand,
which it is not, or not entirely. It is a stack operand, but my
/define_expand movsi/ recognizes it as a register
operand, end emits /movesi_internal_toreg/, while it should emit
/movesi_internal_fromreg/, and the
whole system ends in an endless loop.
To solve this decently, I need to find in the /define_expand movsi/ if
R100 is a stack operand or not.
There is one way, that is to implement TARGET_SECONDARY_RELOAD, have
that parse all the arguments,
put it in an operand database, and have /define_expand movsi/
interrogate this database. Now, I will only
do that if there is no other option.
Best Regards,
Henri.