rune icon indicating copy to clipboard operation
rune copied to clipboard

Basic compiler optimizations

Open udoprog opened this issue 3 years ago • 1 comments

This lowers the complicated AST to an intermediate representation, on which more optimizations can be performed.

Constant folding

With the advent of the new IR, if fed through the IrCompiler it would be possible to mark expressions which are fully constant. If this is the case, they can be constant folded, so:

fn foo() {
    1 + 2
}

Which currently generates:

fn foo() (0x27dc4241305d08c5):
  0000 = push 1
  0001 = push 2
  0002 = op +
  0003 = return

Could instead generate:

fn foo() (0x27dc4241305d08c5):
  0000 = push 3
  0003 = return

Inlining

Trivial function calls can either be fully inlined, or at least they can be reduced to avoid copies. This currently generates more instructions than necessary:

fn foo(a, b) {
    a + b
}

Unit:

fn foo(a, b) (0x27dc4241305d08c5):
  0000 = copy 0 // var `a`
  0001 = copy 1 // var `b`
  0002 = op +
  0003 = clean 2
  0004 = return

But it should be possible to reduce it to:

fn foo(a, b) (0x27dc4241305d08c5):
  0002 = op +
  0004 = return

Because the incoming parameters (a and b) are already pushed on the stack in the correct order.

udoprog avatar Sep 05 '20 18:09 udoprog

This seems to be an exciting issue to try out 🏗️ I've actually noticed the second issue straight away when passing single arguments. For example:

fn foo(a) {}
fn bar() {
    let a = 11;
    foo(a);
}

generates a push + copy 😕

Folding and inlining should be the most useful optimizations. Dead code elimination is another one. Loop unrolling might be very effective for short loops. Other popular optimizations could be questionable on how they would behave on a VM. I'll try some of them out 😅

dranikpg avatar Feb 04 '22 13:02 dranikpg