Optimizer - Replace curve-less inputs with single default

This commit is contained in:
Emmanuel BENOîT 2017-12-02 10:40:47 +01:00
parent f1b51f564d
commit ffcf2917d5
2 changed files with 74 additions and 18 deletions

View file

@ -10,6 +10,31 @@ using namespace opast;
using namespace opopt; using namespace opopt;
/*= T_OptData ================================================================*/
void T_OptData::findInputDecls(
T_OpsParserOutput& program ) noexcept
{
if ( inputDecls ) {
return;
}
inputDecls = T_KeyValueTable< T_String , T_Array< T_InputDecl > >{ };
visitor.visit( program.root , [this]( A_Node& node , const bool exit ) {
if ( exit && node.type( ) == A_Node::OP_INPUT ) {
auto& input{ (T_InputInstrNode&) node };
auto* da{ inputDecls->get( input.id( ) ) };
if ( !da ) {
inputDecls->add( input.id( ) , T_Array< T_InputDecl >{ } );
da = inputDecls->get( input.id( ) );
}
da->add( T_InputDecl{ input.location( ) , input.defValue( ) } );
}
return true;
} );
}
/*= CONSTANT FOLDING =========================================================*/ /*= CONSTANT FOLDING =========================================================*/
namespace { namespace {
@ -43,6 +68,12 @@ struct T_ConstantFolder_
P_ExpressionNode doIdExpr( P_ExpressionNode doIdExpr(
T_IdentifierExprNode& node ) noexcept; T_IdentifierExprNode& node ) noexcept;
// Handle reads from inputs. If there's a curve and it is a constant,
// or if there's no curve and only one default value, then the
// expression is constant.
P_ExpressionNode doInputExpr(
T_InputExprNode& node ) noexcept;
// Transform an unary operator applied to a constant into a constant. // Transform an unary operator applied to a constant into a constant.
P_ExpressionNode doUnaryOp( P_ExpressionNode doUnaryOp(
T_UnaryOperatorNode& node , T_UnaryOperatorNode& node ,
@ -126,24 +157,7 @@ P_ExpressionNode T_ConstantFolder_::checkExpression(
// Replace inputs with value if no curve/constant curve // Replace inputs with value if no curve/constant curve
if ( node.type( ) == A_Node::EXPR_INPUT ) { if ( node.type( ) == A_Node::EXPR_INPUT ) {
if ( !oData.curves ) { return doInputExpr( (T_InputExprNode&) node );
return {};
}
auto& n{ (T_InputExprNode&) node };
auto const* const curve{ oData.curves->curves.get( n.id( ) ) };
if ( curve ) {
// Curve present, check if it's constant
const auto cval{ curve->isConstant( ) };
if ( !cval ) {
return {};
}
return NewOwned< T_ConstantExprNode >( node.parent( ) , *cval );
}
// TODO: check whether there's only one default value; if that's the case,
// well, we got ourselves a constant.
return {};
} }
// Replace UnOp( Cnst ) with result // Replace UnOp( Cnst ) with result
@ -180,6 +194,34 @@ P_ExpressionNode T_ConstantFolder_::checkExpression(
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
P_ExpressionNode T_ConstantFolder_::doInputExpr(
T_InputExprNode& node ) noexcept
{
if ( !oData.curves ) {
return {};
}
auto const* const curve{ oData.curves->curves.get( node.id( ) ) };
if ( curve ) {
// Curve present, check if it's constant
const auto cval{ curve->isConstant( ) };
if ( !cval ) {
return {};
}
return NewOwned< T_ConstantExprNode >( node.parent( ) , *cval );
}
assert( oData.inputDecls );
auto const* const dva{ oData.inputDecls->get( node.id( ) ) };
assert( dva );
if ( dva->size( ) == 1 ) {
// If there's only one default value, that's a constant.
return NewOwned< T_ConstantExprNode >( node.parent( ) ,
(*dva)[ 0 ].value );
}
return {};
}
P_ExpressionNode T_ConstantFolder_::doIdExpr( P_ExpressionNode T_ConstantFolder_::doIdExpr(
T_IdentifierExprNode& node ) noexcept T_IdentifierExprNode& node ) noexcept
{ {
@ -321,6 +363,9 @@ bool opopt::FoldConstants(
T_OptData& oData ) noexcept T_OptData& oData ) noexcept
{ {
T_ConstantFolder_ folder{ oData }; T_ConstantFolder_ folder{ oData };
if ( oData.curves ) {
oData.findInputDecls( program );
}
oData.visitor.visit( program.root , folder ); oData.visitor.visit( program.root , folder );
return folder.didFold; return folder.didFold;
} }

View file

@ -23,6 +23,17 @@ struct T_OptData
// A visitor to be used for the tree // A visitor to be used for the tree
ebcl::T_Visitor< opast::A_Node > visitor{ opast::ASTVisitorBrowser }; ebcl::T_Visitor< opast::A_Node > visitor{ opast::ASTVisitorBrowser };
// Table of input declarations; used to fold constant inputs.
struct T_InputDecl {
ebcl::T_SRDLocation location;
float value;
};
T_Optional< T_KeyValueTable< T_String , T_Array< T_InputDecl > > > inputDecls;
//----------------------------------------------------------------------
void findInputDecls( T_OpsParserOutput& program ) noexcept;
}; };
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/