Optimizer - Finished function inlining
This commit is contained in:
parent
2c636fb7b5
commit
d3b1883693
3 changed files with 260 additions and 4 deletions
|
@ -474,7 +474,7 @@ void T_InstrListNode::replaceMultiple(
|
|||
children_.addNew( );
|
||||
}
|
||||
const auto newSize{ children_.size( ) };
|
||||
const auto nMove{ oldSize + 1 - index };
|
||||
const auto nMove{ rep.size( ) > 1 ? ( oldSize - index ) : 0 };
|
||||
for ( auto i = 1u ; i < nMove ; i ++ ) {
|
||||
children_[ newSize - i ] = std::move(
|
||||
children_[ oldSize - i ] );
|
||||
|
@ -486,6 +486,8 @@ void T_InstrListNode::replaceMultiple(
|
|||
rep.children_[ i ] );
|
||||
children_[ index + i ]->setParent( *this );
|
||||
}
|
||||
|
||||
rep.children_.clear( );
|
||||
} else {
|
||||
children_.remove( index );
|
||||
}
|
||||
|
|
27
c-opast.hh
27
c-opast.hh
|
@ -622,6 +622,9 @@ class T_SetInstrNode : public A_InstructionNode
|
|||
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
||||
{ return idLocation_; }
|
||||
|
||||
void id( T_String const& nid ) noexcept
|
||||
{ id_ = nid; }
|
||||
|
||||
void setExpression( P_ExpressionNode expression ) noexcept
|
||||
{
|
||||
if ( children_.size( ) ) {
|
||||
|
@ -707,6 +710,13 @@ class T_FramebufferInstrNode : public A_ResourceDefInstrNode
|
|||
T_ArgumentNode* lod( ) const noexcept
|
||||
{ return (T_ArgumentNode*) ( children_.size( )
|
||||
? child( 0 ).get( ) : nullptr ); }
|
||||
|
||||
void id( T_String const& nid ,
|
||||
ebcl::T_SRDLocation const& loc ) noexcept
|
||||
{
|
||||
id_ = nid;
|
||||
location( ) = loc;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -802,6 +812,14 @@ class T_PipelineInstrNode : public A_ResourceDefInstrNode
|
|||
{ return pids_[ index ]; }
|
||||
ebcl::T_SRDLocation const& pLocation( const uint32_t index ) const noexcept
|
||||
{ return pidLocations_[ index ]; }
|
||||
|
||||
void program( const uint32_t index ,
|
||||
T_String const& id ,
|
||||
ebcl::T_SRDLocation const& location ) noexcept
|
||||
{
|
||||
pids_[ index ] = id;
|
||||
pidLocations_[ index ] = location;
|
||||
}
|
||||
};
|
||||
|
||||
// Program loader instruction
|
||||
|
@ -1119,6 +1137,9 @@ class T_UniformsInstrNode : public A_InstructionNode
|
|||
{ return progId_; }
|
||||
ebcl::T_SRDLocation const& progIdLocation( ) const noexcept
|
||||
{ return progIdLocation_; }
|
||||
void progId( T_String const& id ,
|
||||
ebcl::T_SRDLocation const& location ) noexcept
|
||||
{ progId_ = id; progIdLocation_ = location; }
|
||||
|
||||
uint32_t uloc( ) const noexcept
|
||||
{ return uloc_; }
|
||||
|
@ -1171,6 +1192,9 @@ class T_UseInstrNode : public A_InstructionNode
|
|||
{ return id_; }
|
||||
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
||||
{ return idLocation_; }
|
||||
void id( T_String const& nid ,
|
||||
ebcl::T_SRDLocation const& location ) noexcept
|
||||
{ id_ = nid; idLocation_ = location; }
|
||||
};
|
||||
|
||||
// Texture/sampler use instructions
|
||||
|
@ -1203,6 +1227,9 @@ class T_UseTextureInstrNode : public T_UseInstrNode
|
|||
{ return samplerId_; }
|
||||
ebcl::T_SRDLocation const& samplerIdLocation( ) const noexcept
|
||||
{ return samplerIdLocation_; }
|
||||
void samplerId( T_String const& id ,
|
||||
ebcl::T_SRDLocation const& location ) noexcept
|
||||
{ samplerId_ = id; samplerIdLocation_ = location; }
|
||||
};
|
||||
|
||||
// Viewport instruction
|
||||
|
|
235
c-opopt.cc
235
c-opopt.cc
|
@ -1858,6 +1858,8 @@ bool opopt::InlineFunctions(
|
|||
T_String target;
|
||||
T_CallInstrNode* callInstrNode;
|
||||
uint32_t fnIndex;
|
||||
uint32_t nArgs{ 0 };
|
||||
uint32_t nLocals{ 0 };
|
||||
|
||||
T_InlineFunction_(
|
||||
T_String target ,
|
||||
|
@ -1871,6 +1873,7 @@ bool opopt::InlineFunctions(
|
|||
struct T_InlineTarget_ {
|
||||
uint32_t count{ 1 };
|
||||
uint32_t extraLocals{ 0 };
|
||||
T_AutoArray< T_String , 16 > elNames;
|
||||
};
|
||||
|
||||
// Find functions that can be inlined
|
||||
|
@ -1970,11 +1973,12 @@ bool opopt::InlineFunctions(
|
|||
// Compute extra locals required
|
||||
const auto nInlines{ ordered.size( ) };
|
||||
for ( auto i = 0u ; i < nInlines ; i ++ ) {
|
||||
auto const& ifd{ inlineFunctions.values( )[ ordered[ i ] ] };
|
||||
auto& ifd{ inlineFunctions.values( )[ ordered[ i ] ] };
|
||||
auto const& fn{ program.root.function( ifd.fnIndex ) };
|
||||
uint32_t nLocals{ fn.locals( ) };
|
||||
for ( auto j = 0u ; j < fn.locals( ) ; j ++ ) {
|
||||
if ( fn.isArgument( fn.getLocalName( j ) ) ) {
|
||||
ifd.nArgs ++;
|
||||
nLocals --;
|
||||
}
|
||||
}
|
||||
|
@ -1984,11 +1988,234 @@ bool opopt::InlineFunctions(
|
|||
nLocals += asTarget->extraLocals;
|
||||
}
|
||||
|
||||
ifd.nLocals = nLocals;
|
||||
|
||||
auto* target{ inlineTargets.get( ifd.target ) };
|
||||
target->extraLocals = std::max( target->extraLocals , nLocals );
|
||||
}
|
||||
|
||||
// Merge (bottom to top)
|
||||
|
||||
return false;
|
||||
// Add extra locals
|
||||
const auto nTargets{ inlineTargets.size( ) };
|
||||
T_StringBuilder idsb;
|
||||
for ( auto i = 0u ; i < nTargets ; i ++ ) {
|
||||
auto& itd{ inlineTargets.values( )[ i ] };
|
||||
auto& fn{ program.root.function( inlineTargets.keys( )[ i ] ) };
|
||||
for ( auto j = 0u , c = 0u ; c < itd.extraLocals ; j ++ ) {
|
||||
idsb.clear( ) << "*inline*" << j;
|
||||
T_String id{ idsb };
|
||||
if ( !fn.hasLocal( id ) ) {
|
||||
fn.addLocalVariable( id , T_SRDLocation{} );
|
||||
fn.setLocalType( fn.locals( ) - 1 ,
|
||||
opast::E_DataType::VARIABLE );
|
||||
itd.elNames.add( std::move( id ) );
|
||||
c ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge (bottom to top)
|
||||
for ( auto i = 0u ; i < nInlines ; i ++ ) {
|
||||
auto const& ifd{ inlineFunctions.values( )[ i ] };
|
||||
auto const& itd{ *inlineTargets.get( ifd.target ) };
|
||||
auto& src{ program.root.function( ifd.fnIndex ) };
|
||||
auto& call{ *ifd.callInstrNode };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Inlining function " << src.name( );
|
||||
return sb;
|
||||
} , 5 );
|
||||
|
||||
// Replace arguments and locals
|
||||
oData.visitor.visit( src.instructions( ) , [&]( A_Node& node , const bool exit ) {
|
||||
if ( !exit ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ( node.type( ) ) {
|
||||
|
||||
default: break;
|
||||
|
||||
case A_Node::EXPR_ID: {
|
||||
auto const& id{ (T_IdentifierExprNode&) node };
|
||||
if ( !src.hasLocal( id.id( ) ) ) {
|
||||
break;
|
||||
}
|
||||
T_OwnPtr< A_Node > nv;
|
||||
if ( src.isArgument( id.id( ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( id.id( ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
if ( caValue.type( ) == A_Node::EXPR_CONST ) {
|
||||
nv = NewOwned< T_ConstantExprNode >(
|
||||
node.parent( ) ,
|
||||
( (T_ConstantExprNode&) caValue ).floatValue( ) );
|
||||
} else {
|
||||
nv = NewOwned< T_IdentifierExprNode >(
|
||||
node.parent( ) ,
|
||||
( (T_IdentifierExprNode&) caValue ).id( ) );
|
||||
}
|
||||
} else {
|
||||
nv = NewOwned< T_IdentifierExprNode >(
|
||||
node.parent( ) ,
|
||||
itd.elNames[ src.getLocalIndex( id.id( ) ) - ifd.nArgs ] );
|
||||
}
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << id.id( )
|
||||
<< " at " << id.location( )
|
||||
<< " with ";
|
||||
if ( nv->type( ) == A_Node::EXPR_ID ) {
|
||||
sb << "identifier " << ((T_IdentifierExprNode&)*nv).id( );
|
||||
} else {
|
||||
sb << "constant " << ((T_ConstantExprNode&)*nv).floatValue( );
|
||||
}
|
||||
return sb;
|
||||
} , 6 );
|
||||
node.parent( ).replace( node , nv );
|
||||
break;
|
||||
}
|
||||
|
||||
case A_Node::OP_UNIFORMS: {
|
||||
auto& n{ (T_UniformsInstrNode&) node };
|
||||
if ( src.isArgument( n.progId( ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( n.progId( ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
assert( caValue.type( ) == A_Node::EXPR_ID );
|
||||
auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.progId( )
|
||||
<< " at " << n.progIdLocation( )
|
||||
<< " with identifier " << repId;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.progId( repId , caValue.location( ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case A_Node::OP_USE_TEXTURE: {
|
||||
auto& n{ (T_UseTextureInstrNode&) node };
|
||||
if ( src.isArgument( n.samplerId( ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( n.samplerId( ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
assert( caValue.type( ) == A_Node::EXPR_ID );
|
||||
auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.samplerId( )
|
||||
<< " at " << n.samplerIdLocation( )
|
||||
<< " with identifier " << repId;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.samplerId( repId , caValue.location( ) );
|
||||
}
|
||||
} // fallthrough
|
||||
case A_Node::OP_USE_PROGRAM:
|
||||
case A_Node::OP_USE_PIPELINE:
|
||||
case A_Node::OP_USE_FRAMEBUFFER: {
|
||||
auto& n{ (T_UseInstrNode&) node };
|
||||
if ( src.isArgument( n.id( ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( n.id( ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
assert( caValue.type( ) == A_Node::EXPR_ID );
|
||||
auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.id( )
|
||||
<< " at " << n.idLocation( )
|
||||
<< " with identifier " << repId;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.id( repId , caValue.location( ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case A_Node::OP_PIPELINE: {
|
||||
auto& n{ (T_PipelineInstrNode&) node };
|
||||
const auto np{ n.size( ) };
|
||||
for ( auto i = 0u ; i < np ; i ++ ) {
|
||||
if ( src.isArgument( n.program( i ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( n.program( i ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
assert( caValue.type( ) == A_Node::EXPR_ID );
|
||||
auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.program( i )
|
||||
<< " at " << n.pLocation( i )
|
||||
<< " with identifier " << repId;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.program( i , repId , caValue.location( ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case A_Node::TN_FBATT: {
|
||||
auto& n{ (T_FramebufferInstrNode::T_Attachment&) node };
|
||||
if ( src.isArgument( n.id( ) ) ) {
|
||||
const auto argIndex{ src.getLocalIndex( n.id( ) ) };
|
||||
auto const& callArg{ call.argument( argIndex ) };
|
||||
auto const& caValue{ callArg.expression( ) };
|
||||
assert( caValue.type( ) == A_Node::EXPR_ID );
|
||||
auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) };
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.id( )
|
||||
<< " at " << n.location( )
|
||||
<< " with identifier " << repId;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.id( repId , caValue.location( ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case A_Node::OP_SET: {
|
||||
auto& n{ (T_SetInstrNode&) node };
|
||||
if ( !src.hasLocal( n.id( ) ) ) {
|
||||
break;
|
||||
}
|
||||
auto const& nid{
|
||||
itd.elNames[ src.getLocalIndex( n.id( ) ) - ifd.nArgs ]
|
||||
};
|
||||
oData.logger( [&]() {
|
||||
T_StringBuilder sb;
|
||||
sb << "Replacing identifier " << n.id( )
|
||||
<< " at " << n.location( )
|
||||
<< " with identifier " << nid;
|
||||
return sb;
|
||||
} , 6 );
|
||||
n.id( nid );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
|
||||
((T_InstrListNode&) call.parent( )).replaceMultiple(
|
||||
call , &src.instructions( ) );
|
||||
}
|
||||
|
||||
T_AutoArray< T_String , 32 > iffns;
|
||||
iffns.ensureCapacity( nInlines );
|
||||
for ( auto i = 0u ; i < nInlines ; i ++ ) {
|
||||
auto const& ifd{ inlineFunctions.values( )[ i ] };
|
||||
iffns.add( program.root.function( ifd.fnIndex ).name( ) );
|
||||
}
|
||||
for ( auto i = 0u ; i < nInlines ; i ++ ) {
|
||||
program.root.removeFunction( iffns[ i ] );
|
||||
}
|
||||
|
||||
oData.state = {};
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue