-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Push ArrayGet instructions backwards through IfElse instructions to avoid expensive array merges #5570
base: master
Are you sure you want to change the base?
Conversation
…void expensive array merges But with bad Rust
compiler/noirc_evaluator/src/ssa.rs
Outdated
@@ -84,6 +84,7 @@ pub(crate) fn optimize_into_acir( | |||
// This pass must come immediately following `mem2reg` as the succeeding passes | |||
// may create an SSA which inlining fails to handle. | |||
.run_pass(Ssa::inline_functions_with_no_predicates, "After Inlining:") | |||
.run_pass(Ssa::array_get_optimization, "After Array Get Optimizations:") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name is temporary, we should find a name that better describes this pass.
// This should match the check in flatten_cfg | ||
if let crate::ssa::ir::function::RuntimeType::Brillig = function.runtime() { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from other passes: I'm not sure what it means though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just means that we only want to apply this SSA pass to functions which are being compiled to constrained ACIR rather than unconstrained Brillig. We do this as some optimisations are specific to each runtime.
This optimisation would benefit both runtimes however so we should remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick weekend phone review.
// This should match the check in flatten_cfg | ||
if let crate::ssa::ir::function::RuntimeType::Brillig = function.runtime() { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just means that we only want to apply this SSA pass to functions which are being compiled to constrained ACIR rather than unconstrained Brillig. We do this as some optimisations are specific to each runtime.
This optimisation would benefit both runtimes however so we should remove this.
Changes to circuit sizes
🧾 Summary (10% most significant diffs)
Full diff report 👇
|
// Only if the array isn't of a tuple type (or a composite type) | ||
if element_types.len() != 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how to handle this case. Without this, insert_instruction_and_results
below returns something that has multiple results and I don't know how to move that on to the next instruction. But maybe this optimization wasn't intended for composite types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to perform this on composite types as well but we can worry about that in a follow-up. Before merging this PR we should make an issue to add this though.
I don't get that gate diff on my machine. On master:
In this PR:
|
// | ||
// and a later ArrayGet instruction is this: | ||
// | ||
// v11 = array_get v4, index v4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// v11 = array_get v4, index v4 | |
// v11 = array_get v10, index v4 |
we mean v10
here?
}; | ||
|
||
// Don't optimize if the index is a constant (this is optimized later on in a different way) | ||
if let Value::NumericConstant { .. } = &dfg[dfg.resolve(*index)] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Value::NumericConstant { .. } = &dfg[dfg.resolve(*index)] { | |
if dfg.is_constant(*index) { |
// Only if the array isn't of a tuple type (or a composite type) | ||
if element_types.len() != 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to perform this on composite types as well but we can worry about that in a follow-up. Before merging this PR we should make an issue to add this though.
// | ||
// and the ArrayGet instruction is this: | ||
// | ||
// v11 = array_get v4, index v4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// v11 = array_get v4, index v4 | |
// v11 = array_get v10, index v4 |
?
I would make sure to run with
|
This is just blocked on the |
@TomAFrench I'd say its also blocked on not showing any other circuit improvements |
True. |
I've pushed an example program which drops from 305 opcodes to 9 with this PR |
Description
Problem
Resolves #5501
Summary
Implements #5501
Additional Context
None.
Documentation
Check one:
PR Checklist*
cargo fmt
on default settings.