summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-17 10:03:53 +0800
committerJohn Hodge <tpg@mutabah.net>2016-12-17 10:03:53 +0800
commite6116ce077b1f99fe3e510e23bdb5c4646adbcca (patch)
tree93b48a3b87740cb4bcc765d3e7a983519d0de2c0
parent8062b43a179b645df1fc11d8b1b1112baa43d964 (diff)
downloadmrust-e6116ce077b1f99fe3e510e23bdb5c4646adbcca.tar.gz
MIR Optimisation and efficiency tweaks
-rw-r--r--src/mir/from_hir.cpp20
-rw-r--r--src/mir/optimise.cpp62
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.
{