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

chore: Remove ssa::value::Value to greatly reduce memory usage #3821

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion acvm-repo/acir/src/circuit/black_box_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use strum_macros::EnumIter;

#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
#[cfg_attr(test, derive(EnumIter))]
pub enum BlackBoxFunc {
/// Bitwise AND.
Expand Down
4 changes: 3 additions & 1 deletion compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) fn optimize_into_acir(
.run_pass(Ssa::defunctionalize, "After Defunctionalization:")
.run_pass(Ssa::inline_functions, "After Inlining:")
// Run mem2reg with the CFG separated into blocks
.run_pass(Ssa::mem2reg, "After Mem2Reg:")
// .run_pass(Ssa::mem2reg, "After Mem2Reg:")
.try_run_pass(Ssa::evaluate_assert_constant, "After Assert Constant:")?
.try_run_pass(Ssa::unroll_loops, "After Unrolling:")?
.run_pass(Ssa::simplify_cfg, "After Simplifying:")
Expand Down Expand Up @@ -179,6 +179,7 @@ impl SsaBuilder {

/// Runs the given SSA pass and prints the SSA afterward if `print_ssa_passes` is true.
fn run_pass(mut self, pass: fn(Ssa) -> Ssa, msg: &str) -> Self {
println!("On pass {msg}");
self.ssa = pass(self.ssa);
self.print(msg)
}
Expand All @@ -189,6 +190,7 @@ impl SsaBuilder {
pass: fn(Ssa) -> Result<Ssa, RuntimeError>,
msg: &str,
) -> Result<Self, RuntimeError> {
println!("On pass {msg}");
self.ssa = pass(self.ssa)?;
Ok(self.print(msg))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ impl<'a> From<&'a SsaType> for AcirType {
/// `Variables`(AcirVar) and types such as `Expression` and `Witness`
/// which are placed into ACIR.
pub(crate) struct AcirContext {
/// Two-way map that links `AcirVar` to `AcirVarData`.
///
/// The vars object is an instance of the `TwoWayMap`, which provides a bidirectional mapping between `AcirVar` and `AcirVarData`.
/// Map that links `AcirVar` to `AcirVarData`.
vars: HashMap<AcirVar, AcirVarData>,

constant_witnesses: HashMap<FieldElement, Witness>,
Expand Down
50 changes: 24 additions & 26 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, rc::Rc};
use std::rc::Rc;

use acvm::FieldElement;
use noirc_errors::Location;
Expand All @@ -8,7 +8,7 @@ use crate::ssa::ir::{
function::{Function, FunctionId},
instruction::{Binary, BinaryOp, Instruction, TerminatorInstruction},
types::Type,
value::{Value, ValueId},
value::ValueId,
};

use super::{
Expand Down Expand Up @@ -137,7 +137,10 @@ impl FunctionBuilder {
}

/// Returns the parameters of the given block in the current function.
pub(crate) fn block_parameters(&self, block: BasicBlockId) -> &[ValueId] {
pub(crate) fn block_parameters(
&self,
block: BasicBlockId,
) -> impl ExactSizeIterator<Item = ValueId> {
self.current_function.dfg.block_parameters(block)
}

Expand Down Expand Up @@ -259,7 +262,7 @@ impl FunctionBuilder {
func: ValueId,
arguments: Vec<ValueId>,
result_types: Vec<Type>,
) -> Cow<[ValueId]> {
) -> Vec<ValueId> {
self.insert_instruction(Instruction::Call { func, arguments }, Some(result_types)).results()
}

Expand Down Expand Up @@ -438,7 +441,7 @@ impl FunctionBuilder {
/// Returns a ValueId pointing to the given oracle/foreign function or imports the oracle
/// into the current function if it was not already, and returns that ID.
pub(crate) fn import_foreign_function(&mut self, function: &str) -> ValueId {
self.current_function.dfg.import_foreign_function(function)
self.current_function.dfg.import_foreign_function(function.to_owned())
}

/// Retrieve a value reference to the given intrinsic operation.
Expand All @@ -453,21 +456,13 @@ impl FunctionBuilder {
}

pub(crate) fn get_intrinsic_from_value(&mut self, value: ValueId) -> Option<Intrinsic> {
match self.current_function.dfg[value] {
Value::Intrinsic(intrinsic) => Some(intrinsic),
match value {
ValueId::Intrinsic(intrinsic) => Some(intrinsic),
_ => None,
}
}
}

impl std::ops::Index<ValueId> for FunctionBuilder {
type Output = Value;

fn index(&self, id: ValueId) -> &Self::Output {
&self.current_function.dfg[id]
}
}

impl std::ops::Index<InstructionId> for FunctionBuilder {
type Output = Instruction;

Expand Down Expand Up @@ -495,7 +490,6 @@ mod tests {
instruction::{Endian, Intrinsic},
map::Id,
types::Type,
value::Value,
};

use super::FunctionBuilder;
Expand All @@ -514,19 +508,23 @@ mod tests {
let input = builder.numeric_constant(FieldElement::from(7_u128), Type::field());
let length = builder.numeric_constant(FieldElement::from(8_u128), Type::field());
let result_types = vec![Type::Array(Rc::new(vec![Type::bool()]), 8)];
let call_results =
builder.insert_call(to_bits_id, vec![input, length], result_types).into_owned();
let call_results = builder.insert_call(to_bits_id, vec![input, length], result_types);

let slice_len = builder
.current_function
.dfg
.get_numeric_constant(call_results[0])
.expect("Expected slice length to be a known constant");

let slice_len = match &builder.current_function.dfg[call_results[0]] {
Value::NumericConstant { constant, .. } => *constant,
_ => panic!(),
};
assert_eq!(slice_len, FieldElement::from(8_u128));

let slice = match &builder.current_function.dfg[call_results[1]] {
Value::Array { array, .. } => array,
_ => panic!(),
};
let slice = builder
.current_function
.dfg
.get_array_constant(call_results[1])
.expect("Expected slice elements to be known")
.0;

assert_eq!(slice[0], one);
assert_eq!(slice[1], one);
assert_eq!(slice[2], one);
Expand Down
33 changes: 16 additions & 17 deletions compiler/noirc_evaluator/src/ssa/ir/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{
dfg::CallStack,
instruction::{InstructionId, TerminatorInstruction},
map::Id,
types::Type,
value::ValueId,
};

Expand All @@ -14,7 +15,7 @@ use super::{
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub(crate) struct BasicBlock {
/// Parameters to the basic block.
parameters: Vec<ValueId>,
parameter_types: Vec<Type>,

/// Instructions in the basic block.
instructions: Vec<InstructionId>,
Expand All @@ -33,30 +34,28 @@ impl BasicBlock {
/// Create a new BasicBlock with the given parameters.
/// Parameters can also be added later via BasicBlock::add_parameter
pub(crate) fn new() -> Self {
Self { parameters: Vec::new(), instructions: Vec::new(), terminator: None }
Self { parameter_types: Vec::new(), instructions: Vec::new(), terminator: None }
}

/// Returns the parameters of this block
pub(crate) fn parameters(&self) -> &[ValueId] {
&self.parameters
/// The number of parameters this basic block has
pub(crate) fn parameter_count(&self) -> u32 {
self.parameter_types.len() as u32
}

/// Removes all the parameters of this block
pub(crate) fn take_parameters(&mut self) -> Vec<ValueId> {
std::mem::take(&mut self.parameters)
/// Adds a parameter to this BasicBlock.
pub(crate) fn add_parameter(&mut self, parameter_type: Type) {
self.parameter_types.push(parameter_type);
}

/// Adds a parameter to this BasicBlock.
/// Expects that the ValueId given should refer to a Value::Param
/// instance with its position equal to self.parameters.len().
pub(crate) fn add_parameter(&mut self, parameter: ValueId) {
self.parameters.push(parameter);
/// Returns the types of this block's parameters
pub(crate) fn get_parameter_types(&self) -> &[Type] {
&self.parameter_types
}

/// Replace this block's current parameters with that of the given Vec.
/// This does not perform any checks that any previous parameters were unused.
pub(crate) fn set_parameters(&mut self, parameters: Vec<ValueId>) {
self.parameters = parameters;
/// Replace this block's current parameter types with that of the given Vec.
/// The given Vec is allowed to be a different number of parameters than the block originally had.
pub(crate) fn set_parameter_types(&mut self, parameter_types: Vec<Type>) {
self.parameter_types = parameter_types;
}

/// Insert an instruction at the end of this block
Expand Down
Loading