From cb42137592620a97db05c30940aeafa1db3ffe3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sun, 10 Dec 2017 11:12:45 +0100 Subject: [PATCH] Optimizer - Edge types in CFG Control flow graph edges have been assigned a type, which may be either FLOW (for normal edges), CALL (for edges that enter a function) or RET (for edges that exit a function). In addition, call sites have an additional FLOW edge that bypasses the function call. --- c-opopt.cc | 46 ++++++++++++++++++++++++++++++++++------------ c-opopt.hh | 22 +++++++++++++++++++--- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/c-opopt.cc b/c-opopt.cc index 779b67a..11153cc 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -27,6 +27,19 @@ uint32_t opopt::ComputeHash( ^ ( ( oh << 29 ) | ( oh >> 3 ) ); } +T_StringBuilder& opopt::operator<<( + T_StringBuilder& obj , + T_OptData::T_CtrlFlowEdge const& value ) noexcept +{ + obj << value.target; + if ( value.type == T_OptData::T_CtrlFlowEdge::CALL ) { + obj << "{c}"; + } else if ( value.type == T_OptData::T_CtrlFlowEdge::RET ) { + obj << "{r}"; + } + return obj; +} + constexpr uint32_t T_OptData::CFG_ENTER; constexpr uint32_t T_OptData::CFG_MAINLOOP; constexpr uint32_t T_OptData::CFG_END; @@ -386,21 +399,30 @@ inline void BCFGHandleCalls_( } // Handle calls + constexpr auto tCall{ T_OptData::T_CtrlFlowEdge::CALL }; + constexpr auto tRet{ T_OptData::T_CtrlFlowEdge::RET }; for ( auto const& cs : data.callSites ) { auto const* frec{ data.cfgFunctions.get( cs.name ) }; assert( frec ); - { - auto& entry{ data.ctrlFlowGraph[ frec->first ] }; - entry->inbound.add( cs.callBlock ); - data.ctrlFlowGraph[ cs.callBlock ]->outbound.add( - frec->first ); - } - { - const auto n{ frec->first + frec->count - 1 }; - auto& exit{ data.ctrlFlowGraph[ n ] }; - exit->outbound.add( cs.retBlock ); - data.ctrlFlowGraph[ cs.retBlock ]->inbound.add( n ); - } + + + const auto nExit{ frec->first + frec->count - 1 }; + auto& bCall{ *data.ctrlFlowGraph[ cs.callBlock ] }; + auto& bRet{ *data.ctrlFlowGraph[ cs.retBlock ] }; + auto& bEntry{ *data.ctrlFlowGraph[ frec->first ] }; + auto& bExit{ *data.ctrlFlowGraph[ nExit ] }; + + // Call + bEntry.inbound.addNew( cs.callBlock , tCall ); + bCall.outbound.addNew( frec->first , tCall ); + + // Return + bExit.outbound.addNew( cs.retBlock , tRet ); + bRet.inbound.addNew( nExit , tRet ); + + // Normal flow, skipping the call + bCall.outbound.addNew( cs.retBlock ); + bRet.inbound.addNew( cs.callBlock ); } } diff --git a/c-opopt.hh b/c-opopt.hh index 6d72976..91cb932 100644 --- a/c-opopt.hh +++ b/c-opopt.hh @@ -66,12 +66,27 @@ struct T_OptData { } }; - // Control flow graph node + // Control flow graph edges and nodes + struct T_CtrlFlowEdge + { + enum E_Type { + FLOW , CALL , RET + }; + + uint32_t target; + E_Type type; + + T_CtrlFlowEdge( + const uint32_t target , + const E_Type type = FLOW ) noexcept + : target{ target } , type{ type } + {} + }; struct T_CtrlFlowNode { T_Optional< T_BasicBlock > instructions; - T_AutoArray< uint32_t , 16 > inbound; - T_AutoArray< uint32_t , 16 > outbound; + T_AutoArray< T_CtrlFlowEdge , 16 > inbound; + T_AutoArray< T_CtrlFlowEdge , 16 > outbound; }; using P_CtrlFlowNode = T_OwnPtr< T_CtrlFlowNode >; @@ -171,6 +186,7 @@ struct T_OptData }; uint32_t ComputeHash( T_OptData::T_VarId const& id ) noexcept; +M_LSHIFT_OP( T_StringBuilder , T_OptData::T_CtrlFlowEdge const& ) noexcept; /*= INDIVIDUAL OPTIMISATIONS =================================================*/