Untitled

posted in DruinkJournal
Published December 18, 2006
Advertisement
Whee. Optimising is fun.
Given my previous sample input of:
void Test() {   int test = 12 + 5 * 4 - 100 / 50;}

I now get (Comments mine):
func Test{   mov  r0, 100   div  r0, 50   push r0   mov  r0, 5      ;   mul  r0, 4      ;   mov  r1, r0     ; *Cough*   mov  r0, 12     ;   add  r0, r1     ;   pop  r1   sub  r0, r1   mov  test, r0}

Next stage


Next up is compile time evaluation of operators. I know that r0 contains 100 at the start there, so I can substitute r0 for 100 until it's written to. My ICodeNodeOpBinary class tells me that the div instruction writes to (and reads from) r0, so I stop substituting r0 there. My ICodeNodeOpBinary class is able to evaluate any opcode, if the two values are constant (Or it will shortly), so it evaluates it to mov r0, 2. r0 isn't read from between it's initialisation on the first opcode and it's termination on the second one, so that opcode can be dropped entirely. Going through all the code doing that should give me:
func Test{   mov  r0, 2   push r0   mov  r0, 32   pop  r1   sub  r0, r1   mov  test, r0}

The bit commented in the code above should optimise away nicely, since:
; Original:   mov  r0, 5   mul  r0, 4   mov  r1, r0   mov  r0, 12   add  r0, r1; After first substitution (mov r0, 5):   mov  r0, 20   mov  r1, r0   mov  r0, 12   add  r0, r1; After second substitution (mov  r0, 20):   mov  r1, 20   mov  r0, 12   add  r0, r1; After third substitution (mov  r1, 20):   mov  r0, 12   add  r0, 20; After fourth substitution (mov  r0, 12):   mov  r0, 32; mov  r0, 32 can then be substituted elsewhere

And that should all work our automatically, since I go through the I-code nodes in order.

Later on


Once the mov's and opcodes have been evaluated, I should be able to do away with mov-push pairs. E.g:
; Original:func Test{   mov  r0, 2   push r0   mov  r0, 32   pop  r1   sub  r0, r1   mov  test, r0}; Becomes:func Test{   push 2   mov  r0, 32   pop  r1   sub  r0, r1   mov  test, r0}
After that, I can change push/pop's into a mov (Perhaps I should do this earlier?). That'll give:
func Test{   mov  r1, 2   mov  r0, 32   sub  r0, r1   mov  test, r0}
Hmm. Yeah, I should do the push/pop reduction first. Then I won't need a second pass of evaluating mov's and operators.

Anyway, once this is all done, it should boil down to:
mov test 30
Then I need to test the living crap out of it [smile]



Todo list

  1. Source code annotation as comments

  2. Make the VM support stack offsets for variables. Maybe just a simple mov command that'll grab a stack index into a register, that should need the least modification. movstack or something I think.

  3. Proper control structures. There's no support for anything like if, while, for, return, whatever. They should be a piece of piss to implement though. And hopefully it won't need much optimising.

  4. Dead code removal. Control structures can be optimised away if the expression can be evaluated at compile time.


Anyway, back to work for now...
Previous Entry Untitled
Next Entry Untitled
0 likes 1 comments

Comments

jollyjeffers
Interesting stuff.

Jack
December 18, 2006 12:50 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement