summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mir/optimise.cpp99
1 files changed, 77 insertions, 22 deletions
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index 99ecf4a7..88a073cf 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -735,28 +735,26 @@ bool MIR_Optimise_BlockSimplify(::MIR::TypeResolve& state, ::MIR::Function& fcn)
unsigned int i = 0;
for(auto& block : fcn.blocks)
{
- if( !visited[i] )
- {
- i++;
- continue ;
- }
- while( block.terminator.is_Goto() )
+ if( visited[i] )
{
- auto tgt = block.terminator.as_Goto();
- if( uses[tgt] != 1 )
- break ;
- if( tgt == i )
- break;
- DEBUG("Append bb " << tgt << " to bb" << i);
+ while( block.terminator.is_Goto() )
+ {
+ auto tgt = block.terminator.as_Goto();
+ if( uses[tgt] != 1 )
+ break ;
+ if( tgt == i )
+ break;
+ DEBUG("Append bb " << tgt << " to bb" << i);
- assert( &fcn.blocks[tgt] != &block );
- // Move contents of source block, then set the TAGDEAD terminator to Incomplete
- auto src_block = mv$(fcn.blocks[tgt]);
- fcn.blocks[tgt].terminator = ::MIR::Terminator::make_Incomplete({});
+ assert( &fcn.blocks[tgt] != &block );
+ // Move contents of source block, then set the TAGDEAD terminator to Incomplete
+ auto src_block = mv$(fcn.blocks[tgt]);
+ fcn.blocks[tgt].terminator = ::MIR::Terminator::make_Incomplete({});
- for(auto& stmt : src_block.statements)
- block.statements.push_back( mv$(stmt) );
- block.terminator = mv$( src_block.terminator );
+ for(auto& stmt : src_block.statements)
+ block.statements.push_back( mv$(stmt) );
+ block.terminator = mv$( src_block.terminator );
+ }
}
i ++;
}
@@ -2015,7 +2013,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
changed = true;
}
}
- else if( tef.name == "align_of" )
+ else if( tef.name == "align_of" || tef.name == "min_align_of" )
{
size_t align_val = 0;
if( Target_GetAlignOf(state.sp, state.m_resolve, tef.params.m_types.at(0), align_val) )
@@ -2027,6 +2025,20 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
changed = true;
}
}
+ else if( tef.name == "min_align_of_val" )
+ {
+ size_t align_val = 0;
+ size_t size_val = 0;
+ // Note: Trait object returns align_val = 0 (slice-based types have an alignment)
+ if( Target_GetSizeAndAlignOf(state.sp, state.m_resolve, tef.params.m_types.at(0), size_val, align_val) && align_val > 0 )
+ {
+ DEBUG("min_align_of_val = " << align_val);
+ auto val = ::MIR::Constant::make_Uint({ align_val, ::HIR::CoreType::Usize });
+ bb.statements.push_back(::MIR::Statement::make_Assign({ mv$(te.ret_val), mv$(val) }));
+ bb.terminator = ::MIR::Terminator::make_Goto(te.ret_block);
+ changed = true;
+ }
+ }
// NOTE: Quick special-case for bswap<u8/i8> (a no-op)
else if( tef.name == "bswap" && (tef.params.m_types.at(0) == ::HIR::CoreType::U8 || tef.params.m_types.at(0) == ::HIR::CoreType::I8) )
{
@@ -2122,7 +2134,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
switch(se.op)
{
case ::MIR::eBinOp::EQ:
- if( val_l.is_Const() )
+ if( val_l.is_Const() || val_r.is_Const() )
;
else
{
@@ -2131,7 +2143,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
}
break;
case ::MIR::eBinOp::NE:
- if( val_l.is_Const() )
+ if( val_l.is_Const() || val_r.is_Const() )
;
else
{
@@ -2139,6 +2151,42 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
new_value = ::MIR::Constant::make_Bool({val_l != val_r});
}
break;
+ case ::MIR::eBinOp::LT:
+ if( val_l.is_Const() || val_r.is_Const() )
+ ;
+ else
+ {
+ replace = true;
+ new_value = ::MIR::Constant::make_Bool({val_l < val_r});
+ }
+ break;
+ case ::MIR::eBinOp::LE:
+ if( val_l.is_Const() || val_r.is_Const() )
+ ;
+ else
+ {
+ replace = true;
+ new_value = ::MIR::Constant::make_Bool({val_l <= val_r});
+ }
+ break;
+ case ::MIR::eBinOp::GT:
+ if( val_l.is_Const() || val_r.is_Const() )
+ ;
+ else
+ {
+ replace = true;
+ new_value = ::MIR::Constant::make_Bool({val_l > val_r});
+ }
+ break;
+ case ::MIR::eBinOp::GE:
+ if( val_l.is_Const() || val_r.is_Const() )
+ ;
+ else
+ {
+ replace = true;
+ new_value = ::MIR::Constant::make_Bool({val_l >= val_r});
+ }
+ break;
// TODO: Other binary operations
default:
break;
@@ -2148,6 +2196,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
{
DEBUG(state << " " << e->src << " = " << new_value);
e->src = mv$(new_value);
+ changed = true;
}
}
),
@@ -2236,6 +2285,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
{
DEBUG(state << " " << e->src << " = " << new_value);
e->src = mv$(new_value);
+ changed = true;
}
}
),
@@ -2358,6 +2408,8 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
auto new_bb = te.targets.at(it->second);
DEBUG(state << "Convert " << bb.terminator << " into Goto(" << new_bb << ") because variant known to be #" << it->second);
bb.terminator = ::MIR::Terminator::make_Goto(new_bb);
+
+ changed = true;
}
} break;
TU_ARM(bb.terminator, If, te) {
@@ -2367,6 +2419,8 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
auto new_bb = (it->second.as_Bool().v ? te.bb0 : te.bb1);
DEBUG(state << "Convert " << bb.terminator << " into Goto(" << new_bb << ") because condition known to be " << it->second);
bb.terminator = ::MIR::Terminator::make_Goto(new_bb);
+
+ changed = true;
}
} break;
default:
@@ -2376,6 +2430,7 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
// - Remove based on known booleans within a single block
// > Eliminates `if false`/`if true` branches
+ // TODO: Is this now defunct after the handling of Terminator::If above?
for(auto& bb : fcn.blocks)
{
auto bbidx = &bb - &fcn.blocks.front();