Skip to content

Commit 65c6092

Browse files
(optimization): Reboxing now also works on whole var reboxing
1 parent ef335a5 commit 65c6092

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

crates/cairo-lang-lowering/src/optimizations/reboxing.rs

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,23 @@ fn apply_reboxing_candidate<'db>(
215215
candidate.reboxed_var.index()
216216
);
217217

218-
// TODO(eytan-starkware): Handle snapshot of box (e.g., @Box<T>).
219-
// Only support MemberOfUnboxed where source is Unboxed for now.
220-
let ReboxingValue::MemberOfUnboxed { source, member } = &candidate.source else {
221-
// If source is not member of unboxed, we are reboxing original value which is not supported
222-
// yet.
223-
return;
218+
match &candidate.source {
219+
ReboxingValue::Revoked => (),
220+
ReboxingValue::Unboxed(id) => replace_variable_usages(lowered, candidate.reboxed_var, *id),
221+
ReboxingValue::MemberOfUnboxed { source, member } => {
222+
replace_into_box_call(db, lowered, candidate, source, *member)
223+
}
224224
};
225+
}
226+
227+
/// Replaces the call to `into_box` with a call to `struct_boxed_deconstruct`.
228+
fn replace_into_box_call<'db>(
229+
db: &'db dyn Database,
230+
lowered: &mut Lowered<'db>,
231+
candidate: &ReboxCandidate,
232+
source: &Rc<ReboxingValue>,
233+
member: usize,
234+
) {
225235
let ReboxingValue::Unboxed(source_var) = **source else {
226236
// When source of the value is not `Unboxes`, it is a nested MemberOfUnboxed, which is not
227237
// supported yet.
@@ -232,7 +242,7 @@ fn apply_reboxing_candidate<'db>(
232242
db,
233243
&mut lowered.variables,
234244
source_var,
235-
*member,
245+
member,
236246
candidate.reboxed_var,
237247
&lowered.blocks[candidate.into_box_location.0].statements[candidate.into_box_location.1],
238248
) {
@@ -244,6 +254,59 @@ fn apply_reboxing_candidate<'db>(
244254
}
245255
}
246256

257+
/// Replaces all usages of old_var with new_var throughout the lowered function.
258+
fn replace_variable_usages(lowered: &mut Lowered<'_>, old_var: VariableId, new_var: VariableId) {
259+
if old_var == new_var {
260+
return;
261+
}
262+
263+
for block in lowered.blocks.iter_mut() {
264+
for stmt in &mut block.statements {
265+
for input in stmt.inputs_mut() {
266+
if input.var_id == old_var {
267+
input.var_id = new_var;
268+
}
269+
}
270+
}
271+
272+
match &mut block.end {
273+
BlockEnd::Return(var_usages, _) => {
274+
for return_var in var_usages.iter_mut() {
275+
if return_var.var_id == old_var {
276+
return_var.var_id = new_var;
277+
}
278+
}
279+
}
280+
BlockEnd::Goto(_, remapping) => {
281+
// Collect all changes needed
282+
let mut changes = Vec::new();
283+
for (dst, src_usage) in remapping.iter() {
284+
if *dst == old_var {
285+
changes.push((*dst, Some(new_var), *src_usage));
286+
} else if src_usage.var_id == old_var {
287+
let mut new_usage = *src_usage;
288+
new_usage.var_id = new_var;
289+
changes.push((*dst, None, new_usage));
290+
}
291+
}
292+
293+
// Apply changes
294+
for (old_key, new_key_opt, new_usage) in changes {
295+
if let Some(new_key) = new_key_opt {
296+
// Key needs to change
297+
remapping.swap_remove(&old_key);
298+
remapping.insert(new_key, new_usage);
299+
} else {
300+
// Only value needs to change
301+
remapping.insert(old_key, new_usage);
302+
}
303+
}
304+
}
305+
_ => {}
306+
}
307+
}
308+
}
309+
247310
/// Creates a struct_boxed_deconstruct call statement.
248311
/// Returns None if the call cannot be created.
249312
fn create_struct_boxed_deconstruct_call<'db>(

crates/cairo-lang-lowering/src/optimizations/test_data/reboxing

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,6 @@ test_reboxing_analysis
229229
//! > function_name
230230
rebox_whole
231231

232-
//! > TODO(eytan-starkware): Add support for whole var reboxing
233-
234232
//! > module_code
235233
struct Simple {
236234
value: felt252,
@@ -264,7 +262,7 @@ Statements:
264262
(v1: test::Simple) <- core::box::unbox::<test::Simple>(v0)
265263
(v2: core::box::Box::<test::Simple>) <- core::box::into_box::<test::Simple>(v1)
266264
End:
267-
Return(v2)
265+
Return(v0)
268266

269267
//! > ==========================================================================
270268

0 commit comments

Comments
 (0)