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 17 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: 81e8a3e1b2c8f0e4a739a8088edb040c99a84c9b, compared to commit: f065c6682e2c896a346716cf88ac285f1d4bf846

🧾 Summary (10% most significant diffs)

Program ACIR opcodes (+/-) % Circuit size (+/-) %
regression_5252 +321 ❌ +0.98% +1,495 ❌ +3.36%
sha256_regression +2,773 ❌ +6.53% +4,027 ❌ +1.94%

Full diff report 👇
Program ACIR opcodes (+/-) % Circuit size (+/-) %
regression_5252 33,237 (+321) +0.98% 46,017 (+1,495) +3.36%
sha256_regression 45,248 (+2,773) +6.53% 211,986 (+4,027) +1.94%
sha256_var_size_regression 22,592 (+625) +2.85% 80,795 (+929) +1.16%
sha256_var_witness_const_regression 1,779 (+21) +1.19% 17,399 (+88) +0.51%
sha256 2,141 (+21) +0.99% 25,505 (+87) +0.34%

@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

TomAFrench and others added 2 commits September 30, 2024 22:19
* master: (313 commits)
  chore: Do not print entire functions when running debug trace (#6814)
  chore(ci): Active rollup circuits in compilation report (#6813)
  feat(ssa): Bring back tracking of RC instructions during DIE (#6783)
  feat: add `nargo test --format json` (#6796)
  chore: Change Id to use a u32 (#6807)
  feat(ssa): Hoist MakeArray instructions during loop invariant code motion  (#6782)
  feat: add `(x | 1)` optimization for booleans (#6795)
  feat: `nargo test -q` (or `nargo test --format terse`) (#6776)
  fix: disable failure persistance in nargo test fuzzing (#6777)
  feat(cli): Verify `return` against ABI and `Prover.toml` (#6765)
  chore(ssa): Activate loop invariant code motion on ACIR functions (#6785)
  fix: use extension in docs link so it also works on GitHub (#6787)
  fix: optimizer to keep track of changing opcode locations (#6781)
  fix: Minimal change to avoid reverting entire PR #6685 (#6778)
  feat: several `nargo test` improvements (#6728)
  chore: Try replace callstack with a linked list (#6747)
  chore: Use `NumericType` not `Type` for casts and numeric constants (#6769)
  chore(ci): Extend compiler memory report to external repos (#6768)
  chore(ci): Handle external libraries in compilation timing report (#6750)
  feat(ssa): Implement missing brillig constraints SSA check (#6658)
  ...
Copy link
Contributor

Peak Memory Sample

Program Peak Memory
keccak256 78.71M
workspace 122.04M
regression_4709 286.66M
ram_blowup_regression 1.62G
private-kernel-tail 209.11M
private-kernel-reset 848.11M
private-kernel-inner 304.33M
parity-root 174.64M

Copy link
Contributor

Compilation Sample

Program Compilation Time %
sha256_regression 0m1.519s 3%
regression_4709 0m0.733s -8%
ram_blowup_regression 0m16.140s -2%
rollup-base-public 6m48.688s 39%
rollup-base-private 3m17.728s 1%
private-kernel-tail 0m1.231s -13%
private-kernel-reset 0m8.309s -7%
private-kernel-inner 0m2.330s -8%
parity-root 0m1.189s 20%
noir-contracts 2m50.883s -2%

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