diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-17 10:03:53 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-17 10:03:53 +0800 |
commit | e6116ce077b1f99fe3e510e23bdb5c4646adbcca (patch) | |
tree | 93b48a3b87740cb4bcc765d3e7a983519d0de2c0 | |
parent | 8062b43a179b645df1fc11d8b1b1112baa43d964 (diff) | |
download | mrust-e6116ce077b1f99fe3e510e23bdb5c4646adbcca.tar.gz |
MIR Optimisation and efficiency tweaks
-rw-r--r-- | src/mir/from_hir.cpp | 20 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 62 |
2 files changed, 79 insertions, 3 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 7d5853dd..9db4b115 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -551,13 +551,29 @@ namespace { { TRACE_FUNCTION_FR("_If", "_If"); - this->visit_node_ptr(node.m_cond); + bool reverse = false; + { + auto* cond_p = &node.m_cond; + while( auto* cond_uni = dynamic_cast<::HIR::ExprNode_UniOp*>(cond_p->get()) ) + { + ASSERT_BUG(cond_uni->span(), cond_uni->m_op == ::HIR::ExprNode_UniOp::Op::Invert, ""); + cond_p = &cond_uni->m_value; + reverse = !reverse; + } + + this->visit_node_ptr(*cond_p); + } auto decision_val = m_builder.get_result_in_lvalue(node.m_cond->span(), node.m_cond->m_res_type); auto true_branch = m_builder.new_bb_unlinked(); auto false_branch = m_builder.new_bb_unlinked(); auto next_block = m_builder.new_bb_unlinked(); - m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) ); + if( reverse ) { + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), false_branch, true_branch }) ); + } + else { + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) ); + } auto result_val = m_builder.new_temporary(node.m_res_type); diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 3086ec3f..f877ab88 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -45,7 +45,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path TRACE_FUNCTION_F(path); ::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn }; - // 1. Replace targets that point to a block that is just a goto + // >> Replace targets that point to a block that is just a goto for(auto& block : fcn.blocks) { TU_MATCHA( (block.terminator), (e), @@ -75,6 +75,66 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path ) } + // >> Merge blocks where a block goto-s to a single-use block. + { + ::std::vector<unsigned int> uses( fcn.blocks.size() ); + for(auto& block : fcn.blocks) + { + TU_MATCHA( (block.terminator), (e), + (Incomplete, + ), + (Return, + ), + (Diverge, + ), + (Goto, + uses[e] ++; + ), + (Panic, + ), + (If, + uses[e.bb0] ++; + uses[e.bb1] ++; + ), + (Switch, + for(auto& target : e.targets) + uses[target] ++; + ), + (Call, + uses[e.ret_block] ++; + uses[e.panic_block] ++; + ) + ) + } + + unsigned int i = 0; + for(auto& block : fcn.blocks) + { + while( block.terminator.is_Goto() ) + { + auto tgt = block.terminator.as_Goto(); + if( uses[tgt] != 1 ) + break ; + DEBUG("Append bb " << tgt << " to bb" << i); + + assert( &fcn.blocks[tgt] != &block ); + + for(auto& stmt : fcn.blocks[tgt].statements) + block.statements.push_back( mv$(stmt) ); + block.terminator = mv$( fcn.blocks[tgt].terminator ); + } + i ++; + } + } + + // >> Combine Duplicate Blocks + // TODO: + + + // >> Propagate dead assignments + // TODO: This requires kowing that doing so has no effect. + // - Can use little heristics like a Call pointing to an assignment of its RV + // GC pass on blocks and variables // - Find unused blocks, then delete and rewrite all references. { |