From be007f8f9616762866ea5dec4538ad27aece660b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 6 Dec 2017 07:42:41 +0100 Subject: [PATCH] Optimizer - Some progress on building UD chains From the table of variables we build a table of per-instruction uses/defines. --- c-opopt.cc | 84 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/c-opopt.cc b/c-opopt.cc index 07715dd..c61de72 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -517,6 +517,59 @@ void BUDCVisitor_( } } +/*----------------------------------------------------------------------------*/ + +struct T_UDEntry_ +{ + uint32_t entry; + bool isUse; + uint32_t index; +}; + +using T_UDEPerInstr_ = T_KeyValueTable< uint32_t , T_AutoArray< T_UDEntry_ , 8 > >; + +template< uint32_t S > +void BUDCAddEntries_( + T_UDEPerInstr_& out , + const uint32_t mainEntry , + const bool isUse , + T_AutoArray< T_OptData::T_VarUDRecord , S > const& entries ) noexcept +{ + const auto na{ entries.size( ) }; + for ( auto j = 0u ; j < na ; j ++ ) { + auto const& use{ entries[ j ] }; + auto* rec{ out.get( use.node ) }; + if ( !rec ) { + out.add( use.node , T_AutoArray< T_UDEntry_ , 8 >{ } ); + rec = out.get( use.node ); + } + assert( rec ); + + auto& ne{ rec->addNew( ) }; + ne.entry = mainEntry; + ne.isUse = isUse; + ne.index = j; + } +} + +/*----------------------------------------------------------------------------*/ + +struct T_VarEvt_ +{ + enum E_VarEvt { + DEF , USE , KILL + }; + + uint32_t instrId; + E_VarEvt evt; + T_OptData::T_VarId var; + + T_VarEvt_( uint32_t instrId , E_VarEvt evt , + T_OptData::T_VarId const& var ) + : instrId( instrId ) , evt( evt ) , var( var ) + { } +}; + } // namespace @@ -528,28 +581,27 @@ void T_OptData::buildUseDefineChains( M_LOGSTR_( "Building use/define chains" , LL1 ); varUDChains.clear( ); - /* - * We need to locate all variable uses. For each use, we will go - * backwards in the graph, until one of the following becomes true: - * - we find an instruction that sets the variable; - * - we find the initial block due to cycling back; - * - we reached the CFG_ENTER node. - * In the latter case, it's an error - the variable is never set. - * - * FIXME: Nope, actually that won't work. We need to find (set) - * instuctions, calls, and also resource initialisations as well - * when visiting the tree; *then* we can associate records from - * both lists. - * - * Note: for function arguments, most of this can be avoided by simply - * looking at the call sites. - */ + // Find all definitions and uses, add them to the table visitor.visit( program.root , [&]( auto& n , const bool exit ) { if ( !exit ) { BUDCVisitor_( program.root , *this , n ); } return true; } ); + + // Build a table of all variable uses/defines that were identified + T_UDEPerInstr_ udPerInstr; + auto const& udcEntries{ varUDChains.values( ) }; + const auto n{ udcEntries.size( ) }; + for ( auto i = 0u ; i < n ; i ++ ) { + auto const& r{ udcEntries[ i ] }; + BUDCAddEntries_( udPerInstr , i , true , r.uses ); + BUDCAddEntries_( udPerInstr , i , false , r.defines ); + } + + // For each node of the CFG graph, we need to generate a sequence that + // indicates what gets defined, used or killed. + T_MultiArray< T_VarEvt_ > cfgVarEvents; }