Skip to content

Commit

Permalink
Merge branch 'master' into mv/6674-hack
Browse files Browse the repository at this point in the history
  • Loading branch information
vezenovm authored Dec 5, 2024
2 parents 11bef2f + 31640e9 commit 4d294bb
Show file tree
Hide file tree
Showing 27 changed files with 519 additions and 363 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
- name: Run release-please
id: release
uses: google-github-actions/release-please-action@v4
uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.NOIR_RELEASES_TOKEN }}

Expand Down
62 changes: 35 additions & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ codespan-reporting = "0.11.1"
criterion = "0.5.0"
# Note that using the "frame-pointer" feature breaks framegraphs on linux
# https://github.com/tikv/pprof-rs/pull/172
pprof = { version = "0.13", features = ["flamegraph", "criterion"] }
pprof = { version = "0.14", features = ["flamegraph", "criterion"] }

cfg-if = "1.0.0"
dirs = "4"
Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/bn254_blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ num-bigint.workspace = true
[dev-dependencies]
ark-std.workspace = true
criterion = "0.5.0"
pprof = { version = "0.12", features = [
pprof = { version = "0.14", features = [
"flamegraph",
"frame-pointer",
"criterion",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub(super) fn compile_array_copy_procedure<F: AcirField + DebugToString>(
BRILLIG_MEMORY_ADDRESSING_BIT_SIZE,
1_usize.into(),
);
// Decrease the original ref count now that this copy is no longer pointing to it
ctx.codegen_usize_op(rc.address, rc.address, BrilligBinaryOp::Sub, 1);
}
});
}
24 changes: 17 additions & 7 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,29 +441,38 @@ impl FunctionBuilder {
/// Insert instructions to increment the reference count of any array(s) stored
/// within the given value. If the given value is not an array and does not contain
/// any arrays, this does nothing.
pub(crate) fn increment_array_reference_count(&mut self, value: ValueId) {
self.update_array_reference_count(value, true);
///
/// Returns whether a reference count instruction was issued.
pub(crate) fn increment_array_reference_count(&mut self, value: ValueId) -> bool {
self.update_array_reference_count(value, true)
}

/// Insert instructions to decrement the reference count of any array(s) stored
/// within the given value. If the given value is not an array and does not contain
/// any arrays, this does nothing.
pub(crate) fn decrement_array_reference_count(&mut self, value: ValueId) {
self.update_array_reference_count(value, false);
///
/// Returns whether a reference count instruction was issued.
pub(crate) fn decrement_array_reference_count(&mut self, value: ValueId) -> bool {
self.update_array_reference_count(value, false)
}

/// Increment or decrement the given value's reference count if it is an array.
/// If it is not an array, this does nothing. Note that inc_rc and dec_rc instructions
/// are ignored outside of unconstrained code.
fn update_array_reference_count(&mut self, value: ValueId, increment: bool) {
///
/// Returns whether a reference count instruction was issued.
fn update_array_reference_count(&mut self, value: ValueId, increment: bool) -> bool {
match self.type_of_value(value) {
Type::Numeric(_) => (),
Type::Function => (),
Type::Numeric(_) => false,
Type::Function => false,
Type::Reference(element) => {
if element.contains_an_array() {
let reference = value;
let value = self.insert_load(reference, element.as_ref().clone());
self.update_array_reference_count(value, increment);
true
} else {
false
}
}
Type::Array(..) | Type::Slice(..) => {
Expand All @@ -474,6 +483,7 @@ impl FunctionBuilder {
} else {
self.insert_dec_rc(value);
}
true
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<'f> FunctionInserter<'f> {
// another MakeArray instruction. Note that this assumes the function inserter is inserting
// in control-flow order. Otherwise we could refer to ValueIds defined later in the program.
let make_array = if let Instruction::MakeArray { elements, typ } = &instruction {
if self.array_is_constant(elements) {
if self.array_is_constant(elements) && self.function.runtime().is_acir() {
if let Some(fetched_value) = self.get_cached_array(elements, typ) {
assert_eq!(results.len(), 1);
self.values.insert(results[0], fetched_value);
Expand Down
13 changes: 8 additions & 5 deletions compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ impl Instruction {
/// conditional on whether the caller wants the predicate to be taken into account or not.
pub(crate) fn can_be_deduplicated(
&self,
dfg: &DataFlowGraph,
function: &Function,
deduplicate_with_predicate: bool,
) -> bool {
use Instruction::*;
Expand All @@ -443,7 +443,7 @@ impl Instruction {
| IncrementRc { .. }
| DecrementRc { .. } => false,

Call { func, .. } => match dfg[*func] {
Call { func, .. } => match function.dfg[*func] {
Value::Intrinsic(intrinsic) => {
intrinsic.can_be_deduplicated(deduplicate_with_predicate)
}
Expand All @@ -453,8 +453,11 @@ impl Instruction {
// We can deduplicate these instructions if we know the predicate is also the same.
Constrain(..) | RangeCheck { .. } => deduplicate_with_predicate,

// This should never be side-effectful
MakeArray { .. } => true,
// Arrays can be mutated in unconstrained code so code that handles this case must
// take care to track whether the array was possibly mutated or not before
// deduplicating. Since we don't know if the containing pass checks for this, we
// can only assume these are safe to deduplicate in constrained code.
MakeArray { .. } => function.runtime().is_acir(),

// These can have different behavior depending on the EnableSideEffectsIf context.
// Replacing them with a similar instruction potentially enables replacing an instruction
Expand All @@ -467,7 +470,7 @@ impl Instruction {
| IfElse { .. }
| ArrayGet { .. }
| ArraySet { .. } => {
deduplicate_with_predicate || !self.requires_acir_gen_predicate(dfg)
deduplicate_with_predicate || !self.requires_acir_gen_predicate(&function.dfg)
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,27 +842,27 @@ mod tests {

#[test]
fn simplify_derive_generators_has_correct_type() {
let src = "
let src = r#"
brillig(inline) fn main f0 {
b0():
v0 = make_array [u8 68, u8 69, u8 70, u8 65, u8 85, u8 76, u8 84, u8 95, u8 68, u8 79, u8 77, u8 65, u8 73, u8 78, u8 95, u8 83, u8 69, u8 80, u8 65, u8 82, u8 65, u8 84, u8 79, u8 82] : [u8; 24]
v0 = make_array b"DEFAULT_DOMAIN_SEPARATOR"
// This call was previously incorrectly simplified to something that returned `[Field; 3]`
v2 = call derive_pedersen_generators(v0, u32 0) -> [(Field, Field, u1); 1]
return v2
}
";
"#;
let ssa = Ssa::from_str(src).unwrap();

let expected = "
let expected = r#"
brillig(inline) fn main f0 {
b0():
v15 = make_array [u8 68, u8 69, u8 70, u8 65, u8 85, u8 76, u8 84, u8 95, u8 68, u8 79, u8 77, u8 65, u8 73, u8 78, u8 95, u8 83, u8 69, u8 80, u8 65, u8 82, u8 65, u8 84, u8 79, u8 82] : [u8; 24]
v15 = make_array b"DEFAULT_DOMAIN_SEPARATOR"
v19 = make_array [Field 3728882899078719075161482178784387565366481897740339799480980287259621149274, Field -9903063709032878667290627648209915537972247634463802596148419711785767431332, u1 0] : [(Field, Field, u1); 1]
return v19
}
";
"#;
assert_normalized_ssa_equals(ssa, expected);
}
}
44 changes: 44 additions & 0 deletions compiler/noirc_evaluator/src/ssa/ir/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use std::{
};

use acvm::acir::AcirField;
use im::Vector;
use iter_extended::vecmap;

use crate::ssa::ir::types::{NumericType, Type};

use super::{
basic_block::BasicBlockId,
dfg::DataFlowGraph,
Expand Down Expand Up @@ -220,6 +223,28 @@ fn display_instruction_inner(
)
}
Instruction::MakeArray { elements, typ } => {
// If the array is a byte array, we check if all the bytes are printable ascii characters
// and, if so, we print the array as a string literal (easier to understand).
// It could happen that the byte array is a random byte sequence that happens to be printable
// (it didn't come from a string literal) but this still reduces the noise in the output
// and actually represents the same value.
let (element_types, is_slice) = match typ {
Type::Array(types, _) => (types, false),
Type::Slice(types) => (types, true),
_ => panic!("Expected array or slice type for MakeArray"),
};
if element_types.len() == 1
&& element_types[0] == Type::Numeric(NumericType::Unsigned { bit_size: 8 })
{
if let Some(string) = try_byte_array_to_string(elements, function) {
if is_slice {
return writeln!(f, "make_array &b{:?}", string);
} else {
return writeln!(f, "make_array b{:?}", string);
}
}
}

write!(f, "make_array [")?;

for (i, element) in elements.iter().enumerate() {
Expand All @@ -234,6 +259,25 @@ fn display_instruction_inner(
}
}

fn try_byte_array_to_string(elements: &Vector<ValueId>, function: &Function) -> Option<String> {
let mut string = String::new();
for element in elements {
let element = function.dfg.get_numeric_constant(*element)?;
let element = element.try_to_u32()?;
if element > 0xFF {
return None;
}
let byte = element as u8;
if byte.is_ascii_alphanumeric() || byte.is_ascii_punctuation() || byte.is_ascii_whitespace()
{
string.push(byte as char);
} else {
return None;
}
}
Some(string)
}

fn result_types(function: &Function, results: &[ValueId]) -> String {
let types = vecmap(results, |result| function.dfg.type_of_value(*result).to_string());
if types.is_empty() {
Expand Down
9 changes: 9 additions & 0 deletions compiler/noirc_evaluator/src/ssa/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,15 @@ impl Type {
}
}

/// Retrieves the array or slice type within this type, or panics if there is none.
pub(crate) fn get_contained_array(&self) -> &Type {
match self {
Type::Numeric(_) | Type::Function => panic!("Expected an array type"),
Type::Array(_, _) | Type::Slice(_) => self,
Type::Reference(element) => element.get_contained_array(),
}
}

pub(crate) fn element_types(self) -> Arc<Vec<Type>> {
match self {
Type::Array(element_types, _) | Type::Slice(element_types) => element_types,
Expand Down
Loading

0 comments on commit 4d294bb

Please sign in to comment.