From 3a463fcb41ae9c8dd8b6fd985a84a99da2eee55f Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Mon, 2 Mar 2020 01:06:12 +0100 Subject: [PATCH] Load numbers directly instead of via stack Assembly output for programs that used number literals was getting hard to read because it indirected everything through the stack, directly loading numbers in programs instead makes things behave much better. This works via the same approach as the previous load forwarding. --- ivy-examples/lots-of-numbers.vy | 2 ++ src/trans/x64.rs | 33 +++++++++++++++------------------ 2 files changed, 17 insertions(+), 18 deletions(-) create mode 100644 ivy-examples/lots-of-numbers.vy diff --git a/ivy-examples/lots-of-numbers.vy b/ivy-examples/lots-of-numbers.vy new file mode 100644 index 0000000..36d83ed --- /dev/null +++ b/ivy-examples/lots-of-numbers.vy @@ -0,0 +1,2 @@ +(let ([f (lam (a b c d e) 0)]) + (f 1 2 3 4 5)) diff --git a/src/trans/x64.rs b/src/trans/x64.rs index 3a07c77..8dc2de7 100644 --- a/src/trans/x64.rs +++ b/src/trans/x64.rs @@ -207,16 +207,18 @@ fn compile_func(func: &Func) -> Definition { Var::Upvar(x) => upvar(x), Var::Ssa(s) => stack(&s), }; - let load = |s| match func.block[s] { - Code::Load(v) => address(v), - _ => stack(s), + let get = |r, s| match func.block[s] { + Code::Load(v) => Inst::Load(r, address(v)), + Code::Num(v) => Inst::Imm(r, (v << 1) | 1), + _ => Inst::Load(r, stack(s)), }; for ssa in &func.order { match &func.block[ssa] { - // We don't need to generate code for loads themselves, they're consulted by other accesses + // We don't need to generate code for loads or nums themselves, they're consulted by other accesses Code::Load(_) => (), + Code::Num(_) => (), Code::StoreGlobal(x, s) => { - body.push(Inst::Load(Reg::Rax, load(s))); + body.push(get(Reg::Rax, s)); body.push(Inst::Store(Addr::Rip(Label::Global(*x)), Reg::Rax)); } Code::MakeLam { @@ -230,7 +232,7 @@ fn compile_func(func: &Func) -> Definition { body.push(Inst::Call(extern_label!("ivy_make_lam"))); body.push(Inst::Store(stack(ssa), Reg::Rax)); for (i, s) in upvars.iter().enumerate() { - body.push(Inst::Load(Reg::Rdi, load(s))); + body.push(get(Reg::Rdi, s)); body.push(Inst::Store( Addr::Off(Reg::Rax, HEADER_SIZE + (*params as i32) * 8 + i as i32 * 8), Reg::Rdi, @@ -241,30 +243,25 @@ fn compile_func(func: &Func) -> Definition { } Code::App(terms) => { let mut terms = terms.iter(); - body.push(Inst::Load( - Reg::Rdi, - load(terms.next().expect("a function to apply")), - )); + body.push(get(Reg::Rdi, terms.next().expect("a function to apply"))); match terms.next() { - Some(s) => body.push(Inst::Load(Reg::Rsi, load(s))), + Some(s) => body.push(get(Reg::Rsi, s)), None => body.push(Inst::Imm(Reg::Rsi, 0)), } body.push(Inst::Call(extern_label!("ivy_app"))); while let Some(term) = terms.next() { body.push(Inst::Mov(Reg::Rdi, Reg::Rax)); - body.push(Inst::Load(Reg::Rsi, load(term))); + body.push(get(Reg::Rsi, term)); body.push(Inst::Call(extern_label!("ivy_app"))); } body.push(Inst::Store(stack(ssa), Reg::Rax)); } - Code::Num(n) => { - body.push(Inst::Imm(Reg::Rax, (n << 1) | 1i64)); - body.push(Inst::Store(stack(ssa), Reg::Rax)); - } } } - if let Code::Load(v) = func.block[&func.result] { - body.push(Inst::Load(Reg::Rax, address(v))); + match func.block[&func.result] { + Code::Load(v) => body.push(Inst::Load(Reg::Rax, address(v))), + Code::Num(n) => body.push(Inst::Imm(Reg::Rax, (n << 1) | 1i64)), + _ => (), } body.push(Inst::Add(Reg::Rsp, stack_slots as u32 * 8)); body.push(Inst::Pop(Reg::Rbx)); -- 2.43.2