diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 14c81e5d984..5dc14336761 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -94,6 +94,9 @@ impl Ssa { self } + /// Inline "simple" functions. + /// A simple function being a function with one or less instructions. + /// Simple functions are still restricted to not inlined if they are recursive or marked with no predicates. pub(crate) fn inline_simple_functions(mut self: Ssa) -> Ssa { let should_inline_call = |callee: &Function| { if let RuntimeType::Acir(_) = callee.runtime() { @@ -112,10 +115,32 @@ impl Ssa { } // Only inline functions with 0 or 1 instructions - entry_block.instructions().len() <= 1 + if entry_block.instructions().len() > 1 { + return false; + } + + let instructions = callee.dfg[entry_block_id].instructions(); + if instructions.is_empty() { + return true; + } + + // Check whether the only instruction is a recursive call, which prevents inlining the callee. + // This special check is done here to avoid performing the entire inline info computation. + // The inline info computation contains extra logic and requires passing over every function. + // which we can avoid in when inlining simple functions. + let only_instruction = callee.dfg[entry_block_id].instructions()[0]; + if let Instruction::Call { func, .. } = callee.dfg[only_instruction] { + let Value::Function(func_id) = callee.dfg[func] else { + return true; + }; + + func_id != callee.id() + } else { + true + } }; - self.functions = btree_map(self.functions.iter(), |(id, function)| { + self.functions = btree_map(&self.functions, |(id, function)| { (*id, function.inlined(&self, &should_inline_call)) }); diff --git a/test_programs/execution_failure/simple_infinite_recursive_function/Nargo.toml b/test_programs/execution_failure/simple_infinite_recursive_function/Nargo.toml new file mode 100644 index 00000000000..4e6f8c90693 --- /dev/null +++ b/test_programs/execution_failure/simple_infinite_recursive_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_infinite_recursive_function" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/simple_infinite_recursive_function/src/main.nr b/test_programs/execution_failure/simple_infinite_recursive_function/src/main.nr new file mode 100644 index 00000000000..6dc99901809 --- /dev/null +++ b/test_programs/execution_failure/simple_infinite_recursive_function/src/main.nr @@ -0,0 +1,14 @@ +fn main() { + // Safety: testing context + unsafe { + foo(); + } +} + +unconstrained fn foo() { + bar(); +} + +unconstrained fn bar() { + bar(); +} diff --git a/test_programs/execution_failure/simple_infinite_recursive_lambda/Nargo.toml b/test_programs/execution_failure/simple_infinite_recursive_lambda/Nargo.toml new file mode 100644 index 00000000000..71885ae5573 --- /dev/null +++ b/test_programs/execution_failure/simple_infinite_recursive_lambda/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_infinite_recursive_lambda" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/simple_infinite_recursive_lambda/src/main.nr b/test_programs/execution_failure/simple_infinite_recursive_lambda/src/main.nr new file mode 100644 index 00000000000..c3adba39f85 --- /dev/null +++ b/test_programs/execution_failure/simple_infinite_recursive_lambda/src/main.nr @@ -0,0 +1,16 @@ +fn main() { + // Safety: testing context + unsafe { + foo(bar); + } +} + +unconstrained fn foo(f: unconstrained fn[Env]()) { + f(); + f(); +} + +unconstrained fn bar() { + bar(); + bar(); +}