For single update

This commit is contained in:
J.Teeuwissen 2023-05-27 21:12:59 +02:00
parent 452bafc616
commit c6e7d56fb6
No known key found for this signature in database
GPG key ID: DB5F7A1ED8D478AD
2 changed files with 31 additions and 28 deletions

View file

@ -4939,6 +4939,8 @@ pub fn with_hole<'a>(
Err(_) => return runtime_error(env, "Can't update record with improper layout"),
};
let single_struct_field = sorted_fields.len() == 1;
// The struct indexing generated by the current context
let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena);
// The symbols that are used to create the new struct
@ -4958,10 +4960,14 @@ pub fn with_hole<'a>(
Ok(_field_layout) => {
current_struct_indexing.push(record_index);
let original_struct_symbol = env.unique_symbol();
if let Some(field) = updates.get(label) {
// The struct with a single field is optimized in such a way that replacing later indexing will cause an incorrect IR.
// Thus, only insert these struct_indices if there is more than one field in the struct.
if !single_struct_field {
let original_struct_symbol = env.unique_symbol();
env.struct_indexing
.insert(record_index, original_struct_symbol);
}
if let Some(field) = updates.get(label) {
let new_struct_symbol = possible_reuse_symbol_or_specialize(
env,
procs,
@ -4972,8 +4978,6 @@ pub fn with_hole<'a>(
new_struct_symbols.push(new_struct_symbol);
fields.push(UpdateExisting(field));
} else {
env.struct_indexing
.insert(record_index, original_struct_symbol);
new_struct_symbols
.push(*env.struct_indexing.get(record_index).unwrap());
fields.push(CopyExisting);
@ -4995,7 +4999,7 @@ pub fn with_hole<'a>(
_ => arena.alloc([record_layout]),
};
if new_struct_symbols.len() == 1 {
if single_struct_field {
// TODO we can probably special-case this more, skipping the generation of
// UpdateExisting
let mut stmt = hole.clone();
@ -5061,19 +5065,15 @@ pub fn with_hole<'a>(
};
for record_index in current_struct_indexing.into_iter().rev() {
let (symbol, usage) = env.struct_indexing.pop(&record_index).unwrap();
match usage {
Usage::Used => {
let layout = field_layouts[record_index.1 as usize];
let access_expr = Expr::StructAtIndex {
structure: specialized_structure_sym,
index: record_index.1,
field_layouts,
};
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
}
Usage::Unused => {}
}
if let Some(symbol) = env.struct_indexing.get_used(&record_index) {
let layout = field_layouts[record_index.1 as usize];
let access_expr = Expr::StructAtIndex {
structure: specialized_structure_sym,
index: record_index.1,
field_layouts,
};
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
};
}
if structure_needs_specialization {
@ -10101,7 +10101,10 @@ where
Some(value)
}
fn pop(&mut self, key: &K) -> Option<(V, Usage)> {
self.map.remove(key)
fn get_used(&mut self, key: &K) -> Option<V> {
self.map.remove(key).and_then(|(value, usage)| match usage {
Usage::Used => Some(value),
Usage::Unused => None,
})
}
}