From e526295741f36c1a7bfb20856f2ff972b449b13b Mon Sep 17 00:00:00 2001 From: XLor Date: Tue, 5 Nov 2024 21:33:31 +0800 Subject: [PATCH 1/9] chore: init inline opt --- src/bin/optimizing.mbt | 1 + src/optimizing/inline/definition.mbt | 5 +++++ src/optimizing/inline/inline.mbt | 3 +++ src/optimizing/inline/moon.pkg.json | 13 +++++++++++++ src/optimizing/moon.pkg.json | 1 + src/optimizing/pass.mbt | 2 ++ 6 files changed, 25 insertions(+) create mode 100644 src/optimizing/inline/definition.mbt create mode 100644 src/optimizing/inline/inline.mbt create mode 100644 src/optimizing/inline/moon.pkg.json diff --git a/src/bin/optimizing.mbt b/src/bin/optimizing.mbt index 174e631a..e57a26cf 100644 --- a/src/bin/optimizing.mbt +++ b/src/bin/optimizing.mbt @@ -13,6 +13,7 @@ let optimizing_manager : @optimizing.Manager = @optimizing.new().add_opt_passes( Pass::Knf(CopyPropagation), Pass::Knf(TailRecursion), Pass::Knf(MayTailRecursion), + Pass::Knf(MethodInline), Pass::Ssa(ConstProp), Pass::Ssa(DeadCodeElimination), Pass::Assembly(InstFold), diff --git a/src/optimizing/inline/definition.mbt b/src/optimizing/inline/definition.mbt new file mode 100644 index 00000000..e4b21aa5 --- /dev/null +++ b/src/optimizing/inline/definition.mbt @@ -0,0 +1,5 @@ +typealias Name = @types.Name + +typealias Syntax = @types.Syntax + +typealias Knf = @knf.Knf diff --git a/src/optimizing/inline/inline.mbt b/src/optimizing/inline/inline.mbt new file mode 100644 index 00000000..04f23fb6 --- /dev/null +++ b/src/optimizing/inline/inline.mbt @@ -0,0 +1,3 @@ +pub fn transform_method_inline(knf : Knf) -> Knf { + knf +} diff --git a/src/optimizing/inline/moon.pkg.json b/src/optimizing/inline/moon.pkg.json new file mode 100644 index 00000000..c190d9be --- /dev/null +++ b/src/optimizing/inline/moon.pkg.json @@ -0,0 +1,13 @@ +{ + "import": [ + { + "path": "moonbitlang/minimbt", + "alias": "types" + }, + "moonbitlang/minimbt/knf", + "moonbitlang/minimbt/closure", + "moonbitlang/minimbt/ssa", + "moonbitlang/minimbt/util", + "moonbitlang/minimbt/shared" + ] +} \ No newline at end of file diff --git a/src/optimizing/moon.pkg.json b/src/optimizing/moon.pkg.json index ea7f0ca3..04940712 100644 --- a/src/optimizing/moon.pkg.json +++ b/src/optimizing/moon.pkg.json @@ -14,6 +14,7 @@ "moonbitlang/minimbt/optimizing/copy", "moonbitlang/minimbt/optimizing/liveness", "moonbitlang/minimbt/optimizing/tail", + "moonbitlang/minimbt/optimizing/inline", "moonbitlang/minimbt/optimizing/dead", "moonbitlang/minimbt/optimizing/inst" ] diff --git a/src/optimizing/pass.mbt b/src/optimizing/pass.mbt index 0e94f3a0..e14f075a 100644 --- a/src/optimizing/pass.mbt +++ b/src/optimizing/pass.mbt @@ -8,6 +8,7 @@ pub enum KnfOptPass { TailRecursion MayTailRecursion CopyPropagation + MethodInline } pub enum ClosureOptPass {} @@ -48,6 +49,7 @@ pub fn KnfOptPass::optimize(self : KnfOptPass, knf : @knf.Knf) -> @knf.Knf { TailRecursion => @tail.transform_tail_recursion(knf) MayTailRecursion => @tail.transform_may_tail_recursion(knf) CopyPropagation => @copy.transform_copy_propagation(knf) + MethodInline => @inline.transform_method_inline(knf) } } From 56d5b175f2cdf7c8925094ec804e599e87f3c0d8 Mon Sep 17 00:00:00 2001 From: XLor Date: Tue, 5 Nov 2024 22:56:05 +0800 Subject: [PATCH 2/9] feat(opt): method inline --- src/optimizing/copy/copy_propagation.mbt | 7 +- src/optimizing/inline/const.mbt | 7 + src/optimizing/inline/inline.mbt | 289 ++++++++++++++++++++++- 3 files changed, 299 insertions(+), 4 deletions(-) create mode 100644 src/optimizing/inline/const.mbt diff --git a/src/optimizing/copy/copy_propagation.mbt b/src/optimizing/copy/copy_propagation.mbt index 2739c327..c82553ea 100644 --- a/src/optimizing/copy/copy_propagation.mbt +++ b/src/optimizing/copy/copy_propagation.mbt @@ -67,9 +67,10 @@ fn Context::transform(self : Context, knf : Knf) -> Knf { } // Loop - Loop(label, args, body) => - Loop(label, self.replace_many_with_type(args), self.transform(body)) - Continue(label, args) => Continue(label, self.replace_many(args)) + Loop(_) => @util.die("unimplementd") + // Loop(label, self.replace_many_with_type(args), self.transform(body)) + Continue(_) => @util.die("unimplementd") + // Continue(label, self.replace_many(args)) // If IfEq(lhs, rhs, true_branch, false_branch, ty) => { diff --git a/src/optimizing/inline/const.mbt b/src/optimizing/inline/const.mbt new file mode 100644 index 00000000..22c9e9dd --- /dev/null +++ b/src/optimizing/inline/const.mbt @@ -0,0 +1,7 @@ +// size < 10, max copy 3 +let max_inline_size = 10 + +let max_inline_size_applied = 3 + +// referrenced at most once +let max_inline_applied = 1 diff --git a/src/optimizing/inline/inline.mbt b/src/optimizing/inline/inline.mbt index 04f23fb6..5c0ac9c5 100644 --- a/src/optimizing/inline/inline.mbt +++ b/src/optimizing/inline/inline.mbt @@ -1,3 +1,290 @@ pub fn transform_method_inline(knf : Knf) -> Knf { - knf + let context = { funcs: Map::new(), path: [], local: @immut/hashmap.new() } + context.collect_knf(knf) + context.transform(knf) +} + +struct InlineContext { + funcs : Map[Name, FuncDefInfo] + path : Array[@knf.FuncDef] + mut local : @immut/hashmap.T[Name, FuncDefInfo] +} + +fn InlineContext::fork( + self : InlineContext, + ~func : @knf.FuncDef? = None +) -> InlineContext { + let path = [..self.path] + match func { + Some(func) => path.push(func) + None => () + } + { funcs: self.funcs, path, local: self.local } +} + +fn InlineContext::add_local(self : InlineContext, name : Name) -> Unit { + match self.funcs.get(name) { + Some(info) => self.local = self.local.add(name, info) + None => @util.die("unreachable") + } +} + +struct FuncDefInfo { + def : @knf.FuncDef + mut applied : Int // Small function + mut size : Int // Small function + // mut applied : Int // count that it is applied + mut count : Int // count that it is referrenced +} + +fn FuncDefInfo::should_be_all_inlined(self : FuncDefInfo) -> Bool { + if self.count > 0 { + false + } else if self.applied <= max_inline_applied { + true + } else if self.size <= max_inline_size && + self.applied <= max_inline_size_applied { + true + } else { + false + } +} + +fn InlineContext::collect_knf(self : InlineContext, knf : Knf) -> Unit { + match knf { + Unit + | Int(_) + | Double(_) + | Neg(_) + | Add(_) + | Sub(_) | Mul(_) | Div(_) | FNeg(_) | FAdd(_) | FSub(_) | FMul(_) | FDiv(_) => + () + + // Loop + Loop(_, args, body) => { + args.each( + fn { + var => + match self.funcs.get(var.0) { + Some(def) => def.count += 1 + None => () + } + }, + ) + self.collect_knf(body) + } + Continue(_, args) => + args.each( + fn { + var => + match self.funcs.get(var) { + Some(def) => def.count += 1 + None => () + } + }, + ) + + // If + IfEq(_, _, true_branch, false_branch, _) + | IfLe(_, _, true_branch, false_branch, _) => { + self.collect_knf(true_branch) + self.collect_knf(false_branch) + } + + // Var + Var(var) => + match self.funcs.get(var) { + Some(def) => def.count += 1 + None => () + } + Tuple(els) => + els.each( + fn { + var => + match self.funcs.get(var) { + Some(def) => def.count += 1 + None => () + } + }, + ) + + // Array + Get(_) => () + Put(_, _, expr) => + match self.funcs.get(expr) { + Some(def) => def.count += 1 + None => () + } + + // Apply + Apply(callee, args) => { + match self.funcs.get(callee) { + Some(def) => def.applied += 1 + None => () + } + args.each( + fn { + var => + match self.funcs.get(var) { + Some(def) => def.count += 1 + None => () + } + }, + ) + } + ExternalFunctionApplication(_, args) => + args.each( + fn { + var => + match self.funcs.get(var) { + Some(def) => def.count += 1 + None => () + } + }, + ) + + // Let + Let(_, expr, rest) => { + self.collect_knf(expr) + self.collect_knf(rest) + } + LetTuple(_, _, rest) => self.collect_knf(rest) + LetRec(def, rest) => { + let info = { def, applied: 0, size: 0, count: 0 } + info.size = info.calc_size(def.body) + self.funcs.set(def.name, info) + self.collect_knf(def.body) + self.collect_knf(rest) + } + + // Unused + ExternalArray(_) => () + } +} + +fn FuncDefInfo::calc_size(self : FuncDefInfo, knf : Knf) -> Int { + match knf { + Unit | Int(_) | Double(_) => 1 + Neg(_) | FNeg(_) => 2 + Add(_) | Sub(_) | Mul(_) | Div(_) | FAdd(_) | FSub(_) | FMul(_) | FDiv(_) => + 3 + + // Loop + Loop(_, _, body) => self.calc_size(body) + Continue(_, args) => args.length() + 1 + + // If + IfEq(_, _, true_branch, false_branch, _) + | IfLe(_, _, true_branch, false_branch, _) => + 3 + self.calc_size(true_branch) + self.calc_size(false_branch) + + // Array + Get(_) => 3 + Put(_) => 4 + + // Var + Var(_) => 1 + Tuple(els) => 1 + els.length() + + // Apply + Apply(_, args) => 1 + 1 + args.length() + ExternalFunctionApplication(_, args) => 1 + args.length() + + // Let + Let(_, expr, rest) => 1 + self.calc_size(expr) + self.calc_size(rest) + LetTuple(els, _, rest) => els.length() + self.calc_size(rest) + LetRec(_, rest) => 1 + self.calc_size(rest) + + // Unused + ExternalArray(_) => @util.die("unreachable") + } +} + +fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { + match knf { + Unit + | Int(_) + | Double(_) + | Neg(_) + | Add(_) + | Sub(_) | Mul(_) | Div(_) | FNeg(_) | FAdd(_) | FSub(_) | FMul(_) | FDiv(_) => + knf + + // Loop + Loop(label, args, body) => Loop(label, args, self.fork().transform(body)) + Continue(_) => knf + + // If + IfEq(lhs, rhs, true_branch, false_branch, ty) => + IfEq( + lhs, + rhs, + self.fork().transform(true_branch), + self.fork().transform(false_branch), + ty, + ) + IfLe(lhs, rhs, true_branch, false_branch, ty) => + IfLe( + lhs, + rhs, + self.fork().transform(true_branch), + self.fork().transform(false_branch), + ty, + ) + + // Var + Var(_) | Tuple(_) => knf + + // Array + Get(_) | Put(_) => knf + + // Apply + Apply(callee, args) => + match self.local.find(callee) { + Some(info) => + if info.should_be_all_inlined() { + if args.length() != info.def.args.length() { + @util.die("Inline mismatch") + } + if self.path.search_by(fn { f => f.id == info.def.id }).is_empty() { + @shared.debug("Transform inline: \{knf}") + let body = info.def.body + let params = info.def.args + // Inline method + args.rev_foldi( + fn { + i, body, arg => + Let(params[args.length() - 1 - i], Var(arg), body) + }, + init=body, + ) + } else { + knf + } + } else { + knf + } + None => knf + } + ExternalFunctionApplication(_) => knf + + // Let + Let(binding, expr, rest) => + Let(binding, self.fork().transform(expr), self.transform(rest)) + LetTuple(binding, expr, rest) => + LetTuple(binding, expr, self.transform(rest)) + LetRec(def, rest) => + match self.funcs.get(def.name) { + Some(_) => { + self.add_local(def.name) + let body = self.fork(func=Some(def)).transform(def.body) + let def = { ..def, body, } + LetRec(def, self.transform(rest)) + } + None => @util.die("unreachable") + } + + // Unused + ExternalArray(_) => knf + } } From 34a7f6c226d80ea9ee78801f139c936acd096aa1 Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 23:23:02 +0800 Subject: [PATCH 3/9] fix(riscv): not inline muliple --- src/optimizing/inline/const.mbt | 2 +- src/optimizing/inline/copy.mbt | 14 ++++++++++++++ src/optimizing/inline/inline.mbt | 32 ++++++++++++-------------------- 3 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 src/optimizing/inline/copy.mbt diff --git a/src/optimizing/inline/const.mbt b/src/optimizing/inline/const.mbt index 22c9e9dd..fc608a2b 100644 --- a/src/optimizing/inline/const.mbt +++ b/src/optimizing/inline/const.mbt @@ -1,7 +1,7 @@ // size < 10, max copy 3 let max_inline_size = 10 -let max_inline_size_applied = 3 +let max_inline_size_applied = 1 // referrenced at most once let max_inline_applied = 1 diff --git a/src/optimizing/inline/copy.mbt b/src/optimizing/inline/copy.mbt new file mode 100644 index 00000000..3debc615 --- /dev/null +++ b/src/optimizing/inline/copy.mbt @@ -0,0 +1,14 @@ +fn copy_func_body(def : @knf.FuncDef, args : Array[Name]) -> Knf { + let body = def.body + let params = def.args + + // Inline method + args.rev_foldi( + fn { i, acc, arg => Let(params[args.length() - 1 - i], Var(arg), acc) }, + init=body, + ) +} + +// fn replace_stmt(map : Map[Name, Name], knf : Knf) -> Knf { +// knf +// } diff --git a/src/optimizing/inline/inline.mbt b/src/optimizing/inline/inline.mbt index 5c0ac9c5..8383fc6d 100644 --- a/src/optimizing/inline/inline.mbt +++ b/src/optimizing/inline/inline.mbt @@ -30,10 +30,9 @@ fn InlineContext::add_local(self : InlineContext, name : Name) -> Unit { } struct FuncDefInfo { - def : @knf.FuncDef - mut applied : Int // Small function + mut def : @knf.FuncDef mut size : Int // Small function - // mut applied : Int // count that it is applied + mut applied : Int // count this it is applied mut count : Int // count that it is referrenced } @@ -211,7 +210,7 @@ fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { knf // Loop - Loop(label, args, body) => Loop(label, args, self.fork().transform(body)) + Loop(label, args, body) => Loop(label, args, self.transform(body)) Continue(_) => knf // If @@ -219,16 +218,16 @@ fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { IfEq( lhs, rhs, - self.fork().transform(true_branch), - self.fork().transform(false_branch), + self.transform(true_branch), + self.transform(false_branch), ty, ) IfLe(lhs, rhs, true_branch, false_branch, ty) => IfLe( lhs, rhs, - self.fork().transform(true_branch), - self.fork().transform(false_branch), + self.transform(true_branch), + self.transform(false_branch), ty, ) @@ -248,16 +247,8 @@ fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { } if self.path.search_by(fn { f => f.id == info.def.id }).is_empty() { @shared.debug("Transform inline: \{knf}") - let body = info.def.body - let params = info.def.args - // Inline method - args.rev_foldi( - fn { - i, body, arg => - Let(params[args.length() - 1 - i], Var(arg), body) - }, - init=body, - ) + info.applied -= 1 + copy_func_body(info.def, args) } else { knf } @@ -270,15 +261,16 @@ fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { // Let Let(binding, expr, rest) => - Let(binding, self.fork().transform(expr), self.transform(rest)) + Let(binding, self.transform(expr), self.transform(rest)) LetTuple(binding, expr, rest) => LetTuple(binding, expr, self.transform(rest)) LetRec(def, rest) => match self.funcs.get(def.name) { - Some(_) => { + Some(info) => { self.add_local(def.name) let body = self.fork(func=Some(def)).transform(def.body) let def = { ..def, body, } + info.def = def LetRec(def, self.transform(rest)) } None => @util.die("unreachable") From d307cee8953c260f8f2bcb43e16b2df3d776de1d Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 23:33:10 +0800 Subject: [PATCH 4/9] feat(opt): clear dead method --- src/optimizing/inline/inline.mbt | 55 +++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/optimizing/inline/inline.mbt b/src/optimizing/inline/inline.mbt index 8383fc6d..ebd994ff 100644 --- a/src/optimizing/inline/inline.mbt +++ b/src/optimizing/inline/inline.mbt @@ -1,7 +1,8 @@ pub fn transform_method_inline(knf : Knf) -> Knf { let context = { funcs: Map::new(), path: [], local: @immut/hashmap.new() } context.collect_knf(knf) - context.transform(knf) + let knf = context.transform(knf) + context.cleanup(knf) } struct InlineContext { @@ -280,3 +281,55 @@ fn InlineContext::transform(self : InlineContext, knf : Knf) -> Knf { ExternalArray(_) => knf } } + +fn InlineContext::cleanup(self : InlineContext, knf : Knf) -> Knf { + match knf { + Unit + | Int(_) + | Double(_) + | Neg(_) + | Add(_) + | Sub(_) | Mul(_) | Div(_) | FNeg(_) | FAdd(_) | FSub(_) | FMul(_) | FDiv(_) => + knf + + // Loop + Loop(label, args, body) => Loop(label, args, self.cleanup(body)) + Continue(_) => knf + + // If + IfEq(lhs, rhs, true_branch, false_branch, ty) => + IfEq(lhs, rhs, self.cleanup(true_branch), self.cleanup(false_branch), ty) + IfLe(lhs, rhs, true_branch, false_branch, ty) => + IfLe(lhs, rhs, self.cleanup(true_branch), self.cleanup(false_branch), ty) + + // Var + Var(_) | Tuple(_) => knf + + // Array + Get(_) | Put(_) => knf + + // Apply + Apply(_) => knf + ExternalFunctionApplication(_) => knf + + // Let + Let(binding, expr, rest) => + Let(binding, self.cleanup(expr), self.cleanup(rest)) + LetTuple(binding, expr, rest) => LetTuple(binding, expr, self.cleanup(rest)) + LetRec(def, rest) => + match self.funcs.get(def.name) { + Some(info) => + if info.applied == 0 && info.count == 0 { + self.cleanup(rest) + } else { + let body = self.cleanup(def.body) + let def = { ..def, body, } + LetRec(def, self.cleanup(rest)) + } + None => @util.die("unreachable") + } + + // Unused + ExternalArray(_) => knf + } +} From 34fa229512cd935e1f5177c655b7effba98ad956 Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 23:37:21 +0800 Subject: [PATCH 5/9] fix(riscv): only riscv have inline --- src/bin/main.mbt | 18 +++++++++++++----- src/bin/optimizing.mbt | 32 +++++++++++++++++++------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/bin/main.mbt b/src/bin/main.mbt index 11711b33..bb20ad10 100644 --- a/src/bin/main.mbt +++ b/src/bin/main.mbt @@ -67,6 +67,7 @@ struct CompileStatus { mut asm : @riscv.AssemblyProgram? mut js : @js.JsResult? mut wasm : @wasm.WasmResult? + mut optimizing_manager : @optimizing.Manager? } fn CompileStatus::initialize( @@ -89,6 +90,7 @@ fn CompileStatus::initialize( asm: None, js: None, wasm: None, + optimizing_manager: None, } match start_stage { Parse => v.source_code = Some(file) @@ -120,7 +122,9 @@ fn CompileStatus::step(self : CompileStatus) -> Bool { } Typecheck => { let typechecked = @typing.type_check(self.ast.unwrap(), externals()) - let typechecked = optimizing_manager.optimize_ast(typechecked) + let typechecked = self.optimizing_manager + .unwrap() + .optimize_ast(typechecked) self.typechecked = Some(typechecked) } Knf => { @@ -133,7 +137,7 @@ fn CompileStatus::step(self : CompileStatus) -> Bool { } KnfOpt => { let knf = self.knf.unwrap() - let knf = optimizing_manager.optimize_knf(knf) + let knf = self.optimizing_manager.unwrap().optimize_knf(knf) self.opt_knf = Some(knf) } Closure => { @@ -149,7 +153,7 @@ fn CompileStatus::step(self : CompileStatus) -> Bool { let world = builder.build(self.closure_ir.unwrap()) self.ssa = Some(world) // Optimizing SSA - optimizing_manager.optimize_ssa_ir(world) + self.optimizing_manager.unwrap().optimize_ssa_ir(world) } Asm => { let world = self.ssa.unwrap() @@ -157,9 +161,9 @@ fn CompileStatus::step(self : CompileStatus) -> Bool { match self.backend { RSICV => { let machine_world = @riscv.build_machine_world(world) - optimizing_manager.optimize_machine_ir(machine_world) + self.optimizing_manager.unwrap().optimize_machine_ir(machine_world) let asm_program = @riscv.emit(machine_world) - optimizing_manager.optimize_assembly(asm_program) + self.optimizing_manager.unwrap().optimize_assembly(asm_program) self.asm = Some(asm_program) } JS => self.js = Some(@js.emit_js(world)) @@ -367,8 +371,12 @@ fn main { Ok(status) => { if js_backend.val { status.backend = JS + status.optimizing_manager = Some(get_optimizing_manager(JS)) } else if wasm_backend.val { status.backend = WASM + status.optimizing_manager = Some(get_optimizing_manager(WASM)) + } else { + status.optimizing_manager = Some(get_optimizing_manager(RSICV)) } status } diff --git a/src/bin/optimizing.mbt b/src/bin/optimizing.mbt index e57a26cf..33ac2f32 100644 --- a/src/bin/optimizing.mbt +++ b/src/bin/optimizing.mbt @@ -6,16 +6,22 @@ typealias Pass = @optimizing.Pass // typealias ClosureOptPass = @optimizing.ClosureOptPass -let optimizing_manager : @optimizing.Manager = @optimizing.new().add_opt_passes( - [ - // Pass::Ast(ConstFold), - // Pass::Ast(Liveness), - Pass::Knf(CopyPropagation), - Pass::Knf(TailRecursion), - Pass::Knf(MayTailRecursion), - Pass::Knf(MethodInline), - Pass::Ssa(ConstProp), - Pass::Ssa(DeadCodeElimination), - Pass::Assembly(InstFold), - ], -) +fn get_optimizing_manager(backend : Backends) -> @optimizing.Manager { + let optimizing_manager : @optimizing.Manager = @optimizing.new().add_opt_passes( + [ + // Pass::Ast(ConstFold), + // Pass::Ast(Liveness), + Pass::Knf(CopyPropagation), + Pass::Knf(TailRecursion), + Pass::Knf(MayTailRecursion), + Pass::Ssa(ConstProp), + Pass::Ssa(DeadCodeElimination), + Pass::Assembly(InstFold), + ], + ) + if backend == RSICV { + optimizing_manager.add_opt_pass(Pass::Knf(MethodInline)) + } else { + optimizing_manager + } +} From 0fcaf4ed4198e8d3426581e118aac9d7e634caf6 Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 23:48:48 +0800 Subject: [PATCH 6/9] chore: try --- src/optimizing/inline/const.mbt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/optimizing/inline/const.mbt b/src/optimizing/inline/const.mbt index fc608a2b..b4a361c3 100644 --- a/src/optimizing/inline/const.mbt +++ b/src/optimizing/inline/const.mbt @@ -1,7 +1,7 @@ -// size < 10, max copy 3 -let max_inline_size = 10 +// size < 200, max copy 1 +let max_inline_size = 200 let max_inline_size_applied = 1 // referrenced at most once -let max_inline_applied = 1 +let max_inline_applied = 0 From e437bf0a68dacaa38efc36e87329b01fc5903b3d Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 01:41:46 +0800 Subject: [PATCH 7/9] feat(closure): extract top level vars --- src/closure/closure_ir.mbt | 2 + src/closure/json.mbt | 7 ++- src/closure/knf_preprocess.mbt | 77 +++++++++++++++++------- src/closure/knf_to_closure.mbt | 3 + src/closure/world.mbt | 3 + src/closure_eval/interpreter.mbt | 53 ++++++++++------ src/optimizing/copy/copy_propagation.mbt | 3 +- src/ssa/world_builder.mbt | 9 ++- 8 files changed, 114 insertions(+), 43 deletions(-) diff --git a/src/closure/closure_ir.mbt b/src/closure/closure_ir.mbt index ed807f8a..85042a29 100644 --- a/src/closure/closure_ir.mbt +++ b/src/closure/closure_ir.mbt @@ -40,6 +40,7 @@ pub enum Expr { pub struct Closure { name : Label + top_level_vars : Array[(Name, LowType)] actual_free_vars : Array[Name] } derive(Show) @@ -54,6 +55,7 @@ pub struct FuncDef { /// true if the function is a closure function, and the closure will be available at `s11` on /// function entry. mut is_closure : Bool + mut top_level_vars : Array[(Name, LowType)] mut formal_free_vars : Array[(Name, LowType)] } derive(Show) diff --git a/src/closure/json.mbt b/src/closure/json.mbt index aa25d29a..c75aa232 100644 --- a/src/closure/json.mbt +++ b/src/closure/json.mbt @@ -197,7 +197,11 @@ pub fn Closure::from_json(json : Json) -> Closure! { for n in actual_free_vars { actual_free_vars_res.push(Name::from_json!(n)) } - { name: Label(name), actual_free_vars: actual_free_vars_res } + { + name: Label(name), + top_level_vars: [], + actual_free_vars: actual_free_vars_res, + } } _ => fail!("invalid json") } @@ -269,6 +273,7 @@ pub fn FuncDef::from_json(json : Json) -> FuncDef! { is_closure: @json.from_json!(b), ty: LowType::from_json!(t), args: args_res, + top_level_vars: [], formal_free_vars: formal_free_vars_res, body: Expr::from_json!(body), } diff --git a/src/closure/knf_preprocess.mbt b/src/closure/knf_preprocess.mbt index 3da6146b..8e04f26c 100644 --- a/src/closure/knf_preprocess.mbt +++ b/src/closure/knf_preprocess.mbt @@ -3,29 +3,35 @@ struct KnfEnv { world : KnfWorld scope_path : Array[MutFuncDef] - global : @immut/hashset.T[Name] local : @hashset.T[Name] + global : @immut/hashset.T[Name] mut free_vars : @immut/hashset.T[Name] + mut top_level : @immut/hashmap.T[Name, LowType] + mut top_level_free_vars : @immut/hashmap.T[Name, LowType] } fn KnfEnv::new(externals : Map[String, Type]) -> KnfEnv { let mut world_global = @immut/hashmap.new() let mut global = @immut/hashset.new() + let mut top_level = @immut/hashmap.new() externals.each( fn { name, typ => { let binding = Name::name_only(@shared.ffi_prefix + name) world_global = world_global.add(binding, to_direct_fn_low_type(typ)) global = global.add(binding) + top_level = top_level.add(binding, to_direct_fn_low_type(typ)) } }, ) { world: KnfWorld::{ externals: world_global, func_defs: Map::new() }, scope_path: [], + local: @hashset.new(), global, + top_level, free_vars: @immut/hashset.new(), - local: @hashset.new(), + top_level_free_vars: @immut/hashmap.new(), } } @@ -35,26 +41,39 @@ fn KnfEnv::fork(self : KnfEnv) -> KnfEnv { { world: self.world, scope_path: self.scope_path, + local: @hashset.new(), global, + top_level: self.top_level, free_vars: @immut/hashset.new(), - local: @hashset.new(), + top_level_free_vars: @immut/hashmap.new(), } } +fn KnfEnv::add_top_level(self : KnfEnv, name : Name, typ : LowType) -> Unit { + self.local.insert(name) + self.top_level = self.top_level.add(name, typ) +} + fn KnfEnv::add_local_var(self : KnfEnv, name : Name) -> Unit { self.local.insert(name) } -fn KnfEnv::collect_free_var(self : KnfEnv, name : Name) -> Unit { +fn KnfEnv::collect_free_var( + self : KnfEnv, + name : Name, + ~loc : SourceLoc = _ +) -> Unit { match self.local.contains(name) { true => () false => match self.global.contains(name) { true => - if self.world.externals.find(name).is_empty() { - self.free_vars = self.free_vars.add(name) + match self.top_level.find(name) { + Some(typ) => + self.top_level_free_vars = self.top_level_free_vars.add(name, typ) + None => self.free_vars = self.free_vars.add(name) } - false => @util.die("Unknown identifier name \{name}") + false => @util.die("Unknown identifier name \{name}", ~loc) } } } @@ -85,11 +104,11 @@ fn KnfEnv::exit_scope(self : KnfEnv) -> Unit { /// ------------- fn knf_preprocess(knf : Knf, externals : Map[String, Type]) -> (Knf, KnfWorld) { let env = KnfEnv::new(externals) - let knf = env.visit_stmt(knf) + let knf = env.visit_stmt(knf, top_level=true) (knf, env.world) } -fn KnfEnv::visit_stmt(self : KnfEnv, knf : Knf) -> Knf { +fn KnfEnv::visit_stmt(self : KnfEnv, knf : Knf, ~top_level : Bool) -> Knf { match knf { // Literal Unit | Int(_) | Double(_) => knf @@ -122,22 +141,22 @@ fn KnfEnv::visit_stmt(self : KnfEnv, knf : Knf) -> Knf { IfEq(lhs, rhs, true_branch, false_branch, typ) => { self.collect_free_var(lhs) self.collect_free_var(rhs) - let true_branch = self.visit_stmt(true_branch) - let false_branch = self.visit_stmt(false_branch) + let true_branch = self.visit_stmt(true_branch, top_level=false) + let false_branch = self.visit_stmt(false_branch, top_level=false) IfEq(lhs, rhs, true_branch, false_branch, typ) } IfLe(lhs, rhs, true_branch, false_branch, typ) => { self.collect_free_var(lhs) self.collect_free_var(rhs) - let true_branch = self.visit_stmt(true_branch) - let false_branch = self.visit_stmt(false_branch) + let true_branch = self.visit_stmt(true_branch, top_level=false) + let false_branch = self.visit_stmt(false_branch, top_level=false) IfLe(lhs, rhs, true_branch, false_branch, typ) } // Loop Loop(label, args, body) => { self.collect_free_vars(args.map(fn { a => a.0 }).iter()) - Loop(label, args, self.visit_stmt(body)) + Loop(label, args, self.visit_stmt(body, top_level=false)) } Continue(label, args) => { self.collect_free_vars(args.iter()) @@ -169,18 +188,26 @@ fn KnfEnv::visit_stmt(self : KnfEnv, knf : Knf) -> Knf { // Let Let((name, typ), expr, rest) => { - let expr = self.visit_stmt(expr) - self.add_local_var(name) - Let((name, typ), expr, self.visit_stmt(rest)) + let expr = self.visit_stmt(expr, top_level=false) + if top_level { + self.add_top_level(name, to_closure_fn_low_type(typ)) + } else { + self.add_local_var(name) + } + Let((name, typ), expr, self.visit_stmt(rest, ~top_level)) } LetTuple(els, expr, rest) => { self.collect_free_var(expr) els.each(fn { el => self.add_local_var(el.0) }) - LetTuple(els, expr, self.visit_stmt(rest)) + LetTuple(els, expr, self.visit_stmt(rest, ~top_level)) } LetRec(def, rest) => { // Add func def to local env - self.add_local_var(def.name) + if top_level { + self.add_top_level(def.name, to_direct_fn_low_type(def.ty)) + } else { + self.add_local_var(def.name) + } // Create mutable func def to maintain some extra information let mutdef = MutFuncDef::new(self, def) // 1. Fork new env for function body @@ -189,16 +216,24 @@ fn KnfEnv::visit_stmt(self : KnfEnv, knf : Knf) -> Knf { // 2. Add params to local env def.args.each(fn { (name, _) => new_env.add_local_var(name) }) // 3. Visit the function body, and update the current def - let updated_def = mutdef.update_body(new_env.visit_stmt(def.body)) + let updated_def = mutdef.update_body( + new_env.visit_stmt(def.body, top_level=false), + ) // 4. Record function free variables, and nest free variables mutdef.free_vars = @immut/hashset.from_array( // Note: we should not pass itself for recursion, for it has not been initialized new_env.free_vars.iter().filter(fn { n => n != def.name }).collect(), ) + mutdef.top_level_free_vars = @immut/hashmap.from_iter( + new_env.top_level_free_vars.iter(), + ) self.collect_free_vars(new_env.free_vars.iter()) + self.collect_free_vars( + new_env.top_level_free_vars.iter().map(fn { v => v.0 }), + ) // 5. Back to the prev env new_env.exit_scope() - LetRec(updated_def, self.visit_stmt(rest)) + LetRec(updated_def, self.visit_stmt(rest, ~top_level)) } // External diff --git a/src/closure/knf_to_closure.mbt b/src/closure/knf_to_closure.mbt index 2b7abd03..9e759310 100644 --- a/src/closure/knf_to_closure.mbt +++ b/src/closure/knf_to_closure.mbt @@ -205,6 +205,7 @@ fn Context::visit_stmt(self : Context, knf : Knf, is_top_level : Bool) -> Expr { is_closure, ty: func_type, args: def.args.mapi(fn { i, a => (a.0, args_type[i]) }), + top_level_vars: mutdef.top_level_free_vars.iter().collect(), formal_free_vars: mutdef.free_vars .iter() .map(fn { fv => (fv, self.get_low_type_of(fv)) }) @@ -221,6 +222,7 @@ fn Context::visit_stmt(self : Context, knf : Knf, is_top_level : Bool) -> Expr { (name, func_type), Closure::{ name: mutdef.to_label(), + top_level_vars: mutdef.top_level_free_vars.iter().collect(), actual_free_vars: mutdef.free_vars.iter().collect(), }, rest, @@ -230,6 +232,7 @@ fn Context::visit_stmt(self : Context, knf : Knf, is_top_level : Bool) -> Expr { (name, func_type), Closure::{ name: mutdef.to_label(), + top_level_vars: mutdef.top_level_free_vars.iter().collect(), actual_free_vars: mutdef.free_vars.iter().collect(), }, rest, diff --git a/src/closure/world.mbt b/src/closure/world.mbt index 64da4aea..073949ca 100644 --- a/src/closure/world.mbt +++ b/src/closure/world.mbt @@ -7,6 +7,8 @@ struct MutFuncDef { force_closure : Bool /// Collected free variables mut free_vars : @immut/hashset.T[Name] + /// Top level + mut top_level_free_vars : @immut/hashmap.T[Name, LowType] } fn MutFuncDef::new(env : KnfEnv, def : @knf.FuncDef) -> MutFuncDef { @@ -16,6 +18,7 @@ fn MutFuncDef::new(env : KnfEnv, def : @knf.FuncDef) -> MutFuncDef { def, force_closure: false, free_vars: @immut/hashset.new(), + top_level_free_vars: @immut/hashmap.new(), } env.world.func_defs.set(def.id, mutdef) mutdef diff --git a/src/closure_eval/interpreter.mbt b/src/closure_eval/interpreter.mbt index 4c7e9983..e46070a9 100644 --- a/src/closure_eval/interpreter.mbt +++ b/src/closure_eval/interpreter.mbt @@ -1,6 +1,7 @@ struct ClosureInterpreter { extern_fns : Map[String, (Array[Value]) -> Value] functions : Map[String, @closure.FuncDef] + mut global_env : InterpreterLocalVars } pub typealias Name = @types.Name @@ -32,7 +33,11 @@ pub fn Value::op_equal(self : Value, other : Value) -> Bool { } pub fn ClosureInterpreter::new() -> ClosureInterpreter { - { extern_fns: Map::new(), functions: Map::new() } + { + extern_fns: Map::new(), + global_env: @immut/hashmap.new(), + functions: Map::new(), + } } pub fn ClosureInterpreter::add_extern_fn( @@ -55,13 +60,14 @@ pub fn ClosureInterpreter::eval_full( self.functions.set(f.name._, f) } let env = InterpreterLocalVars::new() - self.eval!(env, expr.body) + self.eval!(env, expr.body, top_level=true) } pub fn ClosureInterpreter::eval( self : ClosureInterpreter, env : InterpreterLocalVars, - expr : @closure.Expr + expr : @closure.Expr, + ~top_level : Bool ) -> Value!Failure { match expr { Unit => Unit @@ -152,15 +158,15 @@ pub fn ClosureInterpreter::eval( match (x, y) { (Int(x), Int(y)) => if x == y { - self.eval!(env, e1) + self.eval!(env, e1, top_level=false) } else { - self.eval!(env, e2) + self.eval!(env, e2, top_level=false) } (Double(x), Double(y)) => if x == y { - self.eval!(env, e1) + self.eval!(env, e1, top_level=false) } else { - self.eval!(env, e2) + self.eval!(env, e2, top_level=false) } _ => fail!("type mismatch, ifeq expects Int or Double") } @@ -171,15 +177,15 @@ pub fn ClosureInterpreter::eval( match (x, y) { (Int(x), Int(y)) => if x <= y { - self.eval!(env, e1) + self.eval!(env, e1, top_level=false) } else { - self.eval!(env, e2) + self.eval!(env, e2, top_level=false) } (Double(x), Double(y)) => if x <= y { - self.eval!(env, e1) + self.eval!(env, e1, top_level=false) } else { - self.eval!(env, e2) + self.eval!(env, e2, top_level=false) } _ => fail!("type mismatch, ifle expects Int or Double") } @@ -187,7 +193,7 @@ pub fn ClosureInterpreter::eval( // Interperter for loop Loop((label, _), args, body) => { let new_env = env.add(label, Loop(args.map(fn { a => a.0 }), body)) - self.eval!(new_env, body) + self.eval!(new_env, body, top_level=false) } Continue(label, args) => { let tail_loop = find!(env, label) @@ -200,16 +206,19 @@ pub fn ClosureInterpreter::eval( for i = 0; i < params.length(); i = i + 1 { new_env = new_env.add(params[i], find!(env, args[i])) } - self.eval!(new_env, body) + self.eval!(new_env, body, top_level=false) } _ => fail!("type mismatch, continue expects Loop") } } // -------------------- Let((x, _), e1, e2) => { - let v = self.eval!(env, e1) + let v = self.eval!(env, e1, top_level=false) let new_env = env.add(x, v) - self.eval!(new_env, e2) + if top_level { + self.global_env = self.global_env.add(x, v) + } + self.eval!(new_env, e2, ~top_level) } MakeClosure((n, _), c, e) => { let closure = self.functions @@ -220,7 +229,10 @@ pub fn ClosureInterpreter::eval( fv.push(find!(env, x)) } let new_env = env.add(n, Closure(closure, fv)) - self.eval!(new_env, e) + if top_level { + self.global_env = env.add(n, Closure(closure, fv)) + } + self.eval!(new_env, e, ~top_level) } CallDirect(l, xs) => { let args = [] @@ -275,7 +287,7 @@ pub fn ClosureInterpreter::eval( } _ => fail!("type mismatch, lettuple expects Tuple") } - self.eval!(new_env, e) + self.eval!(new_env, e, ~top_level) } ArrayGet(arr, idx) => { let arr = find!(env, arr) @@ -310,10 +322,15 @@ pub fn ClosureInterpreter::eval_fn( let (x, _) = func.args[i] env = env.add(x, args[i]) } + for i = 0; i < func.top_level_vars.length(); i = i + 1 { + let (x, _) = func.top_level_vars[i] + let value = self.global_env.find(x).unwrap() + env = env.add(x, value) + } for i = 0; i < func.formal_free_vars.length(); i = i + 1 { let (x, _) = func.formal_free_vars[i] env = env.add(x, fv[i]) } env = env.add(func.old_name, Closure(func, fv)) - self.eval!(env, func.body) + self.eval!(env, func.body, top_level=false) } diff --git a/src/optimizing/copy/copy_propagation.mbt b/src/optimizing/copy/copy_propagation.mbt index c82553ea..1228e2dc 100644 --- a/src/optimizing/copy/copy_propagation.mbt +++ b/src/optimizing/copy/copy_propagation.mbt @@ -123,8 +123,7 @@ fn Context::transform(self : Context, knf : Knf) -> Knf { LetTuple(binding, expr, self.transform(rest)) } LetRec(def, rest) => { - let new_ctx = Context::new() - let def = { ..def, body: new_ctx.transform(def.body) } + let def = { ..def, body: self.transform(def.body) } LetRec(def, self.transform(rest)) } diff --git a/src/ssa/world_builder.mbt b/src/ssa/world_builder.mbt index 9541a82e..e1a00edd 100644 --- a/src/ssa/world_builder.mbt +++ b/src/ssa/world_builder.mbt @@ -175,10 +175,17 @@ fn WorldBuilder::build_top_level( closure.actual_free_vars.eachi( fn { i, name => self.add_global_var(name, def.formal_free_vars[i].1) }, ) + closure.top_level_vars.each( + fn { name => self.add_global_var(name.0, name.1) }, + ) self.add_global_fun(name, closure) MakeClosure( (name, typ), - { name: closure.name, actual_free_vars: [] }, + { + name: closure.name, + top_level_vars: closure.top_level_vars, + actual_free_vars: [], + }, self.build_top_level(rest), ) } From 035183ed91483f574b1d5542564237d1ccc658cf Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 02:01:47 +0800 Subject: [PATCH 8/9] feat(riscv): cache global var load --- src/riscv/machine_builder.mbt | 64 +++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/riscv/machine_builder.mbt b/src/riscv/machine_builder.mbt index acffa32c..b1f00008 100644 --- a/src/riscv/machine_builder.mbt +++ b/src/riscv/machine_builder.mbt @@ -99,6 +99,7 @@ fn MachineVar::from_ssa(var : @ssa.Var) -> MachineVar { struct Builder { method : MachineMethod vars : Map[Int, MachineVar] + imported_global_vars : Map[String, MachineVar] // for global vars world : MachineWorld @@ -112,7 +113,7 @@ fn Builder::new(world : MachineWorld, method : MachineMethod) -> Builder { } method.params.each(fn { p => vars.set(p.id, p) }) method.local_vars.each(fn { v => vars.set(v.id, v) }) - Builder::{ method, vars, world } + Builder::{ method, vars, imported_global_vars: Map::new(), world } } fn Builder::get_var(self : Builder, var : @ssa.Var) -> MachineVar { @@ -436,18 +437,28 @@ fn Builder::build_rvalue( Some(Int(x)) => Some(Int(x)) Some(Double(x)) => { let label = add_double_const(self.world, x) - let addr = self.add_temp_var(Ptr) - stmts.push(Definition(Some(addr), LoadLabel(label))) - Some(Load((addr, 0), Double, 202)) + match self.imported_global_vars.get(label) { + Some(tmp) => Some(Var(tmp, Double)) + None => { + let addr = self.add_temp_var(Ptr) + stmts.push(Definition(Some(addr), LoadLabel(label))) + Some(Load((addr, 0), Double, 202)) + } + } } None => { let width = Width::from_low_type(var.ty) if var.is_global { let (label, _) = self.world.globals.get(var.id).unwrap() - let addr = self.add_temp_var(Ptr) - stmts.push(Comment("Get global var \{v}")) - stmts.push(Definition(Some(addr), LoadLabel(label))) - Some(Load((addr, 0), width, 203)) + match self.imported_global_vars.get(label) { + Some(tmp) => Some(Var(tmp, width)) + None => { + let addr = self.add_temp_var(Ptr) + stmts.push(Comment("Get global var \{v}")) + stmts.push(Definition(Some(addr), LoadLabel(label))) + Some(Load((addr, 0), width, 203)) + } + } } else { Some(Var(var, width)) } @@ -653,14 +664,19 @@ fn Builder::build_get_var( } } else if var.is_global { match self.world.globals.get(var.id) { - Some((label, g)) => { - let addr = self.add_temp_var(Type::Ptr) - let tmp = self.add_temp_var(var.ty) - stmts.push(Comment("Get global var \{var}")) - stmts.push(Definition(Some(addr), LoadLabel(label))) - stmts.push(Definition(Some(tmp), Load((addr, 0), g.width, 207))) - tmp - } + Some((label, g)) => + match self.imported_global_vars.get(label) { + Some(tmp) => tmp + None => { + let addr = self.add_temp_var(Type::Ptr) + let tmp = self.add_temp_var(var.ty) + stmts.push(Comment("Get global var \{var}")) + stmts.push(Definition(Some(addr), LoadLabel(label))) + stmts.push(Definition(Some(tmp), Load((addr, 0), g.width, 207))) + self.imported_global_vars.set(label, tmp) + tmp + } + } None => @util.die("unreachable") } } else { @@ -677,9 +693,15 @@ fn Builder::build_double_const( stmts : Array[StmtKind] ) -> MachineVar { let label = add_double_const(self.world, value) - let addr = self.add_temp_var(Type::Ptr) - stmts.push(Definition(Some(addr), LoadLabel(label))) - let local_const = self.add_temp_var(Double) - stmts.push(Definition(Some(local_const), Load((addr, 0), Double, 208))) - local_const + match self.imported_global_vars.get(label) { + Some(tmp) => tmp + None => { + let addr = self.add_temp_var(Type::Ptr) + stmts.push(Definition(Some(addr), LoadLabel(label))) + let local_const = self.add_temp_var(Double) + stmts.push(Definition(Some(local_const), Load((addr, 0), Double, 208))) + self.imported_global_vars.set(label, local_const) + local_const + } + } } From 0d9804f98862b7e1b3afcb0a309e1217f287a183 Mon Sep 17 00:00:00 2001 From: yjl9903 Date: Tue, 5 Nov 2024 02:10:53 +0800 Subject: [PATCH 9/9] fix(riscv): not cache non const value --- src/riscv/machine_builder.mbt | 75 +++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/src/riscv/machine_builder.mbt b/src/riscv/machine_builder.mbt index b1f00008..69af358f 100644 --- a/src/riscv/machine_builder.mbt +++ b/src/riscv/machine_builder.mbt @@ -99,7 +99,8 @@ fn MachineVar::from_ssa(var : @ssa.Var) -> MachineVar { struct Builder { method : MachineMethod vars : Map[Int, MachineVar] - imported_global_vars : Map[String, MachineVar] + imported_global_consts : Map[String, MachineVar] + imported_global_labels : Map[String, MachineVar] // for global vars world : MachineWorld @@ -113,7 +114,13 @@ fn Builder::new(world : MachineWorld, method : MachineMethod) -> Builder { } method.params.each(fn { p => vars.set(p.id, p) }) method.local_vars.each(fn { v => vars.set(v.id, v) }) - Builder::{ method, vars, imported_global_vars: Map::new(), world } + Builder::{ + method, + vars, + imported_global_consts: Map::new(), + imported_global_labels: Map::new(), + world, + } } fn Builder::get_var(self : Builder, var : @ssa.Var) -> MachineVar { @@ -437,25 +444,31 @@ fn Builder::build_rvalue( Some(Int(x)) => Some(Int(x)) Some(Double(x)) => { let label = add_double_const(self.world, x) - match self.imported_global_vars.get(label) { + match self.imported_global_consts.get(label) { Some(tmp) => Some(Var(tmp, Double)) - None => { - let addr = self.add_temp_var(Ptr) - stmts.push(Definition(Some(addr), LoadLabel(label))) - Some(Load((addr, 0), Double, 202)) - } + None => + match self.imported_global_labels.get(label) { + Some(addr) => Some(Load((addr, 0), Double, 202)) + None => { + let addr = self.add_temp_var(Ptr) + stmts.push(Definition(Some(addr), LoadLabel(label))) + self.imported_global_labels.set(label, addr) + Some(Load((addr, 0), Double, 202)) + } + } } } None => { let width = Width::from_low_type(var.ty) if var.is_global { let (label, _) = self.world.globals.get(var.id).unwrap() - match self.imported_global_vars.get(label) { - Some(tmp) => Some(Var(tmp, width)) + match self.imported_global_labels.get(label) { + Some(addr) => Some(Load((addr, 0), width, 203)) None => { let addr = self.add_temp_var(Ptr) stmts.push(Comment("Get global var \{v}")) stmts.push(Definition(Some(addr), LoadLabel(label))) + self.imported_global_labels.set(label, addr) Some(Load((addr, 0), width, 203)) } } @@ -665,15 +678,19 @@ fn Builder::build_get_var( } else if var.is_global { match self.world.globals.get(var.id) { Some((label, g)) => - match self.imported_global_vars.get(label) { - Some(tmp) => tmp + match self.imported_global_labels.get(label) { + Some(addr) => { + let tmp = self.add_temp_var(var.ty) + stmts.push(Definition(Some(tmp), Load((addr, 0), g.width, 207))) + tmp + } None => { let addr = self.add_temp_var(Type::Ptr) let tmp = self.add_temp_var(var.ty) stmts.push(Comment("Get global var \{var}")) stmts.push(Definition(Some(addr), LoadLabel(label))) stmts.push(Definition(Some(tmp), Load((addr, 0), g.width, 207))) - self.imported_global_vars.set(label, tmp) + self.imported_global_labels.set(label, addr) tmp } } @@ -693,15 +710,29 @@ fn Builder::build_double_const( stmts : Array[StmtKind] ) -> MachineVar { let label = add_double_const(self.world, value) - match self.imported_global_vars.get(label) { + match self.imported_global_consts.get(label) { Some(tmp) => tmp - None => { - let addr = self.add_temp_var(Type::Ptr) - stmts.push(Definition(Some(addr), LoadLabel(label))) - let local_const = self.add_temp_var(Double) - stmts.push(Definition(Some(local_const), Load((addr, 0), Double, 208))) - self.imported_global_vars.set(label, local_const) - local_const - } + None => + match self.imported_global_labels.get(label) { + Some(addr) => { + let local_const = self.add_temp_var(Double) + stmts.push( + Definition(Some(local_const), Load((addr, 0), Double, 208)), + ) + self.imported_global_consts.set(label, local_const) + local_const + } + None => { + let addr = self.add_temp_var(Type::Ptr) + stmts.push(Definition(Some(addr), LoadLabel(label))) + let local_const = self.add_temp_var(Double) + stmts.push( + Definition(Some(local_const), Load((addr, 0), Double, 208)), + ) + self.imported_global_labels.set(label, addr) + self.imported_global_consts.set(label, local_const) + local_const + } + } } }