repro: md/repro-brillig-explosion
When refactoring the public_state.write method to write one field at a time, (rather than writing an entire array of fields at once) I have come across an interesting loop unrolling issue in brillig gen. I've spent some time diving into the brillig code to work out where the issue is.
I changed
let fields = T::serialize(value);
storage_write(self.storage_slot, fields);
to
let fields = T::serialize(value);
for i in 0..fields.len() {
storage_write(self.storage_slot + i, fields[i]);
}
And saw the number of brillig opcodes jump from ~10 to 2000.
I originally thought it was some generic issue, but it turns out that if you just replace the code with
for i in 0..1 {
println(i);
}
Where the loop should only run once, then the same blow up to 2000 opcodes exists.
[https://github.com/AztecProtocol/aztec-packages/blob/58da8815a68642ea78980de2a6d0f[…]df7/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr
](
)
I have done it on this branch, just run
directory: /noir-projects/noir-contracts
command: nargo compile --package avm_test_contract --silence-warnings
and see the brillig output (show_brillig is hardcoded to true)
To see what the output previously was you can comment the loop, and uncomment storage_writes to see the number of contraints go back to normal
https://github.com/AztecProtocol/aztec-packages/blob/58da8815a68642ea78980de2a6d0f1bbbed88df7/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr
for i in 0..1 {
From the debugging that I have done, I think the inclusion of the loop breaks noir's dead code elimination somewhat. Where the Option::none() in the context object are not removed.
repro: md/repro-brillig-explosion
When refactoring the public_state.write method to write one field at a time, (rather than writing an entire array of fields at once) I have come across an interesting loop unrolling issue in brillig gen. I've spent some time diving into the brillig code to work out where the issue is.
to
And saw the number of brillig opcodes jump from ~10 to 2000.
I originally thought it was some generic issue, but it turns out that if you just replace the code with
Where the loop should only run once, then the same blow up to 2000 opcodes exists.
[https://github.com/AztecProtocol/aztec-packages/blob/58da8815a68642ea78980de2a6d0f[…]df7/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr
](
aztec-packages/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr
Line 43 in 58da881
I have done it on this branch, just run
and see the brillig output (show_brillig is hardcoded to true)
To see what the output previously was you can comment the loop, and uncomment storage_writes to see the number of contraints go back to normal
https://github.com/AztecProtocol/aztec-packages/blob/58da8815a68642ea78980de2a6d0f1bbbed88df7/noir-projects/aztec-nr/aztec/src/state_vars/public_state.nr
for i in 0..1 {
From the debugging that I have done, I think the inclusion of the loop breaks noir's dead code elimination somewhat. Where the Option::none() in the context object are not removed.
aztec-packages/noir-projects/aztec-nr/aztec/src/context.nr
Line 4 in d3fc4f1