diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 3e36459a0d6..c9b3d0f9c6a 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1165,11 +1165,15 @@ impl<'a> Context<'a> { let index_var = self.convert_numeric_value(index, dfg)?; let index_var = self.get_flattened_index(&array_typ, array_id, index_var, dfg)?; - // predicate_index = index*predicate + (1-predicate)*offset - let offset = self.acir_context.add_constant(offset); - let sub = self.acir_context.sub_var(index_var, offset)?; - let pred = self.acir_context.mul_var(sub, self.current_side_effects_enabled_var)?; - let predicate_index = self.acir_context.add_var(pred, offset)?; + let predicate_index = if dfg.is_safe_index(index, array_id) { + index_var + } else { + // index*predicate + (1-predicate)*offset + let offset = self.acir_context.add_constant(offset); + let sub = self.acir_context.sub_var(index_var, offset)?; + let pred = self.acir_context.mul_var(sub, self.current_side_effects_enabled_var)?; + self.acir_context.add_var(pred, offset)? + }; let new_value = if let Some(store) = store_value { let store_value = self.convert_value(store, dfg); diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index f06f46d7af8..d79916a9e11 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -472,6 +472,14 @@ impl DataFlowGraph { } } + /// A constant index less than the array length is safe + pub(crate) fn is_safe_index(&self, index: ValueId, array: ValueId) -> bool { + #[allow(clippy::match_like_matches_macro)] + match (self.type_of_value(array), self.get_numeric_constant(index)) { + (Type::Array(_, len), Some(index)) if index.to_u128() < (len as u128) => true, + _ => false, + } + } /// Sets the terminator instruction for the given basic block pub(crate) fn set_block_terminator( &mut self, diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 1b3466c76fa..e5c40652706 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -396,13 +396,9 @@ impl Instruction { true } - // `ArrayGet`s which read from "known good" indices from an array don't need a predicate. Instruction::ArrayGet { array, index } => { - #[allow(clippy::match_like_matches_macro)] - match (dfg.type_of_value(*array), dfg.get_numeric_constant(*index)) { - (Type::Array(_, len), Some(index)) if index.to_u128() < (len as u128) => false, - _ => true, - } + // `ArrayGet`s which read from "known good" indices from an array should not need a predicate. + !dfg.is_safe_index(*index, *array) } Instruction::EnableSideEffects { .. } | Instruction::ArraySet { .. } => true, diff --git a/test_programs/execution_success/sha256/Prover.toml b/test_programs/execution_success/sha256/Prover.toml index c4df1b749bb..b4bf4162370 100644 --- a/test_programs/execution_success/sha256/Prover.toml +++ b/test_programs/execution_success/sha256/Prover.toml @@ -34,3 +34,5 @@ result = [ 0x73, 0x2b, ] +input = [0, 0] +toggle = false \ No newline at end of file diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr index 4f999d349f0..29bc9ac371a 100644 --- a/test_programs/execution_success/sha256/src/main.nr +++ b/test_programs/execution_success/sha256/src/main.nr @@ -10,11 +10,16 @@ // Not yet here: For R1CS, it is more about manipulating arithmetic gates to get performance // This can be done in ACIR! -fn main(x: Field, result: [u8; 32]) { +fn main(x: Field, result: [u8; 32], input: [u8; 2], toggle: bool) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field // The padding is taken care of by the program // docs:start:sha256_var let digest = std::hash::sha256_var([x as u8], 1); // docs:end:sha256_var assert(digest == result); + + // variable size + let size: Field = 1 + toggle as Field; + let var_sha = std::hash::sha256_var(input, size as u64); + assert(var_sha == std::hash::sha256_var(input, 1)); }