From 1a6509814e5c1c9af678d3f42815d91ccf06f163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sun, 17 Dec 2017 17:27:23 +0100 Subject: [PATCH] Optimizer - Determine order for call inlining --- c-opopt.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/c-opopt.cc b/c-opopt.cc index 4f514f3..55201b7 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -1854,6 +1854,20 @@ bool opopt::InlineFunctions( M_LOGSTR_( "... Inlining functions" , 3 ); // 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 }; for ( auto it = cfg.begin( ) ; it != cfg.end( ) ; it ++ ) { auto const& node{ **it }; @@ -1882,11 +1896,11 @@ bool opopt::InlineFunctions( assert( callNode.instructions ); const uint32_t callInstrIdx{ callNode.instructions->first + callNode.instructions->count - 1 }; - auto const* const instr{ oData.instructions[ callInstrIdx ].node }; - assert( instr && dynamic_cast< T_CallInstrNode const* >( instr ) ); + auto* const instr{ oData.instructions[ callInstrIdx ].node }; + assert( instr && dynamic_cast< T_CallInstrNode* >( instr ) ); // Check call arguments - auto const& cInstr{ dynamic_cast< T_CallInstrNode const& >( *instr ) }; + auto& cInstr{ dynamic_cast< T_CallInstrNode& >( *instr ) }; bool ok{ true }; for ( auto i = 0u ; i < cInstr.size( ) && ok ; i ++ ) { auto const& arg{ cInstr.argument( i ) }; @@ -1898,16 +1912,58 @@ bool opopt::InlineFunctions( } // 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( [&](){ T_StringBuilder sb; - sb << "Will inline function " - << program.root.function( calleeId ).name( ); + sb << "Will inline function " << callee + << " into " << caller; return sb; } , 4 ); } + if ( inlineFunctions.size( ) == 0 ) { + return false; + } // 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 // Merge (bottom to top)