diff --git a/c-opopt.cc b/c-opopt.cc index 42e5328..d23323c 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -1050,39 +1050,6 @@ void T_OptData::buildUseDefineChains( BUDCAddEntries_( udPerInstr , i , false , r.defines ); } - - /* - * So this whole heap of code below is wrong. It wouldn't work correctly - * in all cases (although it does with the current test code, but that's - * irrelevant). - * - * A block B from the CFG has instr{B}+1 points (1 point before each - * instruction, and 1 point at the end of the block). - * - * Uses should be assigned to the point preceding the instruction; defs - * and kills should be assigned to the point that follows it, before - * any uses (it may be simpler to have 2 points / instruction?) - * - * defs from I0 defs from I1 - * \/ \/ - * P00 -> I0 -> P01 -> P10 -> I1 -> I11 -> PBE - * /\ /\ /\ - * uses from I0 uses from I1 defs/kills from block end - * - * Entering/exiting functions is a bit of a PITA: - * - call instructions define function arguments; - * - return edges kill locals - * - * OK, so now that we have edge types, things should be easier, as we - * can: - * - handle arguments directly; they're immutable and always - * defined at the function's call site. - * - handle local variables by walking the function's graph, - * ignoring all CALL edges and terminating at the RET edge; - * - handle globals by following all edges and terminating at the - * exit node - */ - // Proceed for each symbol for ( auto& sym : varUDChains.values( ) ) { switch ( sym.var.type ) { @@ -1109,160 +1076,6 @@ void T_OptData::buildUseDefineChains( } } } - -#if 0 - // Walk the graph from the entry point until all reachable nodes - // have been covered and keeping track of active definitions. When - // the flow diverges, we need to store the state before the - // divergence. - const uint32_t nNodes{ ctrlFlowGraph.size( ) }; - uint32_t nProcessed{ 0 }; - uint32_t node{ CFG_ENTER }; - - bool processedNodes[ nNodes ]; - memset( processedNodes , 0 , sizeof( processedNodes ) ); - - using T_ActDefs_ = T_Array< uint32_t >; - using P_ActDefs_ = T_OwnPtr< T_ActDefs_ >; - P_ActDefs_ activeDefs{ NewOwned< T_ActDefs_ >( ) }; - activeDefs->resize( varUDChains.size( ) , T_HashIndex::INVALID_INDEX ); - - struct T_StackEntry_ { - P_ActDefs_ def; - uint32_t node; - - T_StackEntry_( P_ActDefs_ const& src , const uint32_t n ) noexcept - : def{ NewOwned< T_ActDefs_ >( *src ) } , node( n ) - {} - }; - T_AutoArray< T_StackEntry_ , 32 > stack; - - while ( nProcessed < nNodes ) { - assert( !processedNodes[ node ] ); - auto const& cn{ *ctrlFlowGraph[ node ] }; - processedNodes[ node ] = true; - logger( [=]() { - T_StringBuilder sb; - sb << "processing node " << node; - return sb; - } , LL2 ); - nProcessed ++; - - if ( cn.instructions ) { - // Check for uses and defines in the instructions - const auto is{ cn.instructions->first }; - const auto ie{ is + cn.instructions->count }; - for ( auto ii = is ; ii < ie ; ii ++ ) { - auto const* const irec{ udPerInstr.get( ii ) }; - if ( !irec ) { - continue; - } - const auto nrec{ irec->size( ) }; - - // Handle uses first - for ( auto j = 0u ; j < nrec ; j ++ ) { - auto const& rec{ (*irec)[ j ] }; - if ( !rec.isUse ) { - continue; - } - - auto& resource{ varUDChains[ rec.entry ] }; - const auto defId{ (*activeDefs)[ rec.entry ] }; - // FIXME: must be defined - assert( defId != T_HashIndex::INVALID_INDEX ); - resource.defines[ defId ].refs.add( rec.index ); - resource.uses[ rec.index ].refs.add( defId ); - logger( [&](){ - T_StringBuilder sb; - sb << "USE " << resource.var.name - << " @ instr #" << ii - << ", def " << defId; - return sb; - } , LL2 ); - } - - // Handle defines - for ( auto j = 0u ; j < nrec ; j ++ ) { - auto const& rec{ (*irec)[ j ] }; - if ( rec.isUse ) { - continue; - } - (*activeDefs)[ rec.entry ] = rec.index; - logger( [&](){ - T_StringBuilder sb; - sb << "DEF " << rec.index << ' ' - << varUDChains[ rec.entry ].var.name - << " @ instr #" << ii; - return sb; - } , LL2 ); - } - } - } - - if ( nProcessed == nNodes ) { - break; - } - - // Check for possible next nodes - do { - auto const& rcn{ *ctrlFlowGraph[ node ] }; - const uint32_t nSuccs{ [&](){ - const auto no{ rcn.outbound.size( ) }; - uint32_t c{ 0 }; - for ( auto i = 0u ; i < no ; i ++ ) { - if ( !processedNodes[ rcn.outbound[ i ] ] ) { - c ++; - } - } - return c; - }() }; - logger( [&]() { - T_StringBuilder sb; - sb << "node " << node << ": " << nSuccs - << " successor(s) left (stack depth " - << stack.size( ) << ')'; - return sb; - } , LL2 ); - - // -> no output nodes left -> pop stack and keep trying, - // unless we've already processed all nodes - if ( nSuccs == 0 ) { - assert( !stack.empty( ) ); - node = stack.last( ).node; - activeDefs = std::move( stack.last( ).def ); - stack.removeLast( ); - logger( [&]() { - T_StringBuilder sb; - sb << "pop stack -> next node " << node - << " (stack depth " - << stack.size( ) << ')'; - return sb; - } , LL2 ); - continue; - } - - const auto no{ rcn.outbound.size( ) }; - 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 - } -#endif }