Skip to content
Merged
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
18 changes: 2 additions & 16 deletions compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,22 +131,8 @@ impl<'f> FunctionInserter<'f> {
new_results: &InsertInstructionResult,
) {
assert_eq!(old_results.len(), new_results.len());

match new_results {
InsertInstructionResult::SimplifiedTo(new_result) => {
values.insert(old_results[0], *new_result);
}
InsertInstructionResult::SimplifiedToMultiple(new_results) => {
for (old_result, new_result) in old_results.iter().zip(new_results) {
values.insert(*old_result, *new_result);
}
}
InsertInstructionResult::Results(_, new_results) => {
for (old_result, new_result) in old_results.iter().zip(*new_results) {
values.insert(*old_result, *new_result);
}
}
InsertInstructionResult::InstructionRemoved => (),
for i in 0..old_results.len() {
values.insert(old_results[i], new_results[i]);
}
}

Expand Down
115 changes: 34 additions & 81 deletions compiler/noirc_evaluator/src/ssa/opt/inlining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ impl Ssa {
for entry_point in inline_targets {
let function = &self.functions[&entry_point];
let inlined = function.inlined(&self, &should_inline_call)?;
assert_eq!(inlined.id(), entry_point);
new_functions.insert(entry_point, inlined);
}
self.functions = new_functions;
Expand Down Expand Up @@ -221,14 +222,7 @@ impl InlineContext {
// its parameters here. Failing to do so would cause context.translate_block() to add
// a fresh block for the entry block rather than use the existing one.
let entry_block = context.context.builder.current_function.entry_block();
let original_parameters = context.source_function.parameters();

for parameter in original_parameters {
let typ = context.source_function.dfg.type_of_value(*parameter);
let new_parameter = context.context.builder.add_block_parameter(entry_block, typ);
context.values.insert(*parameter, new_parameter);
}

context.translate_block_parameters(context.source_function.entry_block(), entry_block);
context.blocks.insert(context.source_function.entry_block(), entry_block);
context.inline_blocks(ssa, should_inline_call)?;
// translate databus values
Expand Down Expand Up @@ -384,16 +378,23 @@ impl<'function> PerFunctionContext<'function> {
// The block is not already present in the function being inlined into so we must create it.
// The block's instructions are not copied over as they will be copied later in inlining.
let new_block = self.context.builder.insert_block();
let original_parameters = self.source_function.dfg.block_parameters(source_block);
self.translate_block_parameters(source_block, new_block);
self.blocks.insert(source_block, new_block);
new_block
}

/// Copy block parameters from `source_block` into `target_block`.
fn translate_block_parameters(
&mut self,
source_block: BasicBlockId,
target_block: BasicBlockId,
) {
let original_parameters = self.source_function.dfg.block_parameters(source_block);
for parameter in original_parameters {
let typ = self.source_function.dfg.type_of_value(*parameter);
let new_parameter = self.context.builder.add_block_parameter(new_block, typ);
let new_parameter = self.context.builder.add_block_parameter(target_block, typ);
self.values.insert(*parameter, new_parameter);
}

self.blocks.insert(source_block, new_block);
new_block
}

/// Try to retrieve the function referred to by the given Id.
Expand Down Expand Up @@ -461,17 +462,9 @@ impl<'function> PerFunctionContext<'function> {
return_values
}
_ => {
// If there is more than 1 return instruction we'll need to create a single block we
// can return to and continue inserting in afterwards.
let return_block = self.context.builder.insert_block();

for (block, return_values) in returns {
self.context.builder.switch_to_block(block);
self.context.builder.terminate_with_jmp(return_block, return_values);
}

self.context.builder.switch_to_block(return_block);
self.context.builder.block_parameters(return_block).to_vec()
panic!(
"ICE: found a function with multiple return terminators, but that should not happen"
)
}
}
}
Expand Down Expand Up @@ -635,22 +628,8 @@ impl<'function> PerFunctionContext<'function> {
new_results: InsertInstructionResult,
) {
assert_eq!(old_results.len(), new_results.len());

match new_results {
InsertInstructionResult::SimplifiedTo(new_result) => {
values.insert(old_results[0], new_result);
}
InsertInstructionResult::SimplifiedToMultiple(new_results) => {
for (old_result, new_result) in old_results.iter().zip(new_results) {
values.insert(*old_result, new_result);
}
}
InsertInstructionResult::Results(_, new_results) => {
for (old_result, new_result) in old_results.iter().zip(new_results) {
values.insert(*old_result, *new_result);
}
}
InsertInstructionResult::InstructionRemoved => (),
for i in 0..old_results.len() {
values.insert(old_results[i], new_results[i]);
}
}

Expand All @@ -669,20 +648,8 @@ impl<'function> PerFunctionContext<'function> {
TerminatorInstruction::Jmp { destination, arguments, call_stack } => {
let destination = self.translate_block(*destination, block_queue);
let arguments = vecmap(arguments, |arg| self.translate_value(*arg));

let call_stack = self.source_function.dfg.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
.builder
.set_call_stack(new_call_stack)
.terminate_with_jmp(destination, arguments);
self.extend_call_stack(*call_stack);
self.context.builder.terminate_with_jmp(destination, arguments);
None
}
TerminatorInstruction::JmpIf {
Expand All @@ -692,14 +659,6 @@ impl<'function> PerFunctionContext<'function> {
call_stack,
} => {
let condition = self.translate_value(*condition);
let call_stack = self.source_function.dfg.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);

// See if the value of the condition is known, and if so only inline the reachable
// branch. This lets us inline some recursive functions without recurring forever.
Expand All @@ -710,17 +669,15 @@ impl<'function> PerFunctionContext<'function> {
if constant.is_zero() { *else_destination } else { *then_destination };

let next_block = self.translate_block(next_block, block_queue);
self.context
.builder
.set_call_stack(new_call_stack)
.terminate_with_jmp(next_block, vec![]);
self.extend_call_stack(*call_stack);
self.context.builder.terminate_with_jmp(next_block, vec![]);
}
None => {
let then_block = self.translate_block(*then_destination, block_queue);
let else_block = self.translate_block(*else_destination, block_queue);
self.extend_call_stack(*call_stack);
self.context
.builder
.set_call_stack(new_call_stack)
.terminate_with_jmpif(condition, then_block, else_block);
}
}
Expand All @@ -736,20 +693,8 @@ impl<'function> PerFunctionContext<'function> {
let block_id = self.context.builder.current_block();

if self.inlining_entry {
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
.builder
.set_call_stack(new_call_stack)
.terminate_with_return(return_values.clone());
self.extend_call_stack(*call_stack);
self.context.builder.terminate_with_return(return_values.clone());
}

Some((block_id, return_values))
Expand All @@ -762,6 +707,14 @@ impl<'function> PerFunctionContext<'function> {
}
}
}

fn extend_call_stack(&mut self, call_stack: CallStackId) {
let call_stack = self.source_function.dfg.get_call_stack(call_stack);
let call_stack_data = &mut self.context.builder.current_function.dfg.call_stack_data;
let new_call_stack =
call_stack_data.extend_call_stack(self.context.call_stack, &call_stack);
self.context.builder.set_call_stack(new_call_stack);
}
}

#[cfg(test)]
Expand Down
21 changes: 13 additions & 8 deletions compiler/noirc_evaluator/src/ssa/opt/inlining/inline_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,21 @@ fn compute_function_should_be_inlined(
let function = &ssa.functions[&func_id];
let assert_constant_id = function.dfg.get_intrinsic(Intrinsic::AssertConstant).copied();
let static_assert_id = function.dfg.get_intrinsic(Intrinsic::StaticAssert).copied();
let contains_static_assertion = function.reachable_blocks().iter().any(|block| {
function.dfg[*block].instructions().iter().any(|instruction| {
match &function.dfg[*instruction] {
Instruction::Call { func, .. } => {
Some(*func) == assert_constant_id || Some(*func) == static_assert_id

let contains_static_assertion = if assert_constant_id.is_none() && static_assert_id.is_none() {
false
} else {
function.reachable_blocks().iter().any(|block| {
function.dfg[*block].instructions().iter().any(|instruction| {
match &function.dfg[*instruction] {
Instruction::Call { func, .. } => {
Some(*func) == assert_constant_id || Some(*func) == static_assert_id
}
_ => false,
}
_ => false,
}
})
})
});
};

let neighbors = call_graph.graph().neighbors(index);
let mut total_weight = compute_function_own_weight(function) as i64;
Expand Down
Loading