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.
This commit is contained in:
parent
ddad981055
commit
cb42137592
2 changed files with 53 additions and 15 deletions
46
c-opopt.cc
46
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
c-opopt.hh
22
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 =================================================*/
|
||||
|
|
Loading…
Reference in a new issue