Optimizer - Determine order for call inlining
This commit is contained in:
parent
94b01e62b4
commit
1a6509814e
1 changed files with 62 additions and 6 deletions
68
c-opopt.cc
68
c-opopt.cc
|
@ -1854,6 +1854,20 @@ bool opopt::InlineFunctions(
|
||||||
M_LOGSTR_( "... Inlining functions" , 3 );
|
M_LOGSTR_( "... Inlining functions" , 3 );
|
||||||
|
|
||||||
// Find functions that can be inlined
|
// Find functions that can be inlined
|
||||||
|
struct T_InlineFunction_ {
|
||||||
|
T_String target;
|
||||||
|
T_CallInstrNode* callInstrNode;
|
||||||
|
|
||||||
|
T_InlineFunction_(
|
||||||
|
T_String target ,
|
||||||
|
T_CallInstrNode* const call ) noexcept
|
||||||
|
: target( std::move( target ) ) ,
|
||||||
|
callInstrNode( call )
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
T_KeyValueTable< T_String , T_InlineFunction_ > inlineFunctions;
|
||||||
|
T_KeyValueTable< T_String , uint32_t > inlineTargets;
|
||||||
auto const& cfg{ oData.ctrlFlowGraph };
|
auto const& cfg{ oData.ctrlFlowGraph };
|
||||||
for ( auto it = cfg.begin( ) ; it != cfg.end( ) ; it ++ ) {
|
for ( auto it = cfg.begin( ) ; it != cfg.end( ) ; it ++ ) {
|
||||||
auto const& node{ **it };
|
auto const& node{ **it };
|
||||||
|
@ -1882,11 +1896,11 @@ bool opopt::InlineFunctions(
|
||||||
assert( callNode.instructions );
|
assert( callNode.instructions );
|
||||||
const uint32_t callInstrIdx{ callNode.instructions->first
|
const uint32_t callInstrIdx{ callNode.instructions->first
|
||||||
+ callNode.instructions->count - 1 };
|
+ callNode.instructions->count - 1 };
|
||||||
auto const* const instr{ oData.instructions[ callInstrIdx ].node };
|
auto* const instr{ oData.instructions[ callInstrIdx ].node };
|
||||||
assert( instr && dynamic_cast< T_CallInstrNode const* >( instr ) );
|
assert( instr && dynamic_cast< T_CallInstrNode* >( instr ) );
|
||||||
|
|
||||||
// Check call arguments
|
// Check call arguments
|
||||||
auto const& cInstr{ dynamic_cast< T_CallInstrNode const& >( *instr ) };
|
auto& cInstr{ dynamic_cast< T_CallInstrNode& >( *instr ) };
|
||||||
bool ok{ true };
|
bool ok{ true };
|
||||||
for ( auto i = 0u ; i < cInstr.size( ) && ok ; i ++ ) {
|
for ( auto i = 0u ; i < cInstr.size( ) && ok ; i ++ ) {
|
||||||
auto const& arg{ cInstr.argument( i ) };
|
auto const& arg{ cInstr.argument( i ) };
|
||||||
|
@ -1898,16 +1912,58 @@ bool opopt::InlineFunctions(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to inlineable functions list
|
// Add to inlineable functions list
|
||||||
// TODO
|
auto const& caller{ program.root.function( callerId ).name( ) };
|
||||||
|
auto const& callee{ program.root.function( calleeId ).name( ) };
|
||||||
|
inlineFunctions.add( callee , T_InlineFunction_{
|
||||||
|
caller , &cInstr } );
|
||||||
|
auto* const callerCount{ inlineTargets.get( caller ) };
|
||||||
|
if ( callerCount ) {
|
||||||
|
(*callerCount) ++;
|
||||||
|
} else {
|
||||||
|
inlineTargets.add( caller , 1u );
|
||||||
|
}
|
||||||
|
|
||||||
oData.logger( [&](){
|
oData.logger( [&](){
|
||||||
T_StringBuilder sb;
|
T_StringBuilder sb;
|
||||||
sb << "Will inline function "
|
sb << "Will inline function " << callee
|
||||||
<< program.root.function( calleeId ).name( );
|
<< " into " << caller;
|
||||||
return sb;
|
return sb;
|
||||||
} , 4 );
|
} , 4 );
|
||||||
}
|
}
|
||||||
|
if ( inlineFunctions.size( ) == 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Order inline-able functions
|
// Order inline-able functions
|
||||||
|
T_AutoArray< uint32_t , 32 > ordered;
|
||||||
|
ordered.ensureCapacity( inlineFunctions.size( ) );
|
||||||
|
uint32_t index{ 0 };
|
||||||
|
while ( inlineFunctions.size( ) > ordered.size( ) ) {
|
||||||
|
auto const& fn{ inlineFunctions.keys( )[ index ] };
|
||||||
|
if ( !( ordered.contains( index ) || inlineTargets.contains( fn ) ) ) {
|
||||||
|
ordered.add( index );
|
||||||
|
|
||||||
|
auto const& ifd{ inlineFunctions.values( )[ index ] };
|
||||||
|
auto& tCount{ *inlineTargets.get( ifd.target ) };
|
||||||
|
tCount --;
|
||||||
|
if ( tCount == 0 ) {
|
||||||
|
inlineTargets.remove( ifd.target );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index = ( index + 1 ) % inlineFunctions.size( );
|
||||||
|
}
|
||||||
|
oData.logger( [&](){
|
||||||
|
T_StringBuilder sb;
|
||||||
|
sb << "Inlining order: ";
|
||||||
|
for ( auto i = 0u ; i < ordered.size( ) ; i ++ ) {
|
||||||
|
if ( i > 0 ) {
|
||||||
|
sb << ", ";
|
||||||
|
}
|
||||||
|
sb << inlineFunctions.keys( )[ ordered[ i ] ];
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
} , 5 );
|
||||||
|
|
||||||
// Compute extra locals required
|
// Compute extra locals required
|
||||||
// Merge (bottom to top)
|
// Merge (bottom to top)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue