Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 37 additions & 27 deletions compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ impl Ssa {
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) fn remove_enable_side_effects(mut self) -> Ssa {
for function in self.functions.values_mut() {
#[cfg(debug_assertions)]
remove_enable_side_effects_pre_check(function);

function.remove_enable_side_effects();
}
self
Expand All @@ -48,10 +51,6 @@ impl Function {
return;
}

// Check the precondition that this optimization runs when there's only one block
let block = self.entry_block();
assert_eq!(self.dfg[block].successors().count(), 0);

let one = self.dfg.make_constant(FieldElement::one(), NumericType::bool());
let mut active_condition = one;
let mut last_side_effects_enabled_instruction = None;
Expand Down Expand Up @@ -87,6 +86,7 @@ impl Function {

if condition_is_one {
last_side_effects_enabled_instruction = None;
context.insert_current_instruction();
} else {
last_side_effects_enabled_instruction = Some(context.instruction_id);
context.remove_current_instruction();
Expand All @@ -107,6 +107,16 @@ impl Function {
}
}

/// Check that the CFG has been flattened.
#[cfg(debug_assertions)]
fn remove_enable_side_effects_pre_check(function: &Function) {
if !function.runtime().is_acir() {
return;
}
let block = function.entry_block();
assert_eq!(function.dfg[block].successors().count(), 0);
}

#[cfg(test)]
mod test {
use crate::{
Expand Down Expand Up @@ -252,13 +262,13 @@ mod test {
fn remove_enable_side_effects_for_slice_push_back() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4

// this instruction should be removed
enable_side_effects v1
enable_side_effects v1

v13, v14 = call slice_push_back(u32 3, v9, Field 5) -> (u32, [Field])
return
Expand All @@ -268,11 +278,11 @@ mod test {
let ssa = ssa.remove_enable_side_effects();
assert_ssa_snapshot!(ssa, @r"
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v13, v14 = call slice_push_back(u32 3, v9, Field 5) -> (u32, [Field])
b0(v0: [u32; 3], v1: u1, v2: u32):
v4 = array_get v0, index u32 0 -> u32
v8 = make_array [Field 1, Field 2, Field 3] : [Field]
v10 = array_set v8, index v2, value Field 4
v14, v15 = call slice_push_back(u32 3, v10, Field 5) -> (u32, [Field])
return
}
");
Expand All @@ -282,10 +292,10 @@ mod test {
fn remove_enable_side_effects_for_slice_push_front() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4

// this instruction should be removed
enable_side_effects v1
Expand All @@ -298,11 +308,11 @@ mod test {
let ssa = ssa.remove_enable_side_effects();
assert_ssa_snapshot!(ssa, @r"
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v13, v14 = call slice_push_front(u32 3, v9, Field 5) -> (u32, [Field])
b0(v0: [u32; 3], v1: u1, v2: u32):
v4 = array_get v0, index u32 0 -> u32
v8 = make_array [Field 1, Field 2, Field 3] : [Field]
v10 = array_set v8, index v2, value Field 4
v14, v15 = call slice_push_front(u32 3, v10, Field 5) -> (u32, [Field])
return
}
");
Expand All @@ -312,10 +322,10 @@ mod test {
fn keep_enable_side_effects_for_slice_pop_back() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4
enable_side_effects v1
v13, v14, v15 = call slice_pop_back(u32 3, v9) -> (u32, [Field], Field)
return
Expand All @@ -328,10 +338,10 @@ mod test {
fn keep_enable_side_effects_for_slice_pop_front() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4
enable_side_effects v1
v13, v14, v15 = call slice_pop_front(u32 3, v9) -> (Field, u32, [Field])
return
Expand All @@ -344,10 +354,10 @@ mod test {
fn keep_enable_side_effects_for_slice_insert() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4
enable_side_effects v1
v13, v14 = call slice_insert(u32 3, v9, u32 1, Field 5) -> (u32, [Field])
return
Expand All @@ -360,10 +370,10 @@ mod test {
fn keep_enable_side_effects_for_slice_remove() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u1):
b0(v0: [u32; 3], v1: u1, v2: u32):
v3 = array_get v0, index u32 0 -> u32
v7 = make_array [Field 1, Field 2, Field 3] : [Field]
v9 = array_set v7, index v0, value Field 4
v9 = array_set v7, index v2, value Field 4
enable_side_effects v1
v13, v14, v15 = call slice_remove(u32 3, v9, u32 1) -> (u32, [Field], Field)
return
Expand Down
35 changes: 32 additions & 3 deletions compiler/noirc_evaluator/src/ssa/validation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,16 @@
panic!("Cannot use `{operator}` with field elements");
};
}
Instruction::ArrayGet { index, .. } | Instruction::ArraySet { index, .. } => {
Instruction::ArrayGet { array, index, .. }
| Instruction::ArraySet { array, index, .. } => {
let index_type = dfg.type_of_value(*index);
if !matches!(index_type, Type::Numeric(NumericType::Unsigned { bit_size: 32 })) {
panic!("ArrayGet/ArraySet index must be u32");
}
let array_type = dfg.type_of_value(*array);
if !array_type.contains_an_array() {
panic!("ArrayGet/ArraySet must operate on an array; got {array_type}");
}
}
Instruction::Call { func, arguments } => {
self.type_check_call(instruction, func, arguments);
Expand Down Expand Up @@ -671,19 +676,19 @@
// signature: [u8; 64],
// message_hash: [u8; N],
// ) -> bool
assert_arguments_length(arguments, 4, "ecdsa_secp_256");

Check warning on line 679 in compiler/noirc_evaluator/src/ssa/validation/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (secp)

let public_key_x = arguments[0];
let public_key_x_type = dfg.type_of_value(public_key_x);
let public_key_x_length =
assert_u8_array(&public_key_x_type, "ecdsa_secp256 public_key_x");

Check warning on line 684 in compiler/noirc_evaluator/src/ssa/validation/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (secp)
assert_array_length(public_key_x_length, 32, "ecdsa_secp256 public_key_x");

Check warning on line 685 in compiler/noirc_evaluator/src/ssa/validation/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (secp)

let public_key_y = arguments[1];
let public_key_y_type = dfg.type_of_value(public_key_y);
let public_key_y_length =
assert_u8_array(&public_key_y_type, "ecdsa_secp256 public_key_y");

Check warning on line 690 in compiler/noirc_evaluator/src/ssa/validation/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (secp)
assert_array_length(public_key_y_length, 32, "ecdsa_secp256 public_key_y");

Check warning on line 691 in compiler/noirc_evaluator/src/ssa/validation/mod.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (secp)

let signature = arguments[2];
let signature_type = dfg.type_of_value(signature);
Expand Down Expand Up @@ -1606,7 +1611,7 @@
return

}

";
let _ = Ssa::from_str(src).unwrap();
}
Expand All @@ -1617,7 +1622,7 @@
let src = "
acir(inline) fn main f0 {
b0():
v3 = make_array [Field 1, Field 2, Field 3] : [Field]
v3 = make_array [Field 1, Field 2, Field 3] : [Field]
v4 = call f1(v3) -> u32
return v4
}
Expand Down Expand Up @@ -1658,4 +1663,28 @@
";
let _ = Ssa::from_str(src).unwrap();
}

#[test]
#[should_panic(expected = "ArrayGet/ArraySet index must be u32")]
fn array_get_wrong_index_type() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: [u8; 3], v1: u64):
v2 = array_get v0, index v1 -> u32
return v2
}";
let _ = Ssa::from_str(src).unwrap();
}

#[test]
#[should_panic(expected = "ArrayGet/ArraySet must operate on an array")]
fn array_get_wrong_array_type() {
let src = "
acir(inline) predicate_pure fn main f0 {
b0(v0: u32, v1: u32):
v2 = array_get v0, index v1 -> u32
return v2
}";
let _ = Ssa::from_str(src).unwrap();
}
}
Loading