Optimizer - Constant propagation for variables
* It doesn't work for function arguments at this point, but shouldn't be too hard to implement that. * Can't use it to its full potential mostly because I need to get rid of the node-specific shit in the AST.
This commit is contained in:
parent
f574780c5e
commit
efa1b26150
4 changed files with 144 additions and 3 deletions
34
c-opast.cc
34
c-opast.cc
|
@ -32,6 +32,15 @@ T_RootNode& A_Node::root( ) const noexcept
|
||||||
const_cast< A_Node* >( node ) );
|
const_cast< A_Node* >( node ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void A_Node::replaceChild(
|
||||||
|
A_Node const& /*child*/ ,
|
||||||
|
T_OwnPtr< A_Node > /*replacement*/
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
fprintf( stderr , "replaceChild called on invalid node\n" );
|
||||||
|
std::terminate( );
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
A_Node* opast::ASTVisitorBrowser(
|
A_Node* opast::ASTVisitorBrowser(
|
||||||
|
@ -492,6 +501,19 @@ T_BinaryOperatorNode::T_BinaryOperatorNode(
|
||||||
})( ) , parent ) , op_( op )
|
})( ) , parent ) , op_( op )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
void T_BinaryOperatorNode::replaceChild(
|
||||||
|
A_Node const& child ,
|
||||||
|
T_OwnPtr< A_Node > replacement
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
if ( right_.get( ) == &child ) {
|
||||||
|
right_ = std::move( replacement );
|
||||||
|
} else {
|
||||||
|
assert( left_.get( ) == &child );
|
||||||
|
left_ = std::move( replacement );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= T_FramebufferInstrNode ===================================================*/
|
/*= T_FramebufferInstrNode ===================================================*/
|
||||||
|
|
||||||
|
@ -629,7 +651,17 @@ T_Optional< T_SRDLocation > T_LocalsInstrNode::addVariable(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= T_CondInstrNode ============================================================*/
|
/*= T_CondInstrNode ==========================================================*/
|
||||||
|
|
||||||
|
void T_CondInstrNode::T_Expression::replaceChild(
|
||||||
|
A_Node const& child ,
|
||||||
|
T_OwnPtr< A_Node > replacement ) noexcept
|
||||||
|
{
|
||||||
|
assert( expression_.get( ) == &child );
|
||||||
|
expression_ = std::move( replacement );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void T_CondInstrNode::setExpression(
|
void T_CondInstrNode::setExpression(
|
||||||
P_ExpressionNode expression ) noexcept
|
P_ExpressionNode expression ) noexcept
|
||||||
|
|
12
c-opast.hh
12
c-opast.hh
|
@ -94,6 +94,10 @@ class A_Node
|
||||||
{ assert( parent_ ); return *parent_; }
|
{ assert( parent_ ); return *parent_; }
|
||||||
|
|
||||||
T_RootNode& root( ) const noexcept;
|
T_RootNode& root( ) const noexcept;
|
||||||
|
|
||||||
|
virtual void replaceChild(
|
||||||
|
A_Node const& child ,
|
||||||
|
T_OwnPtr< A_Node > replacement ) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Browser function to be used with T_Visitor
|
// Browser function to be used with T_Visitor
|
||||||
|
@ -460,6 +464,10 @@ class T_CondInstrNode : public A_InstructionNode
|
||||||
|
|
||||||
void expression( P_ExpressionNode expr ) noexcept
|
void expression( P_ExpressionNode expr ) noexcept
|
||||||
{ assert( expr ); expression_ = std::move( expr ); }
|
{ assert( expr ); expression_ = std::move( expr ); }
|
||||||
|
|
||||||
|
void replaceChild(
|
||||||
|
A_Node const& child ,
|
||||||
|
T_OwnPtr< A_Node > replacement ) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class T_ValuedCase : public A_Node
|
class T_ValuedCase : public A_Node
|
||||||
|
@ -1362,6 +1370,10 @@ class T_BinaryOperatorNode : public A_ExpressionNode
|
||||||
{ return *right_; }
|
{ return *right_; }
|
||||||
A_ExpressionNode& right( ) noexcept
|
A_ExpressionNode& right( ) noexcept
|
||||||
{ return *right_; }
|
{ return *right_; }
|
||||||
|
|
||||||
|
void replaceChild(
|
||||||
|
A_Node const& child ,
|
||||||
|
T_OwnPtr< A_Node > replacement ) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
97
c-opopt.cc
97
c-opopt.cc
|
@ -1441,6 +1441,41 @@ bool opopt::FoldConstants(
|
||||||
|
|
||||||
|
|
||||||
/*= CONSTANT PROPAGATION =====================================================*/
|
/*= CONSTANT PROPAGATION =====================================================*/
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void CPReplaceWithConstant_(
|
||||||
|
A_InstructionNode& instruction ,
|
||||||
|
T_OptData::T_VarId const& var ,
|
||||||
|
const double value ,
|
||||||
|
T_OptData& oData
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
oData.visitor.visit( instruction , [&]( A_Node& node , const bool exit ) {
|
||||||
|
if ( !exit || node.type( ) != A_Node::EXPR_ID ) {
|
||||||
|
return node.type( ) != A_Node::ILIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& eid{ (T_IdentifierExprNode&) node };
|
||||||
|
if ( eid.id( ) != var.name ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& p{ eid.parent( ) };
|
||||||
|
auto replacement{ NewOwned< T_ConstantExprNode >( p , value ) };
|
||||||
|
replacement->location( ) = eid.location( );
|
||||||
|
p.replaceChild( eid , std::move( replacement ) );
|
||||||
|
oData.logger( [&]() {
|
||||||
|
T_StringBuilder sb;
|
||||||
|
sb << "Propagated constant from " << var.name
|
||||||
|
<< " at " << instruction.location( )
|
||||||
|
<< " (value " << value << ")";
|
||||||
|
return sb;
|
||||||
|
} , LL2 );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace <anon>
|
||||||
|
|
||||||
bool opopt::PropagateConstants(
|
bool opopt::PropagateConstants(
|
||||||
T_OpsParserOutput& program ,
|
T_OpsParserOutput& program ,
|
||||||
|
@ -1463,7 +1498,67 @@ bool opopt::PropagateConstants(
|
||||||
oData.buildUseDefineChains( program );
|
oData.buildUseDefineChains( program );
|
||||||
M_LOGSTR_( "... Propagating constants" , 2 );
|
M_LOGSTR_( "... Propagating constants" , 2 );
|
||||||
|
|
||||||
return false;
|
T_Set< uint32_t > cDefs{ UseTag< ArrayBacked< 16 > >( ) };
|
||||||
|
T_AutoArray< double , 16 > cValues;
|
||||||
|
bool changesMade{ false };
|
||||||
|
for ( auto const& udc : oData.varUDChains.values( ) ) {
|
||||||
|
cDefs.clear( );
|
||||||
|
cValues.clear( );
|
||||||
|
|
||||||
|
// Find all constant definitions
|
||||||
|
const auto nDefs{ udc.defines.size( ) };
|
||||||
|
for ( auto i = 0u ; i < nDefs ; i ++ ) {
|
||||||
|
auto const& def{ udc.defines[ i ] };
|
||||||
|
auto const* const ri{ oData.instructions[ def.node ].node };
|
||||||
|
if ( ri->type( ) == A_Node::OP_SET ) {
|
||||||
|
auto const* const si{
|
||||||
|
dynamic_cast< T_SetInstrNode const* >( ri ) };
|
||||||
|
if ( si->expression( ).type( ) == A_Node::EXPR_CONST ) {
|
||||||
|
cDefs.add( i );
|
||||||
|
cValues.add( ( (T_ConstantExprNode&) si->expression( ) ).floatValue( ) );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Instruction is not supported, exit
|
||||||
|
assert( cDefs.size( ) == 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert( cValues.size( ) == cDefs.size( ) );
|
||||||
|
if ( cValues.empty( ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto nUses{ udc.uses.size( ) };
|
||||||
|
for ( auto i = 0u ; i < nUses ; i ++ ) {
|
||||||
|
auto const& use{ udc.uses[ i ] };
|
||||||
|
const auto nRefs{ use.refs.size( ) };
|
||||||
|
T_Optional< double > repVal{ };
|
||||||
|
for ( auto j = 0u ; j < nRefs ; j ++ ) {
|
||||||
|
const auto dIdx{ cDefs.indexOf( use.refs[ j ] ) };
|
||||||
|
if ( dIdx == -1 ) {
|
||||||
|
repVal.clear( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( !repVal ) {
|
||||||
|
repVal = cValues[ dIdx ];
|
||||||
|
} else if ( *repVal != cValues[ dIdx ] ) {
|
||||||
|
repVal.clear( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !repVal ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf( "Could replace use at %d with constant %f\n" ,
|
||||||
|
use.node , *repVal );
|
||||||
|
CPReplaceWithConstant_( *oData.instructions[ use.node ].node ,
|
||||||
|
udc.var , *repVal , oData );
|
||||||
|
changesMade = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changesMade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
(1920 1080)
|
(1920 1080)
|
||||||
)
|
)
|
||||||
(optimizer on
|
(optimizer on
|
||||||
(constant-folding on)
|
(constant-folding on
|
||||||
|
# (fixed-resolution on)
|
||||||
|
)
|
||||||
(constant-propagation on)
|
(constant-propagation on)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue