summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-07-07 13:30:29 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-07-07 13:30:29 +0800
commita94abe48f395b161ade776c019da12ba99eb5e88 (patch)
tree6639ab378f60929c65ff6945435da13b44039862
parentcb11800ea4a8a542c2a0667870ab3730e2b8b9df (diff)
downloadmrust-a94abe48f395b161ade776c019da12ba99eb5e88.tar.gz
MIR Optimise - Fix (and detect) mis-optimisation with indexing, more const propagation
-rw-r--r--src/mir/check.cpp12
-rw-r--r--src/mir/dump.cpp6
-rw-r--r--src/mir/optimise.cpp59
3 files changed, 68 insertions, 9 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 6ed34563..d159c85f 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -357,6 +357,18 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn
val_state.mark_validity( state, v.second, true );
break;
case ::MIR::Statement::TAG_Assign:
+ // Destination must be valid
+ for(const auto& w : stmt.as_Assign().dst.m_wrappers)
+ {
+ if( w.is_Deref() ) {
+ // TODO: Check validity of the rest of the wrappers.
+ }
+ if( w.is_Index() )
+ {
+ if( val_state.locals[w.as_Index()] != ValStates::State::Valid )
+ MIR_BUG(state, "Use of non-valid lvalue - " << ::MIR::LValue::new_Local(w.as_Index()));
+ }
+ }
// Check source (and invalidate sources)
TU_MATCH( ::MIR::RValue, (stmt.as_Assign().src), (se),
(Use,
diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp
index 69ffa850..d41bef7c 100644
--- a/src/mir/dump.cpp
+++ b/src/mir/dump.cpp
@@ -181,13 +181,13 @@ namespace {
void fmt_val(::std::ostream& os, const ::MIR::Constant& e) {
TU_MATCHA( (e), (ce),
(Int,
- os << ce.v;
+ os << ce.v << "_" << ce.t;
),
(Uint,
- os << "0x" << ::std::hex << ce.v << ::std::dec;
+ os << "0x" << ::std::hex << ce.v << ::std::dec << "_" << ce.t;
),
(Float,
- os << ce.v;
+ os << ce.v << "_" << ce.t;
),
(Bool,
os << (ce.v ? "true" : "false");
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index a08aa055..3810d801 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -2347,11 +2347,47 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn)
// TU_ARMav(Int, (le, re)) {
TU_ARMA(Int, le) { const auto& re = val_r.as_Int();
MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::ADD - " << val_l << " + " << val_r);
- new_value = ::MIR::Constant::make_Int({ H::truncate_s(le.t, le.v + re.v) });
+ new_value = ::MIR::Constant::make_Int({ H::truncate_s(le.t, le.v + re.v), le.t });
}
TU_ARMA(Uint, le) { const auto& re = val_r.as_Uint();
MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::ADD - " << val_l << " + " << val_r);
- new_value = ::MIR::Constant::make_Uint({ H::truncate_u(le.t, le.v + re.v) });
+ new_value = ::MIR::Constant::make_Uint({ H::truncate_u(le.t, le.v + re.v), le.t });
+ }
+ }}
+ break;
+ case ::MIR::eBinOp::SUB:
+ MIR_ASSERT(state, val_l.tag() == val_r.tag(), "Mismatched types for eBinOp::SUB - " << val_l << " + " << val_r);
+ //{TU_MATCH_HDRA( (val_l, val_r), {)
+ {TU_MATCH_HDRA( (val_l), {)
+ default:
+ break;
+ // TU_ARMav(Int, (le, re)) {
+ TU_ARMA(Int, le) { const auto& re = val_r.as_Int();
+ MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::SUB - " << val_l << " + " << val_r);
+ new_value = ::MIR::Constant::make_Int({ H::truncate_s(le.t, le.v - re.v), le.t });
+ }
+ TU_ARMA(Uint, le) { const auto& re = val_r.as_Uint();
+ MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::SUB - " << val_l << " + " << val_r);
+ new_value = ::MIR::Constant::make_Uint({ H::truncate_u(le.t, le.v - re.v), le.t });
+ }
+ }}
+ break;
+ case ::MIR::eBinOp::MOD:
+ MIR_ASSERT(state, val_l.tag() == val_r.tag(), "Mismatched types for eBinOp::MOD - " << val_l << " + " << val_r);
+ //{TU_MATCH_HDRA( (val_l, val_r), {)
+ {TU_MATCH_HDRA( (val_l), {)
+ default:
+ break;
+ // TU_ARMav(Int, (le, re)) {
+ TU_ARMA(Int, le) { const auto& re = val_r.as_Int();
+ MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::MOD - " << val_l << " + " << val_r);
+ MIR_ASSERT(state, re.v != 0, "Const eval error: Constant division by zero");
+ new_value = ::MIR::Constant::make_Int({ H::truncate_s(le.t, le.v % re.v), le.t });
+ }
+ TU_ARMA(Uint, le) { const auto& re = val_r.as_Uint();
+ MIR_ASSERT(state, le.t == re.t, "Mismatched types for eBinOp::MOD - " << val_l << " + " << val_r);
+ MIR_ASSERT(state, re.v != 0, "Const eval error: Constant division by zero");
+ new_value = ::MIR::Constant::make_Uint({ H::truncate_u(le.t, le.v % re.v), le.t });
}
}}
break;
@@ -3250,7 +3286,7 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F
const ::MIR::LValue* new_dst = nullptr;
auto& blk2 = fcn.blocks.at(e.ret_block);
for(const auto& stmt : blk2.statements)
- {
+ {
// Find `RValue::Use( this_lvalue )`
if( stmt.is_Assign() && stmt.as_Assign().src.is_Use() && stmt.as_Assign().src.as_Use() == e.ret_val ) {
new_dst = &stmt.as_Assign().dst;
@@ -3263,16 +3299,27 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F
{
auto lvalue_impacts_dst = [&](const ::MIR::LValue& lv)->bool {
// Returns true if the two lvalues share a common root
- // TODO: Could restrict based on the presence of
- // deref/field accesses?
+ // TODO: Could restrict based on the presence of deref/field accesses?
+ // If `lv` is a local AND matches the index in `new_dst`, check for indexing
+ if( lv.is_Local() )
+ {
+ for(const auto& w : new_dst->m_wrappers)
+ {
+ if( w.is_Index() && w.as_Index() == lv.as_Local() )
+ {
+ return true;
+ }
+ }
+ }
return lv.m_root == new_dst->m_root;
};
for(auto it = blk2.statements.begin(); it != blk2.statements.end(); ++ it)
{
+ state.set_cur_stmt(&blk2 - &fcn.blocks.front(), it - blk2.statements.begin());
const auto& stmt = *it;
if( stmt.is_Assign() && stmt.as_Assign().src.is_Use() && stmt.as_Assign().src.as_Use() == e.ret_val )
{
- DEBUG("- Replace function return " << e.ret_val << " with " << *new_dst);
+ DEBUG(state << "- Replace function return " << e.ret_val << " with " << *new_dst);
e.ret_val = new_dst->clone();
// TODO: Invalidate the entry, instead of deleting?
it = blk2.statements.erase(it);