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"), 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 // The struct indexing generated by the current context
let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena); let mut current_struct_indexing = Vec::with_capacity_in(sorted_fields.len(), env.arena);
// The symbols that are used to create the new struct // The symbols that are used to create the new struct
@ -4958,10 +4960,14 @@ pub fn with_hole<'a>(
Ok(_field_layout) => { Ok(_field_layout) => {
current_struct_indexing.push(record_index); current_struct_indexing.push(record_index);
// 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(); let original_struct_symbol = env.unique_symbol();
if let Some(field) = updates.get(label) {
env.struct_indexing env.struct_indexing
.insert(record_index, original_struct_symbol); .insert(record_index, original_struct_symbol);
}
if let Some(field) = updates.get(label) {
let new_struct_symbol = possible_reuse_symbol_or_specialize( let new_struct_symbol = possible_reuse_symbol_or_specialize(
env, env,
procs, procs,
@ -4972,8 +4978,6 @@ pub fn with_hole<'a>(
new_struct_symbols.push(new_struct_symbol); new_struct_symbols.push(new_struct_symbol);
fields.push(UpdateExisting(field)); fields.push(UpdateExisting(field));
} else { } else {
env.struct_indexing
.insert(record_index, original_struct_symbol);
new_struct_symbols new_struct_symbols
.push(*env.struct_indexing.get(record_index).unwrap()); .push(*env.struct_indexing.get(record_index).unwrap());
fields.push(CopyExisting); fields.push(CopyExisting);
@ -4995,7 +4999,7 @@ pub fn with_hole<'a>(
_ => arena.alloc([record_layout]), _ => 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 // TODO we can probably special-case this more, skipping the generation of
// UpdateExisting // UpdateExisting
let mut stmt = hole.clone(); let mut stmt = hole.clone();
@ -5061,9 +5065,7 @@ pub fn with_hole<'a>(
}; };
for record_index in current_struct_indexing.into_iter().rev() { for record_index in current_struct_indexing.into_iter().rev() {
let (symbol, usage) = env.struct_indexing.pop(&record_index).unwrap(); if let Some(symbol) = env.struct_indexing.get_used(&record_index) {
match usage {
Usage::Used => {
let layout = field_layouts[record_index.1 as usize]; let layout = field_layouts[record_index.1 as usize];
let access_expr = Expr::StructAtIndex { let access_expr = Expr::StructAtIndex {
structure: specialized_structure_sym, structure: specialized_structure_sym,
@ -5071,9 +5073,7 @@ pub fn with_hole<'a>(
field_layouts, field_layouts,
}; };
stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt)); stmt = Stmt::Let(symbol, access_expr, layout, arena.alloc(stmt));
} };
Usage::Unused => {}
}
} }
if structure_needs_specialization { if structure_needs_specialization {
@ -10101,7 +10101,10 @@ where
Some(value) Some(value)
} }
fn pop(&mut self, key: &K) -> Option<(V, Usage)> { fn get_used(&mut self, key: &K) -> Option<V> {
self.map.remove(key) self.map.remove(key).and_then(|(value, usage)| match usage {
Usage::Used => Some(value),
Usage::Unused => None,
})
} }
} }

View file

@ -1,13 +1,13 @@
procedure Test.1 (Test.2): procedure Test.1 (Test.2):
dec Test.2; dec Test.2;
let Test.8 : Str = "ux"; let Test.7 : Str = "ux";
let Test.9 : Str = "uy"; let Test.8 : Str = "uy";
let Test.7 : {Str, Str} = Struct {Test.8, Test.9}; let Test.6 : {Str, Str} = Struct {Test.7, Test.8};
ret Test.7; ret Test.6;
procedure Test.0 (): procedure Test.0 ():
let Test.11 : Str = "x"; let Test.10 : Str = "x";
let Test.12 : Str = "y"; let Test.11 : Str = "y";
let Test.10 : {Str, Str} = Struct {Test.11, Test.12}; let Test.9 : {Str, Str} = Struct {Test.10, Test.11};
let Test.3 : {Str, Str} = CallByName Test.1 Test.10; let Test.3 : {Str, Str} = CallByName Test.1 Test.9;
ret Test.3; ret Test.3;