Skip to content
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

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

asterite
Copy link
Collaborator

@asterite asterite commented Jul 19, 2024

Description

Problem

Resolves #5501

Summary

Implements #5501

Additional Context

None.

Documentation

Check one:

  • No documentation needed.
  • Documentation included in this PR.
  • [For Experimental Features] Documentation to be submitted in a separate PR.

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

@@ -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:")
Copy link
Collaborator Author

@asterite asterite Jul 19, 2024

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.

Comment on lines 27 to 30
// This should match the check in flatten_cfg
if let crate::ssa::ir::function::RuntimeType::Brillig = function.runtime() {
continue;
}
Copy link
Collaborator Author

@asterite asterite Jul 19, 2024

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.

Copy link
Member

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.

Copy link
Member

@TomAFrench TomAFrench left a 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.

compiler/noirc_evaluator/src/ssa/opt/array_get.rs Outdated Show resolved Hide resolved
compiler/noirc_evaluator/src/ssa/opt/array_get.rs Outdated Show resolved Hide resolved
compiler/noirc_evaluator/src/ssa/opt/array_get.rs Outdated Show resolved Hide resolved
Comment on lines 27 to 30
// This should match the check in flatten_cfg
if let crate::ssa::ir::function::RuntimeType::Brillig = function.runtime() {
continue;
}
Copy link
Member

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.

Copy link
Contributor

github-actions bot commented Jul 22, 2024

Changes to circuit sizes

Generated at commit: 89a775100e3c08be4ba21b9d1b04913a602b55a7, compared to commit: 1ac980bb6d227d0cc52162b0251deae92aa0ea86

🧾 Summary (10% most significant diffs)

Program ACIR opcodes (+/-) % Circuit size (+/-) %
sha256_regression +11,411 ❌ +29.14% +15,042 ❌ +7.41%
sha256_var_size_regression +2,239 ❌ +11.64% +3,101 ❌ +4.16%

Full diff report 👇
Program ACIR opcodes (+/-) % Circuit size (+/-) %
sha256_regression 50,573 (+11,411) +29.14% 218,128 (+15,042) +7.41%
sha256_var_size_regression 21,471 (+2,239) +11.64% 77,700 (+3,101) +4.16%
regression_5252 77,268 (+270) +0.35% 84,727 (+865) +1.03%
sha256 2,424 (+14) +0.58% 47,628 (0) 0.00%
sha256_var_witness_const_regression 1,997 (+14) +0.71% 44,720 (0) 0.00%

@asterite asterite marked this pull request as ready for review July 22, 2024 15:00
Comment on lines +77 to +78
// Only if the array isn't of a tuple type (or a composite type)
if element_types.len() != 1 {
Copy link
Collaborator Author

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?

Copy link
Contributor

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.

@asterite
Copy link
Collaborator Author

I don't get that gate diff on my machine. On master:

+-----------------+----------+----------------------+--------------+
| Package         | Function | Expression Width     | ACIR Opcodes |
+-----------------+----------+----------------------+--------------+
| regression_5252 | main     | Bounded { width: 4 } | 81786        |
+-----------------+----------+----------------------+--------------+

In this PR:

+-----------------+----------+----------------------+--------------+
| Package         | Function | Expression Width     | ACIR Opcodes |
+-----------------+----------+----------------------+--------------+
| regression_5252 | main     | Bounded { width: 4 } | 81786        |
+-----------------+----------+----------------------+--------------+

//
// and a later ArrayGet instruction is this:
//
// v11 = array_get v4, index v4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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)] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if let Value::NumericConstant { .. } = &dfg[dfg.resolve(*index)] {
if dfg.is_constant(*index) {

Comment on lines +77 to +78
// Only if the array isn't of a tuple type (or a composite type)
if element_types.len() != 1 {
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// v11 = array_get v4, index v4
// v11 = array_get v10, index v4

?

@vezenovm
Copy link
Contributor

vezenovm commented Jul 22, 2024

In this PR:

I would make sure to run with nargo info --force as we cache build artifacts.
I got the following which is in line with the diff action:

+-----------------+----------+----------------------+--------------+
| Package         | Function | Expression Width     | ACIR Opcodes |
+-----------------+----------+----------------------+--------------+
| regression_5252 | main     | Bounded { width: 4 } | 82053        |
+-----------------+----------+----------------------+--------------+

@TomAFrench
Copy link
Member

This is just blocked on the regression_5252 regression, right?

@jfecher
Copy link
Contributor

jfecher commented Aug 20, 2024

@TomAFrench I'd say its also blocked on not showing any other circuit improvements

@TomAFrench
Copy link
Member

True.

@TomAFrench
Copy link
Member

I've pushed an example program which drops from 305 opcodes to 9 with this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Push ArrayGet instructions backwards through IfElse instructions to avoid expensive array merges
4 participants