Nicholas Clark wrote:
But I was envisaging for ARM that r12 or r14 ought to be the scratch register. The way the ABI works, with r12 trashed on function call entry, but r0 used to return values from functions means that r12 is available within an op, while mapping r0 to a parrot register for the first JITted op after an external call could save 1 register move.
Don't do that ;-)
1) jit/i386 already has JITted native vtable calls with return values. So mapping a register, which returns values from functions is not a good idea because:
2) Next optimizations will avoid register load/store, when a register is preserved, register allocation will be more long ranged (i.e. past external calls too). For this, we need some notion for preserved registers, e.g. #define PRESERVED_REGS 3 (first 3 regs are callee saved).
The one reg/reg move is by far more inexpensive then a reload from memory.
Here is a snippet of my proposal I sent to Daniel:
<cite>
In the meanwhile, I'll have some ideas for jit.c, which I could start coding:
- move Parrot_jit_save/_load_registers to jit.c
- check usage of all registers -> reg_usage[4][NUM_REGISTERS] ...
- check usage in non JITted sections too
- optimize register allocation:
* when register usage of next section doesn't collide, keep usage
- optimize load and store
* store always before non jitted section (exceptions)
* load only differing registers
BTW, is it an improvement to allocate a register, when the use count==1?
Changes beyond this: allocate P (and S) registers too: the JITed vtable calls could benefit from this. If there are too many registers to allocate (damned i386) I would weight the allocation like e.g. 10:2:1 for I:P:S, so if a P parrot register is heavily used, it would get a processor register.
</cite>
First is done.
Second is in work currently.
Last is done (for RHS use_count == 1).
Nicholas Clark
leo