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: Reduce memory consumption by storing array length as u32 during SSA #6606

Merged
merged 5 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 compiler/noirc_evaluator/src/acir/acir_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl<'a> From<&'a SsaType> for AcirType {
SsaType::Numeric(numeric_type) => AcirType::NumericType(*numeric_type),
SsaType::Array(elements, size) => {
let elements = elements.iter().map(|e| e.into()).collect();
AcirType::Array(elements, *size)
AcirType::Array(elements, *size as usize)
}
_ => unreachable!("The type {value} cannot be represented in ACIR"),
}
Expand Down
27 changes: 12 additions & 15 deletions compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ impl<'a> Context<'a> {
AcirValue::Array(_) => {
let block_id = self.block_id(param_id);
let len = if matches!(typ, Type::Array(_, _)) {
typ.flattened_size()
typ.flattened_size() as usize
} else {
return Err(InternalError::Unexpected {
expected: "Block params should be an array".to_owned(),
Expand Down Expand Up @@ -816,7 +816,9 @@ impl<'a> Context<'a> {
let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg));
let output_count = result_ids
.iter()
.map(|result_id| dfg.type_of_value(*result_id).flattened_size())
.map(|result_id| {
dfg.type_of_value(*result_id).flattened_size() as usize
})
.sum();

let Some(acir_function_id) =
Expand Down Expand Up @@ -948,7 +950,7 @@ impl<'a> Context<'a> {
let block_id = self.block_id(&array_id);
let array_typ = dfg.type_of_value(array_id);
let len = if matches!(array_typ, Type::Array(_, _)) {
array_typ.flattened_size()
array_typ.flattened_size() as usize
} else {
Self::flattened_value_size(&output)
};
Expand Down Expand Up @@ -1444,7 +1446,7 @@ impl<'a> Context<'a> {
// a separate SSA value and restrictions on slice indices should be generated elsewhere in the SSA.
let array_typ = dfg.type_of_value(array);
let array_len = if !array_typ.contains_slice_element() {
array_typ.flattened_size()
array_typ.flattened_size() as usize
} else {
self.flattened_slice_size(array, dfg)
};
Expand Down Expand Up @@ -1539,7 +1541,7 @@ impl<'a> Context<'a> {
let value = self.convert_value(array, dfg);
let array_typ = dfg.type_of_value(array);
let len = if !array_typ.contains_slice_element() {
array_typ.flattened_size()
array_typ.flattened_size() as usize
} else {
self.flattened_slice_size(array, dfg)
};
Expand Down Expand Up @@ -1810,7 +1812,7 @@ impl<'a> Context<'a> {

return_values
.iter()
.fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size())
.fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size() as usize)
}

/// Converts an SSA terminator's return values into their ACIR representations
Expand Down Expand Up @@ -2155,7 +2157,7 @@ impl<'a> Context<'a> {
let inputs = vecmap(&arguments_no_slice_len, |arg| self.convert_value(*arg, dfg));

let output_count = result_ids.iter().fold(0usize, |sum, result_id| {
sum + dfg.try_get_array_length(*result_id).unwrap_or(1)
sum + dfg.try_get_array_length(*result_id).unwrap_or(1) as usize
});

let vars = self.acir_context.black_box_function(black_box, inputs, output_count)?;
Expand All @@ -2179,7 +2181,7 @@ impl<'a> Context<'a> {
endian,
field,
radix,
array_length as u32,
array_length,
result_type[0].clone().into(),
)
.map(|array| vec![array])
Expand All @@ -2193,12 +2195,7 @@ impl<'a> Context<'a> {
};

self.acir_context
.bit_decompose(
endian,
field,
array_length as u32,
result_type[0].clone().into(),
)
.bit_decompose(endian, field, array_length, result_type[0].clone().into())
.map(|array| vec![array])
}
Intrinsic::ArrayLen => {
Expand All @@ -2219,7 +2216,7 @@ impl<'a> Context<'a> {
let acir_value = self.convert_value(slice_contents, dfg);

let array_len = if !slice_typ.contains_slice_element() {
slice_typ.flattened_size()
slice_typ.flattened_size() as usize
} else {
self.flattened_slice_size(slice_contents, dfg)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ impl<'block> BrilligBlock<'block> {
Type::Array(_, nested_size) => {
let inner_array = BrilligArray {
pointer: self.brillig_context.allocate_register(),
size: *nested_size,
size: *nested_size as usize,
};
self.allocate_foreign_call_result_array(element_type, inner_array);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ pub(crate) fn allocate_value<F, Registers: RegisterAllocator>(
}
Type::Array(item_typ, elem_count) => BrilligVariable::BrilligArray(BrilligArray {
pointer: brillig_context.allocate_register(),
size: compute_array_length(&item_typ, elem_count),
size: compute_array_length(&item_typ, elem_count as usize),
}),
Type::Slice(_) => BrilligVariable::BrilligVector(BrilligVector {
pointer: brillig_context.allocate_register(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl FunctionContext {
vecmap(item_type.iter(), |item_typ| {
FunctionContext::ssa_type_to_parameter(item_typ)
}),
*size,
*size as usize,
),
Type::Slice(_) => {
panic!("ICE: Slice parameters cannot be derived from type information")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub(crate) fn type_to_heap_value_type(typ: &Type) -> HeapValueType {
),
Type::Array(elem_type, size) => HeapValueType::Array {
value_types: elem_type.as_ref().iter().map(type_to_heap_value_type).collect(),
size: typ.element_size() * size,
size: typ.element_size() * *size as usize,
},
Type::Slice(elem_type) => HeapValueType::Vector {
value_types: elem_type.as_ref().iter().map(type_to_heap_value_type).collect(),
Expand Down
8 changes: 5 additions & 3 deletions compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl FunctionBuilder {
for value in values {
self.add_to_data_bus(*value, &mut databus);
}
let len = databus.values.len();
let len = databus.values.len() as u32;

let array = (len > 0 && matches!(self.current_function.runtime(), RuntimeType::Acir(_)))
.then(|| {
Expand Down Expand Up @@ -223,9 +223,11 @@ impl FunctionBuilder {
ssa_params: &[ValueId],
mut flattened_params_databus_visibility: Vec<DatabusVisibility>,
) -> Vec<DatabusVisibility> {
let ssa_param_sizes: Vec<_> = ssa_params
let ssa_param_sizes: Vec<usize> = ssa_params
.iter()
.map(|ssa_param| self.current_function.dfg[*ssa_param].get_type().flattened_size())
.map(|ssa_param| {
self.current_function.dfg[*ssa_param].get_type().flattened_size() as usize
})
.collect();

let mut is_ssa_params_databus = Vec::with_capacity(ssa_params.len());
Expand Down
39 changes: 15 additions & 24 deletions compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,20 @@ impl DataFlowGraph {
instruction_id: InstructionId,
ctrl_typevars: Option<Vec<Type>>,
) {
self.results.insert(instruction_id, Default::default());

// Get all of the types that this instruction produces
// and append them as results.
for typ in self.instruction_result_types(instruction_id, ctrl_typevars) {
self.append_result(instruction_id, typ);
}
let results = self
.instruction_result_types(instruction_id, ctrl_typevars)
.into_iter()
.enumerate()
.map(|(position, typ)| {
self.values.insert(Value::Instruction {
typ,
position,
instruction: instruction_id,
})
})
.collect();
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved

self.results.insert(instruction_id, results);
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
}

/// Return the result types of this instruction.
Expand Down Expand Up @@ -370,22 +377,6 @@ impl DataFlowGraph {
matches!(self.values[value].get_type(), Type::Reference(_))
}

/// Appends a result type to the instruction.
pub(crate) fn append_result(&mut self, instruction_id: InstructionId, typ: Type) -> ValueId {
let results = self.results.get_mut(&instruction_id).unwrap();
let expected_res_position = results.len();

let value_id = self.values.insert(Value::Instruction {
typ,
position: expected_res_position,
instruction: instruction_id,
});

// Add value to the list of results for this instruction
results.push(value_id);
value_id
}

/// Replaces an instruction result with a fresh id.
pub(crate) fn replace_result(
&mut self,
Expand Down Expand Up @@ -463,7 +454,7 @@ impl DataFlowGraph {

/// If this value is an array, return the length of the array as indicated by its type.
/// Otherwise, return None.
pub(crate) fn try_get_array_length(&self, value: ValueId) -> Option<usize> {
pub(crate) fn try_get_array_length(&self, value: ValueId) -> Option<u32> {
match self.type_of_value(value) {
Type::Array(_, length) => Some(length),
_ => None,
Expand Down
14 changes: 7 additions & 7 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub(super) fn simplify_call(
{
let field = constant_args[0];
let limb_count = if let Some(Type::Array(_, array_len)) = return_type {
array_len as u32
array_len
} else {
unreachable!("ICE: Intrinsic::ToRadix return type must be array")
};
Expand All @@ -73,7 +73,7 @@ pub(super) fn simplify_call(
let field = constant_args[0];
let radix = constant_args[1].to_u128() as u32;
let limb_count = if let Some(Type::Array(_, array_len)) = return_type {
array_len as u32
array_len
} else {
unreachable!("ICE: Intrinsic::ToRadix return type must be array")
};
Expand Down Expand Up @@ -353,7 +353,7 @@ pub(super) fn simplify_call(
Intrinsic::IsUnconstrained => SimplifyResult::None,
Intrinsic::DerivePedersenGenerators => {
if let Some(Type::Array(_, len)) = ctrl_typevars.unwrap().first() {
simplify_derive_generators(dfg, arguments, *len as u32, block, call_stack)
simplify_derive_generators(dfg, arguments, *len, block, call_stack)
} else {
unreachable!("Derive Pedersen Generators must return an array");
}
Expand Down Expand Up @@ -420,8 +420,8 @@ fn simplify_slice_push_back(
for elem in &arguments[2..] {
slice.push_back(*elem);
}
let slice_size = slice.len();
let element_size = element_type.element_size();
let slice_size = slice.len() as u32;
let element_size = element_type.element_size() as u32;
let new_slice = make_array(dfg, slice, element_type, block, &call_stack);

let set_last_slice_value_instr = Instruction::ArraySet {
Expand Down Expand Up @@ -610,7 +610,7 @@ fn make_constant_array(
let result_constants: im::Vector<_> =
results.map(|element| dfg.make_constant(element, typ.clone())).collect();

let typ = Type::Array(Arc::new(vec![typ]), result_constants.len());
let typ = Type::Array(Arc::new(vec![typ]), result_constants.len() as u32);
make_array(dfg, result_constants, typ, block, call_stack)
}

Expand Down Expand Up @@ -805,7 +805,7 @@ fn simplify_derive_generators(
results.push(dfg.make_constant(y, Type::field()));
results.push(is_infinite);
}
let len = results.len();
let len = results.len() as u32;
let typ =
Type::Array(vec![Type::field(), Type::field(), Type::unsigned(1)].into(), len / 3);
let result = make_array(dfg, results.into(), typ, block, call_stack);
Expand Down
6 changes: 3 additions & 3 deletions compiler/noirc_evaluator/src/ssa/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(crate) enum Type {
Reference(Arc<Type>),

/// An immutable array value with the given element type and length
Array(Arc<CompositeType>, usize),
Array(Arc<CompositeType>, u32),

/// An immutable slice value with a given element type
Slice(Arc<CompositeType>),
Expand Down Expand Up @@ -111,7 +111,7 @@ impl Type {
}

/// Creates the str<N> type, of the given length N
pub(crate) fn str(length: usize) -> Type {
pub(crate) fn str(length: u32) -> Type {
Type::Array(Arc::new(vec![Type::char()]), length)
}

Expand Down Expand Up @@ -161,7 +161,7 @@ impl Type {
}

/// Returns the flattened size of a Type
pub(crate) fn flattened_size(&self) -> usize {
pub(crate) fn flattened_size(&self) -> u32 {
match self {
Type::Array(elements, len) => {
elements.iter().fold(0, |sum, elem| sum + (elem.flattened_size() * len))
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Function {
}
}

fn known_slice_lengths(func: &Function) -> HashMap<InstructionId, usize> {
fn known_slice_lengths(func: &Function) -> HashMap<InstructionId, u32> {
let mut known_slice_lengths = HashMap::default();
for block_id in func.reachable_blocks() {
let block = &func.dfg[block_id];
Expand Down Expand Up @@ -61,7 +61,7 @@ fn known_slice_lengths(func: &Function) -> HashMap<InstructionId, usize> {

fn replace_known_slice_lengths(
func: &mut Function,
known_slice_lengths: HashMap<InstructionId, usize>,
known_slice_lengths: HashMap<InstructionId, u32>,
) {
known_slice_lengths.into_iter().for_each(|(instruction_id, known_length)| {
let call_returns = func.dfg.instruction_results(instruction_id);
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ pub(crate) fn type_to_brillig_parameter(typ: &Type) -> Option<BrilligParameter>
for item_typ in item_type.iter() {
parameters.push(type_to_brillig_parameter(item_typ)?);
}
Some(BrilligParameter::Array(parameters, *size))
Some(BrilligParameter::Array(parameters, *size as usize))
}
_ => None,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl<'a> SliceCapacityTracker<'a> {
pub(crate) fn collect_slice_information(
&self,
instruction: &Instruction,
slice_sizes: &mut HashMap<ValueId, usize>,
slice_sizes: &mut HashMap<ValueId, u32>,
results: &[ValueId],
) {
match instruction {
Expand Down Expand Up @@ -106,13 +106,12 @@ impl<'a> SliceCapacityTracker<'a> {
Intrinsic::ToBits(_) => {
// Compiler sanity check
assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_)));
slice_sizes.insert(result_slice, FieldElement::max_num_bits() as usize);
slice_sizes.insert(result_slice, FieldElement::max_num_bits());
}
Intrinsic::ToRadix(_) => {
// Compiler sanity check
assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_)));
slice_sizes
.insert(result_slice, FieldElement::max_num_bytes() as usize);
slice_sizes.insert(result_slice, FieldElement::max_num_bytes());
}
Intrinsic::AsSlice => {
let array_size = self
Expand Down Expand Up @@ -157,15 +156,15 @@ impl<'a> SliceCapacityTracker<'a> {
pub(crate) fn compute_slice_capacity(
&self,
array_id: ValueId,
slice_sizes: &mut HashMap<ValueId, usize>,
slice_sizes: &mut HashMap<ValueId, u32>,
) {
if let Some((array, typ)) = self.dfg.get_array_constant(array_id) {
// Compiler sanity check
assert!(!typ.is_nested_slice(), "ICE: Nested slices are not allowed and should not have reached the flattening pass of SSA");
if let Type::Slice(_) = typ {
let element_size = typ.element_size();
let len = array.len() / element_size;
slice_sizes.insert(array_id, len);
slice_sizes.insert(array_id, len as u32);
}
}
}
Expand Down
Loading
Loading