feat(lowering): trim unused parameters of generated loop functions - #10246
feat(lowering): trim unused parameters of generated loop functions#10246TomerStarkware wants to merge 1 commit into
Conversation
PR SummaryMedium Risk Overview The phase runs once at the start of the final optimization pipeline on Tests and examples add file-based coverage, extend specialized-function fixtures with both branches of Reviewed by Cursor Bugbot for commit 4f536cf. Bugbot is set up for automated code reviews on this repo. Configure here. |
orizi
left a comment
There was a problem hiding this comment.
@orizi made 1 comment.
Reviewable status: 0 of 11 files reviewed, 1 unresolved discussion (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 20 at r1 (raw file):
/// Query implementation of [crate::db::LoweringGroup::unused_parameters]. #[salsa::tracked(returns(ref))] pub fn unused_parameters<'db>(
would changing usages analysis to not include these somehow have the same effect?
orizi
left a comment
There was a problem hiding this comment.
@orizi made 1 comment.
Reviewable status: 0 of 11 files reviewed, 2 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 30 at r1 (raw file):
} // Only compiler-generated loop functions are trimmed, as trimming the parameters of a // user-visible function would change its externally callable signature.
As a first stage - allow for specialized functions as well (as again, not externally called ever)
Code quote:
// Only compiler-generated loop functions are trimmed, as trimming the parameters of a
// user-visible function would change its externally callable signature.
orizi
left a comment
There was a problem hiding this comment.
@orizi made 2 comments.
Reviewable status: 0 of 11 files reviewed, 4 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 40 at r1 (raw file):
return vec![]; } let Ok(lowered) = db.lowered_body(function, LoweringStage::PreOptimizations) else {
probably post-baseline - as we would remove more unused code.
Code quote:
PreOptimizationscrates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 93 at r1 (raw file):
// which is beyond the parameters and is therefore never removed. remove_indices(&mut call_stmt.inputs, unused); }
Suggestion:
remove_indices(&mut call_stmt.inputs, db.unused_parameters(callee));a43609b to
5578367
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware made 4 comments.
Reviewable status: 0 of 12 files reviewed, 4 unresolved discussions (waiting on orizi).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 20 at r1 (raw file):
Previously, orizi wrote…
would changing
usagesanalysis to not include these somehow have the same effect?
used use_site analysis
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 30 at r1 (raw file):
Previously, orizi wrote…
As a first stage - allow for specialized functions as well (as again, not externally called ever)
Done.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 40 at r1 (raw file):
Previously, orizi wrote…
probably post-baseline - as we would remove more unused code.
Done.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 93 at r1 (raw file):
// which is beyond the parameters and is therefore never removed. remove_indices(&mut call_stmt.inputs, unused); }
Done.
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed 5 files and all commit messages, made 2 comments, and resolved 4 discussions.
Reviewable status: 5 of 12 files reviewed, 2 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 28 at r2 (raw file):
if matches!(db.optimizations(), Optimizations::Disabled) { return vec![]; }
should be part of the optimization fn - not the info query.
Code quote:
// The `TrimUnusedParams` phase is only part of the enabled optimization strategy, so when
// optimizations are disabled no parameter is trimmed.
if matches!(db.optimizations(), Optimizations::Disabled) {
return vec![];
}crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 69 at r2 (raw file):
&& call_stmt.function.body(db) == Ok(Some(function)) && call_stmt.inputs.get(*position).map(|input| input.var_id) == Some(**param) })
Suggestion:
if count == 1
&& let UseLocation::Statement((block_id, stmt_idx)) = loc
&& let Statement::Call(call_stmt) = &lowered.blocks[block_id].statements[stmt_idx]
&& call_stmt.function.body(db) == Ok(Some(function))
&& call_stmt.inputs.get(*position).map(|input| input.var_id) == Some(**param) {
true
} else {
false
}
})5578367 to
d3b2811
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware made 2 comments.
Reviewable status: 5 of 12 files reviewed, 2 unresolved discussions (waiting on orizi).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 28 at r2 (raw file):
Previously, orizi wrote…
should be part of the optimization fn - not the info query.
Done.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 69 at r2 (raw file):
&& call_stmt.function.body(db) == Ok(Some(function)) && call_stmt.inputs.get(*position).map(|input| input.var_id) == Some(**param) })
Done.
orizi
left a comment
There was a problem hiding this comment.
@orizi made 2 comments and resolved 1 discussion.
Reviewable status: 4 of 12 files reviewed, 3 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/db.rs line 114 at r3 (raw file):
/// applied they should be skipped when computing the /// function's external signature. fn unused_parameters<'db>(
why is it required to be pub at all?
isn't it just local for trim?
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 34 at r3 (raw file):
) { return vec![]; }
same issue - this sounds like something to be handled at callsite - this isn't actually used in any case.
or have a wrapper fn that has a different name.
Code quote:
// Only compiler-generated loop functions and specialized functions are trimmed, as trimming
// the parameters of a user-visible function would change its externally callable signature.
if !matches!(
function.long(db),
ConcreteFunctionWithBodyLongId::Generated(GeneratedFunction {
key: GeneratedFunctionKey::Loop(_),
..
}) | ConcreteFunctionWithBodyLongId::Specialized(_)
) {
return vec![];
}
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed 2 files and all commit messages, and resolved 1 discussion.
Reviewable status: 6 of 12 files reviewed, 2 unresolved discussions (waiting on TomerStarkware).
d3b2811 to
6d7722c
Compare
7b5f859 to
5447d91
Compare
a2ce4e8 to
b27c8dd
Compare
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed all commit messages and made 2 comments.
Reviewable status: 3 of 12 files reviewed, 4 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/db.rs line 106 at r5 (raw file):
} /// Returns the sorted positions of the parameters of the function that are never used by its
i believe this can be totally removed now.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params_test.rs line 24 at r5 (raw file):
use crate::{LoweringStage, Statement}; cairo_lang_test_utils::test_file_test!(
use the testing framework refactor.
b27c8dd to
2859c4c
Compare
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed all commit messages and made 1 comment.
Reviewable status: 3 of 13 files reviewed, 5 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 10 at r6 (raw file):
extern fn ext() -> bool nopanic; #[target_function] fn foo(a: felt252, b: felt252) -> felt252 {
can you replace all the testing with foo calling an unused_x fn - which calls an extern using particular vars?
all tests would be more readable, and we'd probably not need a special test code.
orizi
left a comment
There was a problem hiding this comment.
@orizi resolved 2 discussions.
Reviewable status: 3 of 13 files reviewed, 3 unresolved discussions (waiting on TomerStarkware).
2859c4c to
5f32d6e
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware made 5 comments.
Reviewable status: 3 of 13 files reviewed, 3 unresolved discussions (waiting on orizi).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 34 at r3 (raw file):
Previously, orizi wrote…
same issue - this sounds like something to be handled at callsite - this isn't actually used in any case.
or have a wrapper fn that has a different name.
Done.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params_test.rs line 24 at r5 (raw file):
Previously, orizi wrote…
use the testing framework refactor.
Done.
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 10 at r6 (raw file):
Previously, orizi wrote…
can you replace all the testing with
foocalling anunused_xfn - which calls anexternusing particular vars?all tests would be more readable, and we'd probably not need a special test code.
Done.
crates/cairo-lang-lowering/src/db.rs line 114 at r3 (raw file):
Previously, orizi wrote…
why is it required to be pub at all?
isn't it just local for trim?
Done.
crates/cairo-lang-lowering/src/db.rs line 106 at r5 (raw file):
Previously, orizi wrote…
i believe this can be totally removed now.
Done.
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed 2 files, made 5 comments, and resolved 3 discussions.
Reviewable status: 5 of 13 files reviewed, 5 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 105 at r7 (raw file):
if trimmable(callee) { remove_indices(&mut call_stmt.inputs, unused_parameters(db, callee)); }
Suggestion:
if let Statement::Call(call_stmt) = stmt
&& let Some(callee) = call_stmt.function.body(db)?
&& trimmable(callee) {
remove_indices(&mut call_stmt.inputs, unused_parameters(db, callee));
}crates/cairo-lang-lowering/src/optimizations/trim_unused_params_test.rs line 45 at r7 (raw file):
_ => 100, }) }),
would #[inline] on the expected function just
Code quote:
init_lowering_group(
&mut db,
Optimizations::Enabled(OptimizationConfig {
moveable_functions: vec![],
inlining_strategy: InliningStrategy::InlineSmallFunctions(0),
skip_const_folding: false,
}),
Some(|db, function_id| {
Ok(match function_id.long(db) {
ConcreteFunctionWithBodyLongId::Specialized(_) => 1,
_ => 100,
})
}),crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 18 at r7 (raw file):
fn foo(a: felt252, b: u32) { unused_a(0, a, b); }
this is the better ordering. (caller before callee)
prefer good name over extra doc.
(do this everywhere in this file)
Suggestion:
//! > cairo_code
#[target_function]
fn foo(a: felt252, b: u32) {
callee(0, a, b);
}
fn callee(_assure_specialized: felt252, unused: felt252, used: u32) {
ext(used);
}
#[allow(extern_outside_corelib)]
extern fn ext(v: u32) nopanic;
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 58 at r7 (raw file):
fn foo(a: u8, n: felt252) { thread_a(0, a, n); }
Suggestion:
#[target_function]
fn foo(a: u8, n: felt252) {
callee(0, a, n);
}
// `a` is only passed to the recursive call at its own position, so the entire chain is dead.
fn callee(_assure_specialized: felt252, threaded: u8, n: felt252) {
if n == 0 {
return;
}
thread_a(0, threaded, n - 1);
}
tests/e2e_test_data/trim_unused_params line 1 at r7 (raw file):
//! > Recursive loop function with a param that is always overwritten before use.
this dir is for sierra-to-casm related testing.
examples dir might be more relevant.
5f32d6e to
cc52f34
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware made 5 comments.
Reviewable status: 5 of 13 files reviewed, 5 unresolved discussions (waiting on orizi).
crates/cairo-lang-lowering/src/optimizations/trim_unused_params_test.rs line 45 at r7 (raw file):
Previously, orizi wrote…
would
#[inline]on the expected function just
Done.
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 18 at r7 (raw file):
Previously, orizi wrote…
this is the better ordering. (caller before callee)
prefer good name over extra doc.
(do this everywhere in this file)
Done.
tests/e2e_test_data/trim_unused_params line 1 at r7 (raw file):
Previously, orizi wrote…
this dir is for sierra-to-casm related testing.
examples dir might be more relevant.
Done.
crates/cairo-lang-lowering/src/optimizations/trim_unused_params.rs line 105 at r7 (raw file):
if trimmable(callee) { remove_indices(&mut call_stmt.inputs, unused_parameters(db, callee)); }
Done.
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 58 at r7 (raw file):
fn foo(a: u8, n: felt252) { thread_a(0, a, n); }
Done.
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed 14 files and all commit messages, made 3 comments, and resolved 5 discussions.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on TomerStarkware).
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 97 at r8 (raw file):
ext_felt252(used_a); ext_u32(used_b); }
Suggestion:
fn callee(_assure_specialized: felt252, used_a: felt252, used_b: u32) {
ext((used_a, used_b));
}
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 102 at r8 (raw file):
extern fn ext_felt252(v: felt252) nopanic; #[allow(extern_outside_corelib)] extern fn ext_u32(v: u32) nopanic;
Suggestion:
#[allow(extern_outside_corelib)]
extern fn ext<T>(t: T) nopanic;
cc52f34 to
944d086
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware made 2 comments.
Reviewable status: 17 of 18 files reviewed, 2 unresolved discussions (waiting on orizi).
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 97 at r8 (raw file):
ext_felt252(used_a); ext_u32(used_b); }
Done.
crates/cairo-lang-lowering/src/optimizations/test_data/trim_unused_params line 102 at r8 (raw file):
extern fn ext_felt252(v: felt252) nopanic; #[allow(extern_outside_corelib)] extern fn ext_u32(v: u32) nopanic;
Done.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 944d086. Configure here.
orizi
left a comment
There was a problem hiding this comment.
@orizi reviewed 1 file and all commit messages, and resolved 2 discussions.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on TomerStarkware).
Adds a `TrimUnusedParams` optimization phase that removes parameters never used by a compiler-generated loop function's body, from both the function's signature and every call site. Only loop functions are trimmed, as trimming a user-visible function would change its externally callable signature. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
944d086 to
4f536cf
Compare

Adds a
TrimUnusedParamsoptimization phase that removes parameters never used by a compiler-generated loop function's body, from both the function's signature and every call site.unused_parametersquery computes, per function, the parameter positions (in thePreOptimizationslayout) that are unused by the body. OnlyGeneratedFunctionKey::Loopfunctions are considered — trimming a user-visible function would change its externally callable signature — and nothing is trimmed when optimizations are disabled.PreOptimizationslowering, removing the unused parameters from the function's signature and from the inputs of every call site (coupon inputs are past the parameters and are never removed).get_function_signatureskips the trimmed parameters so the Sierra signature matches the post-optimizations lowering.🤖 Generated with Claude Code