diff options
Diffstat (limited to 'src/mir')
-rw-r--r-- | src/mir/check.cpp | 2 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 2 | ||||
-rw-r--r-- | src/mir/dump.cpp | 6 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 35 | ||||
-rw-r--r-- | src/mir/main_bindings.hpp | 6 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 1 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 147 |
7 files changed, 146 insertions, 53 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp index cfcc52d4..b2d86590 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -285,6 +285,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn }; ::std::vector<ToVisit> to_visit_blocks; + // TODO: Check that all used locals are also set (anywhere at all) + auto add_to_visit = [&](unsigned int idx, ::std::vector<unsigned int> src_path, auto vs) { for(const auto& b : to_visit_blocks) if( b.bb == idx && b.state == vs) diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 78939f78..37d256df 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -1219,7 +1219,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, void MIR_CleanupCrate(::HIR::Crate& crate) { ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){ - MIR_Cleanup(res, p, *expr_ptr.m_mir, args, ty); + MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty); } }; ov.visit_crate(crate); } diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index c390f5b6..90b81d5d 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -515,7 +515,7 @@ namespace { { m_os << indent() << "{\n"; inc_indent(); - dump_mir(m_os, m_indent_level, *item.m_code.m_mir); + dump_mir(m_os, m_indent_level, item.m_code.get_mir_or_error(Span())); dec_indent(); m_os << indent() << "}\n"; } @@ -538,7 +538,7 @@ namespace { inc_indent(); m_os << " = {\n"; inc_indent(); - dump_mir(m_os, m_indent_level, *item.m_value.m_mir); + dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span())); dec_indent(); m_os << indent() << "} /* = " << item.m_value_res << "*/;\n"; dec_indent(); @@ -562,7 +562,7 @@ namespace { inc_indent(); m_os << " = {\n"; inc_indent(); - dump_mir(m_os, m_indent_level, *item.m_value.m_mir); + dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span())); dec_indent(); m_os << indent() << "} /* = " << item.m_value_res << "*/;\n"; dec_indent(); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 84d60082..6a96ab64 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -17,7 +17,7 @@ #include "from_hir.hpp" #include "operations.hpp" #include <mir/visit_crate_mir.hpp> - +#include <hir/expr_state.hpp> namespace { @@ -1037,9 +1037,8 @@ namespace { // Short-circuiting boolean operations if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolAnd || node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr ) { - // TODO: Generate a SplitScope to handle the early breaks. - auto split_scope = m_builder.new_scope_split(node.span()); + DEBUG("- ShortCircuit Left"); this->visit_node_ptr(node.m_left); auto left = m_builder.get_result_in_lvalue(node.m_left->span(), ty_l); @@ -1048,12 +1047,16 @@ namespace { auto bb_false = m_builder.new_bb_unlinked(); m_builder.end_block( ::MIR::Terminator::make_If({ mv$(left), bb_true, bb_false }) ); + // Generate a SplitScope to handle the conditional nature of the next code + auto split_scope = m_builder.new_scope_split(node.span()); + if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr ) { + DEBUG("- ShortCircuit ||"); // If left is true, assign result true and return m_builder.set_cur_block( bb_true ); m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({true}) )); - m_builder.end_split_arm(node.m_left->span(), split_scope, true); + m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true); m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) ); // If left is false, assign result to right @@ -1061,22 +1064,24 @@ namespace { } else { + DEBUG("- ShortCircuit &&"); // If left is false, assign result false and return m_builder.set_cur_block( bb_false ); m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({false}) )); - m_builder.end_split_arm(node.m_left->span(), split_scope, true); + m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true); m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) ); // If left is true, assign result to right m_builder.set_cur_block( bb_true ); } + DEBUG("- ShortCircuit Right"); auto tmp_scope = m_builder.new_scope_temp(node.m_right->span()); this->visit_node_ptr(node.m_right); m_builder.push_stmt_assign(node.span(), res.clone(), m_builder.get_result(node.m_right->span())); m_builder.terminate_scope(node.m_right->span(), mv$(tmp_scope)); - m_builder.end_split_arm(node.m_left->span(), split_scope, true); + m_builder.end_split_arm(node.m_right->span(), split_scope, /*reachable=*/true); m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) ); m_builder.set_cur_block( bb_next ); @@ -1605,7 +1610,7 @@ namespace { // Extract the "Place" type m_builder.end_block(::MIR::Terminator::make_Call({ place__ok, place__panic, - place.clone(), ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "make_place", {}), + place.clone(), ::HIR::Path(node.m_place->m_res_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "make_place", {}), ::make_vec1( mv$(val) ) })); break; } @@ -2417,10 +2422,24 @@ namespace { // -------------------------------------------------------------------- +void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty) +{ + if( !expr_ptr.m_mir ) + { + StaticTraitResolve resolve { crate }; + if(expr_ptr.m_state->m_impl_generics) resolve.set_impl_generics(*expr_ptr.m_state->m_impl_generics); + if(expr_ptr.m_state->m_item_generics) resolve.set_item_generics(*expr_ptr.m_state->m_item_generics); + expr_ptr.set_mir( LowerMIR(resolve, path, expr_ptr, res_ty, args) ); + } +} + void HIR_GenerateMIR(::HIR::Crate& crate) { ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){ - expr_ptr.m_mir = LowerMIR(res, p, expr_ptr, ty, args); + if( !expr_ptr.get_mir_opt() ) + { + expr_ptr.set_mir( LowerMIR(res, p, expr_ptr, ty, args) ); + } } }; ov.visit_crate(crate); } diff --git a/src/mir/main_bindings.hpp b/src/mir/main_bindings.hpp index cb4f3232..69d5fd90 100644 --- a/src/mir/main_bindings.hpp +++ b/src/mir/main_bindings.hpp @@ -7,10 +7,8 @@ */ #pragma once #include <iostream> +#include <hir/hir.hpp> -namespace HIR { -class Crate; -} class TransList; extern void HIR_GenerateMIR(::HIR::Crate& crate); @@ -21,3 +19,5 @@ extern void MIR_CheckCrate_Full(/*const*/ ::HIR::Crate& crate); extern void MIR_CleanupCrate(::HIR::Crate& crate); extern void MIR_OptimiseCrate(::HIR::Crate& crate, bool minimal_optimisations); extern void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list); + +extern void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty); diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index f2b3a246..3e14ce66 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -2193,6 +2193,7 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv) { if( !lvalue_is_copy(sp, lv) ) { auto& vs = get_val_state_mut(sp, lv); + // TODO: If the current state is Optional, set the drop flag to 0 vs = VarState::make_Invalid(InvalidType::Moved); } } diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 06a8e3dd..80bca08d 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -27,7 +27,7 @@ #define CHECK_AFTER_ALL 1 #define DUMP_AFTER_PASS 1 -#define DUMP_AFTER_DONE 0 +#define DUMP_AFTER_DONE 1 #define CHECK_AFTER_DONE 2 // 1 = Check before GC, 2 = check before and after GC // ---- @@ -106,12 +106,14 @@ bool MIR_OptimiseInline(const StaticTraitResolve& resolve, const ::HIR::ItemPath // - Constant propagation (inlining may have lead to some more constant information MIR_Optimise_ConstPropagte(state, fcn); // - Unify non-overlapping locals +#if 0 if(MIR_Optimise_UnifyTemporaries(state, fcn)) { #if CHECK_AFTER_ALL MIR_Validate(resolve, path, fcn, args, ret_type); #endif } +#endif // - Remove no-op statements MIR_Optimise_NoopRemoval(state, fcn); @@ -238,6 +240,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path // Run UnifyTemporaries last, then unify blocks, then run some // optimisations that might be affected +#if 0 if(MIR_Optimise_UnifyTemporaries(state, fcn)) { #if CHECK_AFTER_ALL @@ -247,6 +250,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path //MIR_Optimise_ConstPropagte(state, fcn); MIR_Optimise_NoopRemoval(state, fcn); } +#endif #if DUMP_AFTER_DONE @@ -536,10 +540,10 @@ namespace { if( it->second->monomorphised.code ) { return &*it->second->monomorphised.code; } - else if( hir_fcn.m_code.m_mir ) { + else if( const auto* mir = hir_fcn.m_code.get_mir_opt() ) { MIR_ASSERT(state, hir_fcn.m_params.m_types.empty(), "Enumeration failure - Function had params, but wasn't monomorphised - " << path); // TODO: Check for trait methods too? - return &*hir_fcn.m_code.m_mir; + return mir; } else { MIR_ASSERT(state, !hir_fcn.m_code, "LowerMIR failure - No MIR but HIR is present?! - " << path); @@ -551,10 +555,10 @@ namespace { TU_MATCHA( (path.m_data), (pe), (Generic, const auto& fcn = state.m_crate.get_function_by_path(state.sp, pe.m_path); - if( fcn.m_code.m_mir ) + if( const auto* mir = fcn.m_code.get_mir_opt() ) { params.fcn_params = &pe.m_params; - return &*fcn.m_code.m_mir; + return mir; } ), (UfcsKnown, @@ -626,14 +630,14 @@ namespace { { params.impl_params.m_types = mv$(best_impl_params); DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); - if( fit->second.data.m_code.m_mir ) - return &*fit->second.data.m_code.m_mir; + if( const auto* mir = fit->second.data.m_code.get_mir_opt() ) + return mir; } else { params.impl_params = pe.trait.m_params.clone(); - if( ve.m_code.m_mir ) - return &*ve.m_code.m_mir; + if( const auto* mir = ve.m_code.get_mir_opt() ) + return mir; } return nullptr; ), @@ -653,12 +657,12 @@ namespace { MIR_ASSERT(state, best_impl, "Couldn't find an impl for " << path); auto fit = best_impl->m_methods.find(pe.item); MIR_ASSERT(state, fit != best_impl->m_methods.end(), "Couldn't find method in best inherent impl"); - if( fit->second.data.m_code.m_mir ) + if( const auto* mir = fit->second.data.m_code.get_mir_opt() ) { params.self_ty = &*pe.type; params.fcn_params = &pe.params; params.impl_params = pe.impl_params.clone(); - return &*fit->second.data.m_code.m_mir; + return mir; } return nullptr; ), @@ -3243,36 +3247,97 @@ bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn) { bool removed_statement = false; TRACE_FUNCTION_FR("", removed_statement); - ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() ); - visit_blocks(state, fcn, [&read_drop_flags](auto , const ::MIR::BasicBlock& block) { - for(const auto& stmt : block.statements) - { - if( const auto* e = stmt.opt_SetDropFlag() ) + ::std::vector<bool> used_drop_flags( fcn.drop_flags.size() ); + { + ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() ); + visit_blocks(state, fcn, [&read_drop_flags,&used_drop_flags](auto , const ::MIR::BasicBlock& block) { + for(const auto& stmt : block.statements) { - if(e->other != ~0u) { - read_drop_flags[e->other] = true; + if( const auto* e = stmt.opt_SetDropFlag() ) + { + if(e->other != ~0u) { + read_drop_flags[e->other] = true; + used_drop_flags[e->other] = true; + } + used_drop_flags[e->idx] = true; + } + else if( const auto* e = stmt.opt_Drop() ) + { + if(e->flag_idx != ~0u) { + read_drop_flags[e->flag_idx] = true; + used_drop_flags[e->flag_idx] = true; + } } } - else if( const auto* e = stmt.opt_Drop() ) + }); + DEBUG("Un-read drop flags:" << FMT_CB(ss, + for(size_t i = 0; i < read_drop_flags.size(); i ++) + if( ! read_drop_flags[i] && used_drop_flags[i] ) + ss << " " << i; + )); + visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) { + for(auto it = block.statements.begin(); it != block.statements.end(); ) { - if(e->flag_idx != ~0u) { - read_drop_flags[e->flag_idx] = true; + if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) { + removed_statement = true; + it = block.statements.erase(it); + } + else { + ++ it; } } - } - }); - visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) { - for(auto it = block.statements.begin(); it != block.statements.end(); ) - { - if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) { - removed_statement = true; - it = block.statements.erase(it); + }); + } + + // Find any drop flags that are never assigned with a value other than their default, then remove those dead assignments. + { + ::std::vector<bool> edited_drop_flags( fcn.drop_flags.size() ); + visit_blocks(state, fcn, [&edited_drop_flags,&fcn](auto , const ::MIR::BasicBlock& block) { + for(const auto& stmt : block.statements) + { + if( const auto* e = stmt.opt_SetDropFlag() ) + { + if(e->other != ~0u) { + // If the drop flag is set based on another, assume it's changed + edited_drop_flags[e->idx] = true; + } + else if( e->new_val != fcn.drop_flags[e->idx] ) { + // If the new value is not the default, it's changed + edited_drop_flags[e->idx] = true; + } + else { + // Set to the default, doesn't change the 'edited' state + } + } } - else { - ++ it; + }); + DEBUG("Un-edited drop flags:" << FMT_CB(ss, + for(size_t i = 0; i < edited_drop_flags.size(); i ++) + if( ! edited_drop_flags[i] && used_drop_flags[i] ) + ss << " " << i; + )); + visit_blocks_mut(state, fcn, [&edited_drop_flags,&removed_statement,&fcn](auto _id, auto& block) { + for(auto it = block.statements.begin(); it != block.statements.end(); ) + { + // If this is a SetDropFlag and the target flag isn't edited, remove + if(const auto* e = it->opt_SetDropFlag()) + { + if( ! edited_drop_flags[e->idx] ) { + assert( e->new_val == fcn.drop_flags[e->idx] ); + removed_statement = true; + it = block.statements.erase(it); + } + else { + ++ it; + } + } + else { + ++ it; + } } - } - }); + }); + } + return removed_statement; } @@ -3414,7 +3479,11 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn visited[bb] = true; auto assigned_lval = [&](const ::MIR::LValue& lv) { - if(const auto* le = lv.opt_Local() ) + const auto* lvp = &lv; + // TODO: Consume through indexing/field accesses + while(lvp->is_Field()) + lvp = &*lvp->as_Field().val; + if(const auto* le = lvp->opt_Local() ) used_locals[*le] = true; }; @@ -3732,11 +3801,12 @@ void MIR_OptimiseCrate(::HIR::Crate& crate, bool do_minimal_optimisation) if( ! dynamic_cast<::HIR::ExprNode_Block*>(expr.get()) ) { return ; } + auto& mir = expr.get_mir_or_error_mut(Span()); if( do_minimal_optimisation ) { - MIR_OptimiseMin(res, p, *expr.m_mir, args, ty); + MIR_OptimiseMin(res, p, mir, args, ty); } else { - MIR_Optimise(res, p, *expr.m_mir, args, ty); + MIR_Optimise(res, p, mir, args, ty); } } }; @@ -3769,9 +3839,10 @@ void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list) { did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *mono_fcn.code, mono_fcn.arg_tys, mono_fcn.ret_ty, list); } - else if( hir_fcn.m_code.m_mir) + else if( hir_fcn.m_code ) { - did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *hir_fcn.m_code.m_mir, hir_fcn.m_args, hir_fcn.m_return, list); + auto& mir = hir_fcn.m_code.get_mir_or_error_mut(Span()); + did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, mir, hir_fcn.m_args, hir_fcn.m_return, list); } else { |