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(ssa): Merge slices in if statements with witness conditions #2347

Merged
merged 73 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
504aad0
cleanup load instruction search w/ predecessors methods
vezenovm Aug 9, 2023
d129a0a
update regression_2218 test
vezenovm Aug 9, 2023
2106b6c
merge conflicts w/ master
vezenovm Aug 9, 2023
51abb14
initial merge slices work, weird bug right now with intrinsics, not g…
vezenovm Aug 10, 2023
17d66aa
cargo clippy
vezenovm Aug 10, 2023
06d7773
working slice merger, but broken index_lvalue and append
vezenovm Aug 10, 2023
a92d2c9
merge slices working w/ updated slice representation, have to fix som…
vezenovm Aug 10, 2023
e32e665
clean up recursive load fetch method
vezenovm Aug 10, 2023
ada6129
add test to mem2reg pass
vezenovm Aug 10, 2023
bedfa2a
cleaner search methods
vezenovm Aug 10, 2023
3d422e1
switch from recursive to while-loop based search for loads
vezenovm Aug 10, 2023
c12c5bb
add comments to mem2reg pass
vezenovm Aug 10, 2023
9988d91
fmt
vezenovm Aug 10, 2023
7cc6afe
remove dbg
vezenovm Aug 10, 2023
b4ee4fc
merge conflcits w/ mv/func-mem2reg
vezenovm Aug 10, 2023
24b2fe6
fixed ec_baby_jubjub but need fix to mem2reg pass to make it efficient
vezenovm Aug 10, 2023
fc7327a
move dom tree per func
vezenovm Aug 10, 2023
0bb6401
cargo fmt
vezenovm Aug 10, 2023
5baf9e8
make dom tree part of the func context
vezenovm Aug 10, 2023
990d593
merge w/ mv/func-mem2reg
vezenovm Aug 10, 2023
06256c6
remove old ocmment
vezenovm Aug 10, 2023
ae75b7a
Merge branch 'mv/func-mem2reg' into mv/merge-slices-2
vezenovm Aug 10, 2023
1f8d4bd
fixed mem2reg before flattening
vezenovm Aug 11, 2023
c8f9317
remove loops from mem2reg function context
vezenovm Aug 11, 2023
a824ed3
remove import
vezenovm Aug 11, 2023
e345f8c
Update crates/noirc_evaluator/src/ssa/opt/mem2reg.rs
jfecher Aug 11, 2023
fb53610
Update crates/noirc_evaluator/src/ssa/opt/mem2reg.rs
jfecher Aug 11, 2023
e07c999
m em2reg debug work
vezenovm Aug 12, 2023
265b883
working func mem2reg for various reference alias cases
vezenovm Aug 15, 2023
3906ca2
array dynamic back to original
vezenovm Aug 15, 2023
7ed502d
use reachable blocks
vezenovm Aug 15, 2023
bac1e30
merge conflicts w/ master
vezenovm Aug 15, 2023
d697231
merge conflicts from master
vezenovm Aug 15, 2023
71c5693
restore sha2_blocks test
vezenovm Aug 15, 2023
c612b45
remove unnecessary clone and unused methods
vezenovm Aug 15, 2023
4e47914
merge conflcits w/ mem2reg branch and quick change
vezenovm Aug 15, 2023
ef10232
bring back loops check inside fetch methods
vezenovm Aug 15, 2023
0a1925c
merge conflicts
vezenovm Aug 15, 2023
8d535eb
Update crates/nargo_cli/tests/execution_success/regression/src/main.nr
vezenovm Aug 15, 2023
bd678a9
all to_bits methods working for acir, fixing up brillig with new slic…
vezenovm Aug 15, 2023
f989fe9
guarantee that x == 3 in references regressio nfor 2218
vezenovm Aug 15, 2023
12ee7ad
remove leftover comments
vezenovm Aug 15, 2023
415e516
Merge branch 'mv/func-mem2reg' into mv/merge-slices-2
vezenovm Aug 15, 2023
6149e48
all brillig sslice intrinsics working except insert and remove
vezenovm Aug 15, 2023
2a1da3e
working brillig_nested_slices
vezenovm Aug 16, 2023
2a95fbf
missed save
vezenovm Aug 16, 2023
c05e92c
working brillig oracle with new slices
vezenovm Aug 16, 2023
3f37004
cleanup comments and dbgs
vezenovm Aug 16, 2023
97a4b2a
merge conflicts w/ master
vezenovm Aug 16, 2023
c89bb76
fixes to simplify_call
vezenovm Aug 16, 2023
48c8514
cleanup updating slice length in brillig block
vezenovm Aug 16, 2023
ff631e2
cleanup in simplify_call and cleanup
vezenovm Aug 16, 2023
c55befc
more integration tests for merge_slices
vezenovm Aug 16, 2023
394b5c5
small comments
vezenovm Aug 16, 2023
14b676d
remove dbg
vezenovm Aug 16, 2023
7999996
remove unnecessary noir test
vezenovm Aug 16, 2023
ffda9cc
remove check on failed_to_unroll
vezenovm Aug 16, 2023
9e4a065
cleanup index_lvalue
vezenovm Aug 16, 2023
2b82aca
cleanup codegen_literal
vezenovm Aug 16, 2023
89e553e
remove radix padding
vezenovm Aug 17, 2023
de2d962
merge conflicts w/ master
vezenovm Aug 17, 2023
7ba3be5
some pr comments and formatting
vezenovm Aug 18, 2023
caebc6b
Update crates/nargo_cli/tests/execution_success/brillig_to_le_bytes/s…
vezenovm Aug 18, 2023
a2a0898
Update crates/noirc_evaluator/src/ssa/ir/instruction/call.rs
vezenovm Aug 18, 2023
5327345
Update crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs
vezenovm Aug 18, 2023
cca2e34
Update crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs
vezenovm Aug 18, 2023
892b435
Update crates/noirc_evaluator/src/ssa/opt/flatten_cfg.rs
vezenovm Aug 18, 2023
eaa6e9c
Update crates/noirc_evaluator/src/ssa/ssa_gen/context.rs
vezenovm Aug 18, 2023
bfea324
comments
vezenovm Aug 18, 2023
f8c9c70
cleanup and comments from pr review
vezenovm Aug 18, 2023
b3a54c6
more specific comment for LValue::SliceIndex assign
vezenovm Aug 18, 2023
838c598
improve error in codegen_literal
vezenovm Aug 18, 2023
99b1c20
Update crates/noirc_evaluator/src/ssa/ssa_gen/context.rs
vezenovm Aug 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions crates/nargo/src/ops/foreign_calls.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use acvm::{
acir::brillig::{ForeignCallResult, Value},
acir::brillig::{ForeignCallOutput, ForeignCallResult, Value},
pwg::ForeignCallWaitInfo,
};
use iter_extended::vecmap;
Expand Down Expand Up @@ -54,13 +54,25 @@ impl ForeignCall {
}
Some(ForeignCall::Sequence) => {
let sequence_length: u128 = foreign_call.inputs[0][0].to_field().to_u128();

Ok(vecmap(0..sequence_length, Value::from).into())
let sequence = vecmap(0..sequence_length, Value::from);

Ok(ForeignCallResult {
values: vec![
ForeignCallOutput::Single(sequence_length.into()),
ForeignCallOutput::Array(sequence),
],
})
}
Some(ForeignCall::ReverseSequence) => {
let sequence_length: u128 = foreign_call.inputs[0][0].to_field().to_u128();

Ok(vecmap((0..sequence_length).rev(), Value::from).into())
let sequence = vecmap((0..sequence_length).rev(), Value::from);

Ok(ForeignCallResult {
values: vec![
ForeignCallOutput::Single(sequence_length.into()),
ForeignCallOutput::Array(sequence),
],
})
}
None => panic!("unexpected foreign call {:?}", foreign_call_name),
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "slice_access_failure"
type = "bin"
authors = [""]
compiler_version = "0.10.2"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x = "5"
y = "10"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fn main(x : Field, y : pub Field) {
let mut slice = [0; 2];
if x == y {
slice = slice.push_back(y);
slice = slice.push_back(x);
} else {
slice = slice.push_back(x);
}
// This constraint should fail as the slice length is 3 and the index is 3
// The right hand side AND case ensures that the circuit inputs have not changed
// and we always hit the else case in the if statement above.
assert((slice[3] == 0) & (slice[2] != y));
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,85 @@ unconstrained fn main(x: Field, y: Field) {
let (empty_slice, should_be_x) = slice.remove(0);
assert(should_be_x == x);
assert(empty_slice.len() == 0);

regression_merge_slices(x, y);
}

// Tests slice passing to/from functions
unconstrained fn push_front_to_slice<T>(slice: [T], item: T) -> [T] {
slice.push_front(item)
}

// The parameters to this function must come from witness values (inputs to main)
unconstrained fn regression_merge_slices(x: Field, y: Field) {
merge_slices_if(x, y);
merge_slices_else(x);
}

unconstrained fn merge_slices_if(x: Field, y: Field) {
let slice = merge_slices_return(x, y);
assert(slice[2] == 10);
assert(slice.len() == 3);

let slice = merge_slices_mutate(x, y);
assert(slice[3] == 5);
assert(slice.len() == 4);

let slice = merge_slices_mutate_in_loop(x, y);
assert(slice[6] == 4);
assert(slice.len() == 7);
}

unconstrained fn merge_slices_else(x: Field) {
let slice = merge_slices_return(x, 5);
assert(slice[0] == 0);
assert(slice[1] == 0);
assert(slice.len() == 2);

let slice = merge_slices_mutate(x, 5);
assert(slice[2] == 5);
assert(slice.len() == 3);

let slice = merge_slices_mutate_in_loop(x, 5);
assert(slice[2] == 5);
assert(slice.len() == 3);
}

// Test returning a merged slice without a mutation
unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] {
let slice = [0; 2];
if x != y {
if x != 20 {
slice.push_back(y)
} else {
slice
}
} else {
slice
}
}

// Test mutating a slice inside of an if statement
unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] {
let mut slice = [0; 2];
if x != y {
slice = slice.push_back(y);
slice = slice.push_back(x);
} else {
slice = slice.push_back(x);
}
slice
}

// Test mutating a slice inside of a loop in an if statement
unconstrained fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] {
let mut slice = [0; 2];
if x != y {
for i in 0..5 {
slice = slice.push_back(i);
}
} else {
slice = slice.push_back(x);
}
slice
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ unconstrained fn main(x : Field) -> pub [u8; 31] {
// The result of this byte array will be little-endian
let byte_array = x.to_le_bytes(31);
assert(byte_array.len() == 31);

let mut bytes = [0; 31];
for i in 0..31 {
bytes[i] = byte_array[i];
Expand Down
79 changes: 76 additions & 3 deletions crates/nargo_cli/tests/execution_success/slices/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use dep::std::slice;
use dep::std;
fn main(x : Field, y : pub Field) {
/// TODO(#1889): Using slices in if statements where the condition is a witness
/// is not yet supported

let mut slice = [0; 2];
assert(slice[0] == 0);
assert(slice[0] != 1);
Expand Down Expand Up @@ -49,6 +46,8 @@ fn main(x : Field, y : pub Field) {
assert(append[4] == 5);

regression_2083();
// The parameters to this function must come from witness values (inputs to main)
regression_merge_slices(x, y);
}

// Ensure that slices of struct/tuple values work.
Expand Down Expand Up @@ -83,3 +82,77 @@ fn regression_2083() {
assert(x.0 == 5);
assert(x.1 == 6);
}

// The parameters to this function must come from witness values (inputs to main)
fn regression_merge_slices(x: Field, y: Field) {
merge_slices_if(x, y);
merge_slices_else(x);
}

fn merge_slices_if(x: Field, y: Field) {
let slice = merge_slices_return(x, y);
assert(slice[2] == 10);
assert(slice.len() == 3);

let slice = merge_slices_mutate(x, y);
assert(slice[3] == 5);
assert(slice.len() == 4);

let slice = merge_slices_mutate_in_loop(x, y);
assert(slice[6] == 4);
assert(slice.len() == 7);
}

fn merge_slices_else(x: Field) {
let slice = merge_slices_return(x, 5);
assert(slice[0] == 0);
assert(slice[1] == 0);
assert(slice.len() == 2);

let slice = merge_slices_mutate(x, 5);
assert(slice[2] == 5);
assert(slice.len() == 3);

let slice = merge_slices_mutate_in_loop(x, 5);
assert(slice[2] == 5);
assert(slice.len() == 3);
}

// Test returning a merged slice without a mutation
fn merge_slices_return(x: Field, y: Field) -> [Field] {
let slice = [0; 2];
if x != y {
if x != 20 {
slice.push_back(y)
} else {
slice
}
} else {
slice
}
}

// Test mutating a slice inside of an if statement
fn merge_slices_mutate(x: Field, y: Field) -> [Field] {
let mut slice = [0; 2];
if x != y {
slice = slice.push_back(y);
slice = slice.push_back(x);
} else {
slice = slice.push_back(x);
}
slice
}

// Test mutating a slice inside of a loop in an if statement
fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] {
let mut slice = [0; 2];
if x != y {
for i in 0..5 {
slice = slice.push_back(i);
}
} else {
slice = slice.push_back(x);
}
slice
}
Loading
Loading