mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
Refactor the optimisation for immediately-returned Let statements
The original intention was to avoid creating a local when we define and immediately return a primitive value. But now our default path does avoids unnecessary locals anyway! For StackMemory values we do need an optimised path but it's nicer to just pass a flag to Storage::allocate.
This commit is contained in:
parent
2daefc8b32
commit
1b97675f1f
3 changed files with 37 additions and 54 deletions
|
@ -12,7 +12,7 @@ use roc_mono::layout::{Builtin, Layout};
|
|||
|
||||
use crate::code_builder::CodeBuilder;
|
||||
use crate::layout::WasmLayout;
|
||||
use crate::storage::{LocalKind, StackMemoryLocation, Storage, StoredValue};
|
||||
use crate::storage::{Storage, StoredValue, StoredValueKind};
|
||||
use crate::{copy_memory, pop_stack_frame, push_stack_frame, CopyMemoryConfig, LocalId, PTR_TYPE};
|
||||
|
||||
// Don't allocate any constant data at address zero or near it. Would be valid, but bug-prone.
|
||||
|
@ -105,8 +105,11 @@ impl<'a> WasmBackend<'a> {
|
|||
};
|
||||
|
||||
for (layout, symbol) in proc.args {
|
||||
self.storage
|
||||
.allocate(&WasmLayout::new(layout), *symbol, LocalKind::Parameter);
|
||||
self.storage.allocate(
|
||||
&WasmLayout::new(layout),
|
||||
*symbol,
|
||||
StoredValueKind::Parameter,
|
||||
);
|
||||
}
|
||||
|
||||
signature_builder.with_params(self.storage.arg_types.clone())
|
||||
|
@ -190,50 +193,20 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
fn build_stmt(&mut self, stmt: &Stmt<'a>, ret_layout: &Layout<'a>) -> Result<(), String> {
|
||||
match stmt {
|
||||
// Simple optimisation: if we are just returning the expression, we don't need a local
|
||||
Stmt::Let(let_sym, expr, layout, Stmt::Ret(ret_sym)) if *let_sym == *ret_sym => {
|
||||
let wasm_layout = WasmLayout::new(layout);
|
||||
|
||||
if let WasmLayout::StackMemory {
|
||||
size,
|
||||
alignment_bytes,
|
||||
} = wasm_layout
|
||||
{
|
||||
// Map this symbol to the first argument (pointer into caller's stack)
|
||||
// Saves us from having to copy it later
|
||||
let storage = StoredValue::StackMemory {
|
||||
location: StackMemoryLocation::PointerArg(LocalId(0)),
|
||||
size,
|
||||
alignment_bytes,
|
||||
};
|
||||
self.storage.symbol_storage_map.insert(*let_sym, storage);
|
||||
}
|
||||
|
||||
self.build_expr(let_sym, expr, layout)?;
|
||||
|
||||
if let WasmLayout::Primitive(value_type, size) = wasm_layout {
|
||||
let vm_state = self.code_builder.set_top_symbol(*let_sym);
|
||||
self.storage.symbol_storage_map.insert(
|
||||
*let_sym,
|
||||
StoredValue::VirtualMachineStack {
|
||||
vm_state,
|
||||
value_type,
|
||||
size,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
self.code_builder.add_one(Br(self.block_depth)); // jump to end of function (stack frame pop)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Stmt::Let(sym, expr, layout, following) => {
|
||||
let wasm_layout = WasmLayout::new(layout);
|
||||
|
||||
self.storage
|
||||
.allocate(&wasm_layout, *sym, LocalKind::Variable);
|
||||
let kind = match following {
|
||||
Stmt::Ret(ret_sym) if *sym == *ret_sym => StoredValueKind::ReturnValue,
|
||||
_ => StoredValueKind::Variable,
|
||||
};
|
||||
|
||||
self.storage.allocate(&wasm_layout, *sym, kind);
|
||||
|
||||
self.build_expr(sym, expr, layout)?;
|
||||
|
||||
// For primitives, we record that this symbol is at the top of the VM stack
|
||||
// (For other values, we wrote to memory and there's nothing on the VM stack)
|
||||
if let WasmLayout::Primitive(value_type, size) = wasm_layout {
|
||||
let vm_state = self.code_builder.set_top_symbol(*sym);
|
||||
self.storage.symbol_storage_map.insert(
|
||||
|
@ -349,9 +322,11 @@ impl<'a> WasmBackend<'a> {
|
|||
let mut jp_param_storages = std::vec::Vec::with_capacity(parameters.len());
|
||||
for parameter in parameters.iter() {
|
||||
let wasm_layout = WasmLayout::new(¶meter.layout);
|
||||
let mut param_storage =
|
||||
self.storage
|
||||
.allocate(&wasm_layout, parameter.symbol, LocalKind::Variable);
|
||||
let mut param_storage = self.storage.allocate(
|
||||
&wasm_layout,
|
||||
parameter.symbol,
|
||||
StoredValueKind::Variable,
|
||||
);
|
||||
param_storage = self.storage.ensure_value_has_local(
|
||||
&mut self.code_builder,
|
||||
parameter.symbol,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue