Optimizer - Mostly OK use/define chain construction

In which "mostly" means that it will work, unless:
1/ something is used before being defined (will trigger assertion)
2/ a local variable is re-used before being redefined, which will
be detected as using the def from the previous execution (won't be a
problem for now as it'll crash first, due to (1))
This commit is contained in:
Emmanuel BENOîT 2017-12-08 22:00:43 +01:00
parent f58226aa79
commit fac8de1fde

View file

@ -692,6 +692,7 @@ void T_OptData::buildUseDefineChains(
auto& resource{ varUDChains[ rec.entry ] }; auto& resource{ varUDChains[ rec.entry ] };
const auto defId{ (*activeDefs)[ rec.entry ] }; const auto defId{ (*activeDefs)[ rec.entry ] };
// FIXME: must be defined // FIXME: must be defined
assert( defId != T_HashIndex::INVALID_INDEX );
resource.defines[ defId ].refs.add( rec.index ); resource.defines[ defId ].refs.add( rec.index );
resource.uses[ rec.index ].refs.add( defId ); resource.uses[ rec.index ].refs.add( defId );
logger( [&](){ logger( [&](){
@ -712,7 +713,7 @@ void T_OptData::buildUseDefineChains(
(*activeDefs)[ rec.entry ] = rec.index; (*activeDefs)[ rec.entry ] = rec.index;
logger( [&](){ logger( [&](){
T_StringBuilder sb; T_StringBuilder sb;
sb << "DEF " << rec.index sb << "DEF " << rec.index << ' '
<< varUDChains[ rec.entry ].var.name << varUDChains[ rec.entry ].var.name
<< " @ instr #" << ii; << " @ instr #" << ii;
return sb; return sb;
@ -726,10 +727,6 @@ void T_OptData::buildUseDefineChains(
} }
// Check for possible next nodes // Check for possible next nodes
// -> no output nodes left -> pop stack and keep trying,
// unless we've already processed all nodes
// -> if there's only one, use it and don't push to stack
// -> otherwise push to stack, use first available node
do { do {
auto const& rcn{ *ctrlFlowGraph[ node ] }; auto const& rcn{ *ctrlFlowGraph[ node ] };
const uint32_t nSuccs{ [&](){ const uint32_t nSuccs{ [&](){
@ -742,23 +739,49 @@ void T_OptData::buildUseDefineChains(
} }
return c; return c;
}() }; }() };
logger( [=]() { logger( [&]() {
T_StringBuilder sb; T_StringBuilder sb;
sb << "node " << node << ": " << nSuccs sb << "node " << node << ": " << nSuccs
<< " successor(s) left"; << " successor(s) left (stack depth "
<< stack.size( ) << ')';
return sb; return sb;
} , LL2 ); } , LL2 );
// -> no output nodes left -> pop stack and keep trying,
// unless we've already processed all nodes
if ( nSuccs == 0 ) { if ( nSuccs == 0 ) {
assert( !stack.empty( ) ); assert( !stack.empty( ) );
node = stack.last( ).node; node = stack.last( ).node;
activeDefs = std::move( stack.last( ).def ); activeDefs = std::move( stack.last( ).def );
stack.removeLast( ); stack.removeLast( );
logger( [&]() {
T_StringBuilder sb;
sb << "pop stack -> next node " << node
<< " (stack depth "
<< stack.size( ) << ')';
return sb;
} , LL2 );
continue; continue;
} }
// TODO cases in which there is one or more successors const auto no{ rcn.outbound.size( ) };
} while ( 0 ); // XXX uint32_t nn{ T_HashIndex::INVALID_INDEX };
for ( auto i = 0u ; i < no ; i ++ ) {
if ( !processedNodes[ rcn.outbound[ i ] ] ) {
nn = rcn.outbound[ i ];
break;
}
}
// More than one possible successor? Push to stack
if ( nSuccs > 1 ) {
M_LOGSTR_( "pushing node" , LL2 );
stack.addNew( activeDefs , node );
}
node = nn;
break;
} while ( 1 );
// 30 if next block is an end of function, kill locals // 30 if next block is an end of function, kill locals
} }