diff --git a/crates/cairo-lang-lowering/src/db.rs b/crates/cairo-lang-lowering/src/db.rs index 65b3e1942de..e17cf2f3297 100644 --- a/crates/cairo-lang-lowering/src/db.rs +++ b/crates/cairo-lang-lowering/src/db.rs @@ -209,6 +209,15 @@ pub trait LoweringGroup: SemanticGroup + Upcast { dependency_type: DependencyType, ) -> Maybe; + /// A concrete version of `in_cycle`. + #[salsa::invoke(crate::graph_algorithms::cycles::concrete_in_cycle)] + fn concrete_in_cycle( + &self, + function_id: ids::ConcreteFunctionWithBodyId, + dependency_type: DependencyType, + stage: LoweringStage, + ) -> Maybe; + // ### Strongly connected components ### /// Returns the representative of the concrete function's strongly connected component. The diff --git a/crates/cairo-lang-lowering/src/graph_algorithms/cycles.rs b/crates/cairo-lang-lowering/src/graph_algorithms/cycles.rs index e5fac75999d..762a631ee34 100644 --- a/crates/cairo-lang-lowering/src/graph_algorithms/cycles.rs +++ b/crates/cairo-lang-lowering/src/graph_algorithms/cycles.rs @@ -77,3 +77,19 @@ pub fn in_cycle( } Ok(db.function_with_body_scc(function_id, dependency_type).len() > 1) } + +/// Query implementation of [LoweringGroup::concrete_in_cycle]. +pub fn concrete_in_cycle( + db: &dyn LoweringGroup, + function_id: ConcreteFunctionWithBodyId, + dependency_type: DependencyType, + stage: LoweringStage, +) -> Maybe { + if db + .lowered_direct_callees_with_body(function_id, dependency_type, stage)? + .contains(&function_id) + { + return Ok(true); + } + Ok(db.lowered_scc(function_id, dependency_type, stage).len() > 1) +} diff --git a/crates/cairo-lang-lowering/src/inline/mod.rs b/crates/cairo-lang-lowering/src/inline/mod.rs index 4838a1d4d91..d8a3504377c 100644 --- a/crates/cairo-lang-lowering/src/inline/mod.rs +++ b/crates/cairo-lang-lowering/src/inline/mod.rs @@ -27,8 +27,8 @@ use crate::ids::{ use crate::lower::context::{VarRequest, VariableAllocator}; use crate::utils::{InliningStrategy, Rebuilder, RebuilderEx}; use crate::{ - Block, BlockEnd, BlockId, Lowered, LoweringStage, Statement, StatementCall, VarRemapping, - VariableId, + Block, BlockEnd, BlockId, DependencyType, Lowered, LoweringStage, Statement, StatementCall, + VarRemapping, VariableId, }; pub fn get_inline_diagnostics( @@ -59,11 +59,7 @@ pub fn priv_should_inline( function_id: ConcreteFunctionWithBodyId, ) -> Maybe { // Breaks cycles. - // TODO(ilya): consider #[inline(never)] attributes for feedback set. - if db - .function_with_body_feedback_set(function_id, LoweringStage::Monomorphized)? - .contains(&function_id) - { + if db.concrete_in_cycle(function_id, DependencyType::Call, LoweringStage::Monomorphized)? { return Ok(false); } diff --git a/crates/cairo-lang-lowering/src/inline/test_data/inline b/crates/cairo-lang-lowering/src/inline/test_data/inline index 79b9f1b8514..bb7c6d6e3fb 100644 --- a/crates/cairo-lang-lowering/src/inline/test_data/inline +++ b/crates/cairo-lang-lowering/src/inline/test_data/inline @@ -982,8 +982,8 @@ End: //! > test #[inline] with indirect self call. //! > Motivation: -//! #[inline] functions should inline a function unless it is recursively called by itself, even -//! indirectly. In this case, the function bar should be inlined, but not the inner call to foo. +//! #[inline] functions should inline a function unless they are on a call cycle. +//! in this test `bar` should not be inlined into `foo`. //! > test_runner_name test_function_inlining @@ -1066,8 +1066,12 @@ End: blk1: Statements: + (v3: core::panics::PanicResult::<(core::felt252,)>) <- test::bar(v0) End: - Goto(blk7, {}) + Match(match_enum(v3) { + PanicResult::Ok(v4) => blk4, + PanicResult::Err(v6) => blk5, + }) blk2: Statements: @@ -1095,38 +1099,6 @@ Statements: End: Return(v11) -blk6: -Statements: -End: - Match(match_enum(v3) { - PanicResult::Ok(v4) => blk4, - PanicResult::Err(v6) => blk5, - }) - -blk7: -Statements: -End: - Match(match core::felt252_is_zero(v0) { - IsZeroResult::Zero => blk8, - IsZeroResult::NonZero(v12) => blk9, - }) - -blk8: -Statements: - (v13: core::felt252) <- 1 - (v14: core::felt252) <- core::felt252_sub(v0, v13) - (v15: core::panics::PanicResult::<(core::felt252,)>) <- test::foo(v14) -End: - Goto(blk6, {v15 -> v3}) - -blk9: -Statements: - (v16: core::felt252) <- 1 - (v17: (core::felt252,)) <- struct_construct(v16) - (v18: core::panics::PanicResult::<(core::felt252,)>) <- PanicResult::Ok(v17) -End: - Goto(blk6, {v18 -> v3}) - //! > lowering_diagnostics //! > ========================================================================== @@ -1621,8 +1593,12 @@ End: blk1: Statements: + (v3: core::panics::PanicResult::<(core::felt252,)>) <- test::bar(v0) End: - Goto(blk7, {}) + Match(match_enum(v3) { + PanicResult::Ok(v4) => blk4, + PanicResult::Err(v6) => blk5, + }) blk2: Statements: @@ -1650,38 +1626,6 @@ Statements: End: Return(v11) -blk6: -Statements: -End: - Match(match_enum(v3) { - PanicResult::Ok(v4) => blk4, - PanicResult::Err(v6) => blk5, - }) - -blk7: -Statements: -End: - Match(match core::felt252_is_zero(v0) { - IsZeroResult::Zero => blk8, - IsZeroResult::NonZero(v12) => blk9, - }) - -blk8: -Statements: - (v13: core::felt252) <- 1 - (v14: core::felt252) <- core::felt252_sub(v0, v13) - (v15: core::panics::PanicResult::<(core::felt252,)>) <- test::foo(v14) -End: - Goto(blk6, {v15 -> v3}) - -blk9: -Statements: - (v16: core::felt252) <- 1 - (v17: (core::felt252,)) <- struct_construct(v16) - (v18: core::panics::PanicResult::<(core::felt252,)>) <- PanicResult::Ok(v17) -End: - Goto(blk6, {v18 -> v3}) - //! > lowering_diagnostics //! > ==========================================================================