From b9598bbb596d49fea743541eddb5566287d5d0cf Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 6 Jan 2025 19:28:50 +0000 Subject: [PATCH] . --- .../src/ssa/function_builder/mod.rs | 11 ++--- compiler/noirc_evaluator/src/ssa/ir/dfg.rs | 30 ++---------- .../noirc_evaluator/src/ssa/ir/function.rs | 46 ++----------------- .../noirc_evaluator/src/ssa/opt/inlining.rs | 2 +- .../src/ssa/ssa_gen/context.rs | 2 +- 5 files changed, 15 insertions(+), 76 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 76c5d13ce1f..d08d5339237 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -68,9 +68,9 @@ impl FunctionBuilder { /// the FunctionBuilder. A function's default runtime type is `RuntimeType::Acir(InlineType::Inline)`. /// This should only be used immediately following construction of a FunctionBuilder /// and will panic if there are any already finished functions. - pub(crate) fn set_runtime(&mut self, runtime: RuntimeType, separated: bool) { + pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { assert_eq!(self.finished_functions.len(), 0, "Attempted to set runtime on a FunctionBuilder with finished functions. A FunctionBuilder's runtime should only be set on its initial function"); - self.current_function.set_runtime(runtime, separated); + self.current_function.set_runtime(runtime); } /// Finish the current function and create a new function. @@ -83,11 +83,10 @@ impl FunctionBuilder { name: String, function_id: FunctionId, runtime_type: RuntimeType, - separated: bool, ) { let call_stack = self.current_function.dfg.get_call_stack(self.call_stack); let mut new_function = Function::new(name, function_id); - new_function.set_runtime(runtime_type, separated); + new_function.set_runtime(runtime_type); 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 @@ -103,7 +102,7 @@ impl FunctionBuilder { function_id: FunctionId, inline_type: InlineType, ) { - self.new_function_with_type(name, function_id, RuntimeType::Acir(inline_type), false); + self.new_function_with_type(name, function_id, RuntimeType::Acir(inline_type)); } /// Finish the current function and create a new unconstrained function. @@ -113,7 +112,7 @@ impl FunctionBuilder { function_id: FunctionId, inline_type: InlineType, ) { - self.new_function_with_type(name, function_id, RuntimeType::Brillig(inline_type), false); + self.new_function_with_type(name, function_id, RuntimeType::Brillig(inline_type)); } /// Consume the FunctionBuilder returning all the functions it has generated. diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index 2be3eba488a..83f81a038ac 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -33,16 +33,6 @@ pub(crate) struct DataFlowGraph { /// ACIR functions are cloned as Brillig functions. runtime: RuntimeType, - /// Indicate whether we are past the runtime separation step. - /// Before this step the DFG accepts any instruction, because - /// an ACIR function might be cloned as a Brillig function. - /// After the separation, we can instantly remove instructions - /// that would just be ignored by the runtime. - /// - /// TODO(#6841): This would not be necessary if the SSA was - /// already generated for a specific runtime. - is_runtime_separated: bool, - /// All of the instructions in a function instructions: DenseMap, @@ -118,7 +108,6 @@ impl DataFlowGraph { pub(crate) fn new(runtime: RuntimeType) -> Self { Self { runtime, - is_runtime_separated: false, instructions: Default::default(), results: Default::default(), values: Default::default(), @@ -139,22 +128,9 @@ impl DataFlowGraph { self.runtime } - /// Indicate whether the runtimes have been separated yet. - pub(crate) fn is_runtime_separated(&self) -> bool { - self.is_runtime_separated - } - /// Set runtime type of the function. - pub(crate) fn set_runtime(&mut self, runtime: RuntimeType, separated: bool) { + pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { self.runtime = runtime; - self.is_runtime_separated = separated; - } - - /// Mark the runtime as separated. After this we can drop - /// instructions that would be ignored by the runtime, - /// instead of inserting them and carrying them to the end. - pub(crate) fn set_runtime_separated(&mut self) { - self.is_runtime_separated = true; } /// Creates a new basic block with no parameters. @@ -246,7 +222,7 @@ impl DataFlowGraph { ctrl_typevars: Option>, call_stack: CallStackId, ) -> InsertInstructionResult { - if self.is_runtime_separated && !self.is_handled_by_runtime(&instruction_data) { + if !self.is_handled_by_runtime(&instruction_data) { return InsertInstructionResult::InstructionRemoved; } @@ -269,7 +245,7 @@ impl DataFlowGraph { ctrl_typevars: Option>, call_stack: CallStackId, ) -> InsertInstructionResult { - if self.is_runtime_separated && !self.is_handled_by_runtime(&instruction) { + if !self.is_handled_by_runtime(&instruction) { return InsertInstructionResult::InstructionRemoved; } match instruction.simplify(self, block, ctrl_typevars.clone(), call_stack) { diff --git a/compiler/noirc_evaluator/src/ssa/ir/function.rs b/compiler/noirc_evaluator/src/ssa/ir/function.rs index 07353695ec1..25c3573fbdb 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeSet, HashSet}; +use std::collections::BTreeSet; use iter_extended::vecmap; use noirc_frontend::monomorphization::ast::InlineType; @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use super::basic_block::BasicBlockId; use super::dfg::DataFlowGraph; -use super::instruction::{Instruction, TerminatorInstruction}; +use super::instruction::TerminatorInstruction; use super::map::Id; use super::types::Type; use super::value::ValueId; @@ -97,7 +97,7 @@ impl Function { /// Takes the signature (function name & runtime) from a function but does not copy the body. pub(crate) fn clone_signature(id: FunctionId, another: &Function) -> Self { let mut new_function = Function::new(another.name.clone(), id); - new_function.set_runtime(another.runtime(), another.is_runtime_separated()); + new_function.set_runtime(another.runtime()); new_function } @@ -117,14 +117,9 @@ impl Function { self.dfg.runtime() } - /// Indicate whether the runtimes have been separated yet. - pub(crate) fn is_runtime_separated(&self) -> bool { - self.dfg.is_runtime_separated() - } - /// Set runtime type of the function. - pub(crate) fn set_runtime(&mut self, runtime: RuntimeType, separated: bool) { - self.dfg.set_runtime(runtime, separated); + pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { + self.dfg.set_runtime(runtime); } pub(crate) fn is_no_predicates(&self) -> bool { @@ -198,37 +193,6 @@ impl Function { unreachable!("SSA Function {} has no reachable return instruction!", self.id()) } - - /// Remove instructions from all the reachable blocks in a function based on a predicate, - /// keeping the ones where the predicate returns `true`. - pub(crate) fn retain_instructions(&mut self, pred: impl Fn(&Instruction) -> bool) { - for block_id in self.reachable_blocks() { - let mut to_remove = HashSet::new(); - let block = &self.dfg[block_id]; - for instruction_id in block.instructions() { - let instruction = &self.dfg[*instruction_id]; - if !pred(instruction) { - to_remove.insert(*instruction_id); - } - } - if !to_remove.is_empty() { - let block = &mut self.dfg[block_id]; - block.instructions_mut().retain(|id| !to_remove.contains(id)); - } - } - } - - /// Remove all instructions that aren't handled by the runtime, which is now - /// considered final. Seal the [DataFlowGraph] so it instantly simplifies - /// away instructions that the runtime would have to ignore. - /// - /// TODO(#6841): Remove once the SSA generated is for a specific runtime already. - pub(crate) fn separate_runtime(&mut self) { - if self.runtime().is_acir() { - self.retain_instructions(|i| !i.is_brillig_only()); - } - self.dfg.set_runtime_separated(); - } } impl Clone for Function { diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 506e7578bb5..1f6c7433f81 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -361,7 +361,7 @@ impl InlineContext { ) -> InlineContext { let source = &ssa.functions[&entry_point]; let mut builder = FunctionBuilder::new(source.name().to_owned(), entry_point); - builder.set_runtime(source.runtime(), source.is_runtime_separated()); + builder.set_runtime(source.runtime()); Self { builder, recursion_level: 0, diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 58f40845e9d..e89d1d2a0c3 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -107,7 +107,7 @@ impl<'a> FunctionContext<'a> { .1; let mut builder = FunctionBuilder::new(function_name, function_id); - builder.set_runtime(runtime, false); + builder.set_runtime(runtime); let definitions = HashMap::default(); let mut this = Self { definitions, builder, shared_context, loops: Vec::new() }; this.add_parameters_to_scope(parameters);