Skip to content

Commit

Permalink
refactor call_stack
Browse files Browse the repository at this point in the history
  • Loading branch information
guipublic committed Dec 13, 2024
1 parent 773214f commit 10cdd92
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 93 deletions.
5 changes: 3 additions & 2 deletions compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,7 @@ impl<'a> Context<'a> {
}
}

let call_stack = dfg.get_call_stack(call_stack);
let call_stack = dfg.call_stack_data.get_call_stack(call_stack);
let warnings = if has_constant_return {
vec![SsaReport::Warning(InternalWarning::ReturnConstant { call_stack })]
} else {
Expand Down Expand Up @@ -2934,7 +2934,8 @@ mod test {
// Set a call stack for testing whether `brillig_locations` in the `GeneratedAcir` was accurately set.
let mut stack = CallStack::unit(Location::dummy());
stack.push_back(Location::dummy());
let call_stack = builder.current_function.dfg.get_or_insert_locations(stack);
let call_stack =
builder.current_function.dfg.call_stack_data.get_or_insert_locations(stack);
builder.set_call_stack(call_stack);

let foo_v0 = builder.add_parameter(Type::field());
Expand Down
5 changes: 3 additions & 2 deletions compiler/noirc_evaluator/src/ssa/function_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ impl FunctionBuilder {
self.current_block = new_function.entry_block();
let old_function = std::mem::replace(&mut self.current_function, new_function);
// Copy the call stack to the new function
self.call_stack = self.current_function.dfg.get_or_insert_locations(call_stack);
self.call_stack =
self.current_function.dfg.call_stack_data.get_or_insert_locations(call_stack);
self.finished_functions.push(old_function);
}

Expand Down Expand Up @@ -199,7 +200,7 @@ impl FunctionBuilder {
}

pub(crate) fn set_location(&mut self, location: Location) -> &mut FunctionBuilder {
self.call_stack = self.current_function.dfg.add_location_to_root(location);
self.call_stack = self.current_function.dfg.call_stack_data.add_location_to_root(location);
self
}

Expand Down
96 changes: 66 additions & 30 deletions compiler/noirc_evaluator/src/ssa/ir/call_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,56 +23,92 @@ impl CallStackId {
pub(crate) fn is_root(&self) -> bool {
self.0 == 0
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct LocationNode {
pub(crate) parent: Option<CallStackId>,
pub(crate) children: Vec<CallStackId>,
pub(crate) value: Location,
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub(crate) struct CallStackHelper {
locations: Vec<LocationNode>,
}

impl CallStackHelper {
/// Construct a CallStack from a CallStackId
pub(crate) fn get_call_stack(&self, locations: &[LocationNode]) -> CallStack {
let mut call_stack = im::Vector::new();
let mut current_location = *self;
while let Some(parent) = locations[current_location.index()].parent {
call_stack.push_back(locations[current_location.index()].value);
current_location = parent;
pub(crate) fn get_call_stack(&self, mut call_stack: CallStackId) -> CallStack {
let mut result = im::Vector::new();
while let Some(parent) = self.locations[call_stack.index()].parent {
result.push_back(self.locations[call_stack.index()].value);
call_stack = parent;
}
result
}

/// Returns a new CallStackId which extends the call_stack with the provided call_stack.
pub(crate) fn extend_call_stack(
&mut self,
mut call_stack: CallStackId,
locations: &CallStack,
) -> CallStackId {
for location in locations {
call_stack = self.add_child(call_stack, *location);
}
call_stack
}

/// Adds a location to the call stack
pub(crate) fn add_child(
&self,
location: Location,
locations: &mut Vec<LocationNode>,
) -> CallStackId {
if let Some(result) = locations[self.index()]
pub(crate) fn add_child(&mut self, call_stack: CallStackId, location: Location) -> CallStackId {
if let Some(result) = self.locations[call_stack.index()]
.children
.iter()
.rev()
.take(1000)
.find(|child| locations[child.index()].value == location)
.find(|child| self.locations[child.index()].value == location)
{
return *result;
}
locations.push(LocationNode { parent: Some(*self), children: vec![], value: location });
let new_location = CallStackId::new(locations.len() - 1);
locations[self.index()].children.push(new_location);
self.locations.push(LocationNode {
parent: Some(call_stack),
children: vec![],
value: location,
});
let new_location = CallStackId::new(self.locations.len() - 1);
self.locations[call_stack.index()].children.push(new_location);
new_location
}

/// Returns a new CallStackId which extends the current one with the provided call_stack.
pub(crate) fn extend(
/// Retrieve the CallStackId corresponding to call_stack with the last 'len' locations removed.
pub(crate) fn unwind_call_stack(
&self,
call_stack: &CallStack,
locations: &mut Vec<LocationNode>,
mut call_stack: CallStackId,
mut len: usize,
) -> CallStackId {
let mut result = *self;
for location in call_stack {
result = result.add_child(*location, locations);
while len > 0 {
if let Some(parent) = self.locations[call_stack.index()].parent {
len -= 1;
call_stack = parent;
} else {
break;
}
}
result
call_stack
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct LocationNode {
pub(crate) parent: Option<CallStackId>,
pub(crate) children: Vec<CallStackId>,
pub(crate) value: Location,
pub(crate) fn add_location_to_root(&mut self, location: Location) -> CallStackId {
if self.locations.is_empty() {
self.locations.push(LocationNode { parent: None, children: vec![], value: location });
CallStackId::root()
} else {
self.add_child(CallStackId::root(), location)
}
}

/// Get (or create) a CallStackId corresponding to the given locations
pub(crate) fn get_or_insert_locations(&mut self, locations: CallStack) -> CallStackId {
self.extend_call_stack(CallStackId::root(), &locations)
}
}
59 changes: 6 additions & 53 deletions compiler/noirc_evaluator/src/ssa/ir/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::ssa::{function_builder::data_bus::DataBus, ir::instruction::SimplifyR

use super::{
basic_block::{BasicBlock, BasicBlockId},
call_stack::{CallStack, CallStackId, LocationNode},
call_stack::{CallStack, CallStackHelper, CallStackId},
function::FunctionId,
instruction::{
Instruction, InstructionId, InstructionResultType, Intrinsic, TerminatorInstruction,
Expand Down Expand Up @@ -94,7 +94,7 @@ pub(crate) struct DataFlowGraph {
#[serde(skip)]
locations: HashMap<InstructionId, CallStackId>,

location_array: Vec<LocationNode>,
pub(crate) call_stack_data: CallStackHelper,

#[serde(skip)]
pub(crate) data_bus: DataBus,
Expand Down Expand Up @@ -489,7 +489,7 @@ impl DataFlowGraph {

pub(crate) fn get_instruction_call_stack(&self, instruction: InstructionId) -> CallStack {
let call_stack = self.get_instruction_call_stack_id(instruction);
self.get_call_stack(call_stack)
self.call_stack_data.get_call_stack(call_stack)
}

pub(crate) fn get_instruction_call_stack_id(&self, instruction: InstructionId) -> CallStackId {
Expand All @@ -502,29 +502,11 @@ impl DataFlowGraph {
location: Location,
) {
let call_stack = self.locations.entry(instruction).or_default();
call_stack.add_child(location, &mut self.location_array);
*call_stack = self.call_stack_data.add_child(*call_stack, location);
}

pub(crate) fn add_location_to_root(&mut self, location: Location) -> CallStackId {
if self.location_array.is_empty() {
self.location_array.push(LocationNode {
parent: None,
children: vec![],
value: location,
});
CallStackId::root()
} else {
CallStackId::root().add_child(location, &mut self.location_array)
}
}

/// Get (or create) a CallStackId corresponding to the given locations
pub(crate) fn get_or_insert_locations(&mut self, locations: CallStack) -> CallStackId {
let mut result = CallStackId::root();
for location in locations {
result = result.add_child(location, &mut self.location_array);
}
result
pub(crate) fn get_call_stack(&self, call_stack: CallStackId) -> CallStack {
self.call_stack_data.get_call_stack(call_stack)
}

pub(crate) fn get_value_call_stack(&self, value: ValueId) -> CallStack {
Expand All @@ -543,35 +525,6 @@ impl DataFlowGraph {
}
}

pub(crate) fn get_call_stack(&self, call_stack: CallStackId) -> CallStack {
call_stack.get_call_stack(&self.location_array)
}

pub(crate) fn extend_call_stack(
&mut self,
call_stack: CallStackId,
locations: &CallStack,
) -> CallStackId {
call_stack.extend(locations, &mut self.location_array)
}

// Retrieve the CallStackId corresponding to call_stack with the last 'len' locations removed.
pub(crate) fn unwind_call_stack(
&self,
mut call_stack: CallStackId,
mut len: usize,
) -> CallStackId {
while len > 0 {
if let Some(parent) = self.location_array[call_stack.index()].parent {
len -= 1;
call_stack = parent;
} else {
break;
}
}
call_stack
}

/// True if the given ValueId refers to a (recursively) constant value
pub(crate) fn is_constant(&self, argument: ValueId) -> bool {
match &self[self.resolve(argument)] {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Function {
pub(crate) fn new(name: String, id: FunctionId) -> Self {
let mut dfg = DataFlowGraph::default();
// Adds root node for the location tree
dfg.add_location_to_root(Location::dummy());
dfg.call_stack_data.add_location_to_root(Location::dummy());
let entry_block = dfg.make_block();
Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir(InlineType::default()) }
}
Expand Down
9 changes: 8 additions & 1 deletion compiler/noirc_evaluator/src/ssa/opt/inlining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ impl<'function> PerFunctionContext<'function> {
.builder
.current_function
.dfg
.call_stack_data
.extend_call_stack(self.context.call_stack, &call_stack);

self.context.call_stack = new_call_stack;
Expand All @@ -677,6 +678,7 @@ impl<'function> PerFunctionContext<'function> {
.builder
.current_function
.dfg
.call_stack_data
.unwind_call_stack(self.context.call_stack, call_stack_len);

let new_results = InsertInstructionResult::Results(call_id, &new_results);
Expand All @@ -695,6 +697,7 @@ impl<'function> PerFunctionContext<'function> {
.builder
.current_function
.dfg
.call_stack_data
.extend_call_stack(call_stack, &source_call_stack);
let results = self.source_function.dfg.instruction_results(id);
let results = vecmap(results, |id| self.source_function.dfg.resolve(*id));
Expand Down Expand Up @@ -758,6 +761,7 @@ impl<'function> PerFunctionContext<'function> {
.builder
.current_function
.dfg
.call_stack_data
.extend_call_stack(self.context.call_stack, &call_stack);

self.context
Expand All @@ -779,6 +783,7 @@ impl<'function> PerFunctionContext<'function> {
.builder
.current_function
.dfg
.call_stack_data
.extend_call_stack(self.context.call_stack, &call_stack);

// See if the value of the condition is known, and if so only inline the reachable
Expand Down Expand Up @@ -816,12 +821,14 @@ impl<'function> PerFunctionContext<'function> {
let block_id = self.context.builder.current_block();

if self.inlining_entry {
let call_stack = self.source_function.dfg.get_call_stack(*call_stack);
let call_stack =
self.source_function.dfg.call_stack_data.get_call_stack(*call_stack);
let new_call_stack = self
.context
.builder
.current_function
.dfg
.call_stack_data
.extend_call_stack(self.context.call_stack, &call_stack);

self.context
Expand Down
6 changes: 4 additions & 2 deletions compiler/noirc_evaluator/src/ssa/opt/normalize_value_ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ impl Context {

let call_stack = old_function.dfg.get_instruction_call_stack_id(old_instruction_id);
let locations = old_function.dfg.get_call_stack(call_stack);
let new_call_stack = new_function.dfg.get_or_insert_locations(locations);
let new_call_stack =
new_function.dfg.call_stack_data.get_or_insert_locations(locations);
let old_results = old_function.dfg.instruction_results(old_instruction_id);

let ctrl_typevars = instruction
Expand Down Expand Up @@ -116,7 +117,8 @@ impl Context {
.map_values(|value| self.new_ids.map_value(new_function, old_function, value));
terminator.mutate_blocks(|old_block| self.new_ids.blocks[&old_block]);
let locations = old_function.dfg.get_call_stack(terminator.call_stack());
let new_call_stack = new_function.dfg.get_or_insert_locations(locations);
let new_call_stack =
new_function.dfg.call_stack_data.get_or_insert_locations(locations);
terminator.set_call_stack(new_call_stack);
new_function.dfg.set_block_terminator(new_block_id, terminator);
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ pub(crate) fn generate_ssa(
None,
);
}
let return_call_stack =
function_context.builder.current_function.dfg.add_location_to_root(return_location);
let return_call_stack = function_context
.builder
.current_function
.dfg
.call_stack_data
.add_location_to_root(return_location);
let return_instruction =
function_context.builder.current_function.dfg[block].unwrap_terminator_mut();

Expand Down

0 comments on commit 10cdd92

Please sign in to comment.