diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/optimise.cpp | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index b7e63deb..7c284546 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -191,7 +191,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path #endif // >> Move common statements (assignments) across gotos. - change_happened |= MIR_Optimise_CommonStatements(state, fcn); + //change_happened |= MIR_Optimise_CommonStatements(state, fcn); // >> Combine Duplicate Blocks change_happened |= MIR_Optimise_UnifyBlocks(state, fcn); @@ -859,12 +859,31 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool { bool inline_happened = false; TRACE_FUNCTION_FR("", inline_happened); + struct InlineEvent { + ::HIR::Path path; + ::std::vector<size_t> bb_list; + InlineEvent(::HIR::Path p) + :path(::std::move(p)) + { + } + bool has_bb(size_t i) const { + return ::std::find(this->bb_list.begin(), this->bb_list.end(), i) != this->bb_list.end(); + } + void add_range(size_t start, size_t count) { + for(size_t j = 0; j < count; j++) + { + this->bb_list.push_back(start + j); + } + } + }; + ::std::vector<InlineEvent> inlined_functions; struct H { static bool can_inline(const ::HIR::Path& path, const ::MIR::Function& fcn, bool minimal) { // TODO: If the function is marked as `inline(always)`, then inline it regardless of the contents + // TODO: Take a monomorph helper so recursion can be detected if( minimal ) { return false; @@ -888,6 +907,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool return false; // Detect and avoid simple recursion. // - This won't detect mutual recursion - that also needs prevention. + // TODO: This is the pre-monomorph path, but we're comparing with the post-monomorph path if( blk0_te.fcn.is_Path() && blk0_te.fcn.as_Path() == path ) return false; return true; @@ -907,6 +927,10 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool // Recursion, don't inline. if( te.fcn.is_Path() && te.fcn.as_Path() == path ) return false; + // HACK: Only allow if the wrapped function is an intrinsic + // - Works around the TODO about monomorphed paths above + if(!te.fcn.is_Intrinsic()) + return false; } } return true; @@ -1272,6 +1296,15 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool if( ! te->fcn.is_Path() ) continue ; const auto& path = te->fcn.as_Path(); + DEBUG(state << fcn.blocks[i].terminator); + + for(const auto& e : inlined_functions) + { + if( path == e.path && e.has_bb(i) ) + { + MIR_BUG(state, "Recursive inline of " << path); + } + } Cloner cloner { state.sp, state.m_resolve, *te }; const auto* called_mir = get_called_mir(state, list, path, cloner.params); @@ -1292,7 +1325,6 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool DEBUG("Can't inline " << path); continue ; } - DEBUG(state << fcn.blocks[i].terminator); TRACE_FUNCTION_F("Inline " << path); // Allocate a temporary for the return value @@ -1350,6 +1382,17 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool } cloner.const_assignments.clear(); + // Record the inline event + for(auto& e : inlined_functions) + { + if( e.has_bb(i) ) + { + e.add_range(cloner.bb_base, new_blocks.size()); + } + } + inlined_functions.push_back(InlineEvent(path.clone())); + inlined_functions.back().add_range(cloner.bb_base, new_blocks.size()); + // Apply DEBUG("- Append new blocks"); fcn.blocks.reserve( fcn.blocks.size() + new_blocks.size() ); @@ -1359,6 +1402,10 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool } fcn.blocks[i].terminator = ::MIR::Terminator::make_Goto( cloner.bb_base ); inline_happened = true; + + // TODO: Store the inlined path along with the start and end BBs, and then use that to detect recursive + // inlining + // - Recursive inlining should be an immediate panic. } } return inline_happened; @@ -3605,6 +3652,14 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn continue ; } } + + // HACK: Remove drop if it's of an unused value (TODO: only if it's conditional?) + if( se->slot.is_Local() && local_rewrite_table[se->slot.as_Local()] == ~0u ) + { + DEBUG(state << "Remove " << stmt << " - Dropping non-set value"); + to_remove_statements[stmt_idx] = true; + continue ; + } } visit_mir_lvalues_mut(stmt, lvalue_cb); |