On 9/15/06, Leopold Toetsch <[EMAIL PROTECTED]> wrote:
Am Donnerstag, 14. September 2006 02:54 schrieb Karl Forner: > Hello, > > So I propose a new implementation that solve the bugs, and that is linear > in space and time, and hopefully produce > an optimal list of moves. It is to be found in the second patch. Great. Applied as r14621. > We have two lists of registers, the src_regs[] and dest_regs[], that form a > graph: src_regs[i] ==> dest_regs[i] Please note: - There are 2 use cases for register_move a) optimized recursive tail calls b) simple function call argument passing compiled to native code in JIT core For a) {src,dest}_regs aren't register numbers, but just an index in the move list. While a function could have x 1000s of registers, a function call is limited to 255 arguments. This is currently the limit due to the usage of unsigned char (and there's no designer decision on that yet). Anyway, a function call: foo(P2000, P3000, I5) would create src_regs := (0, 1, 2)
So in that case ( a or b ?), the src_regs are always (0,1,2,..,n) ? If so I'm sure that we can use this property to optimize the code. For b) it's either the same or (likely) HW register numbers (whatever is
appropriate - it's not implemented yet) (see jit_set_args_pc()) > A same register may appear several times in the src regs, but only at most > one time > in the dest ones, because it makes no sense to assign two values to a same > register. While it doesn't make sense, we can't prevent users from coding such a function call.
The problem is that I have no clue of JIT, registers and so on. But could you give an example of code that would lead to that case ?
And worse: due to PMC registers any argument passing (with conversions) could have a side effect due to operator overloading or such. This means that we just have to avoid these optimizations which are using register_move() in that case. > To handle a cycle with exit, you do not need a temp register. Excellent. > For instance, after a move(i -> j), j is now the backup of i. This and the implementation assumes that now i and j have the same value. Again due to the nastiness of P registers and due to possible argument conversion, this isn't true in the general case. Again, while it doesn't make much sense, to create such recursive tailcalls with argument conversion to/from PMC registers, users might still code that. Again, we have to check if any argument conversions could take place and then turn off the optimization in case.
ok, so where would the check take place ? I can imagine an extra argument indicating whether or not doing this extra optimization, or two different functions/implementations, or more infomration about the registers allowing the function to decide by itself to do or not the optimization on a register-couple basis ....
OPEN PROBLEMS > --------------------- > It is stated in the documentation that the mov_alt function should be tried > before using a temp register The idea of mov_alt is coming from the JIT code. src HW registers have a backup value in either a parrot registers or some call stack. The mov_alt code would produce an instruction like: mov 8[%ebp], %edx > Suppose that you have a cycle 1 ==> 2 ==> 3 ==> 4 > If move_alt( 1 -> 2 ) fails, should we try move_alt( 2 -> 3) and move_alt( > 3-> 4) too ? It's not implemented yet, but I'd say, if mov_alt fails, a temp should be used always, and mov_alt shouldn't be tried again.
Ok, that's what the implementation does on a per cycle basis, meaning one move_alt try by (disconnected) cycle. It is likely true the other way
too: if mov_alt succeeds for one register, it would always succeed for other registers too.
ok, but I can't see how we could use this property. So is there anything more I could do on this subject ? Karl