Builder tool - Various, pre-constant propagation

+ Prepared flags for constant propagation
+ UI instructions removal in compiler
+ Various changes to test "demo"
This commit is contained in:
Emmanuel BENOîT 2017-12-03 14:59:39 +01:00
parent c4ce6e90d7
commit c7e4ccf67e
9 changed files with 104 additions and 52 deletions

View file

@ -79,6 +79,22 @@ bool BCLResolutions_( T_SRDParserData const& data )
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
F_SRDHandler BCLToggle_(
ptrdiff_t const fldOffset ) noexcept
{
return [=]( T_SRDParserData const& d ) -> bool {
auto const& in{ *d.input };
char* bCfg{ (char*) &d.currentData->value< T_BuildConfiguration >( ) };
*(bool*)( bCfg + fldOffset ) = ( in[ 1 ].stringValue( ) == "on" );
return true;
};
}
#define M_BCL_TOGGLE_( N ) \
BCLToggle_( offsetof( T_BuildConfiguration , N ) )
/*----------------------------------------------------------------------------*/
T_SRDParserConfig BCLInitDefinitions_( ) noexcept T_SRDParserConfig BCLInitDefinitions_( ) noexcept
{ {
using namespace ebcl::SRD; using namespace ebcl::SRD;
@ -116,40 +132,20 @@ T_SRDParserConfig BCLInitDefinitions_( ) noexcept
defs.context( "optim" ) defs.context( "optim" )
<< ( Rule( ) << "constant-folding" << "off" << ( Rule( ) << "constant-folding" << "off"
<< []( T_SRDParserData const& d ) -> bool { << M_BCL_TOGGLE_( constantFolding ) )
auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) };
bCfg.constantFolding = false;
return true;
} )
<< ( Rule( ) << "constant-folding" << "on" << EnterContext( "opt-cf" ) << ( Rule( ) << "constant-folding" << "on" << EnterContext( "opt-cf" )
<< []( T_SRDParserData const& d ) -> bool { << M_BCL_TOGGLE_( constantFolding ) )
auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; << ( Rule( ) << "constant-propagation" << Enum( "on-off" )
bCfg.constantFolding = true; << M_BCL_TOGGLE_( constantPropagation ) )
return true;
} )
<< ( Rule( ) << "dead-code-elimination" << Enum( "on-off" ) << ( Rule( ) << "dead-code-elimination" << Enum( "on-off" )
<< []( T_SRDParserData const& d ) -> bool { << M_BCL_TOGGLE_( deadCodeElimination ) )
auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) };
bCfg.deadCodeElimination = true;
return true;
} )
; ;
defs.context( "opt-cf" ) defs.context( "opt-cf" )
<< ( Rule( ) << "fixed-resolution" << Enum( "on-off" ) << ( Rule( ) << "fixed-resolution" << Enum( "on-off" )
<< []( T_SRDParserData const& d ) -> bool { << M_BCL_TOGGLE_( cfFixedSize ) )
auto const& in{ *d.input };
auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) };
bCfg.cfFixedSize = ( in[ 1 ].stringValue( ) == "on" );
return true;
} )
<< ( Rule( ) << "inputs" << Enum( "on-off" ) << ( Rule( ) << "inputs" << Enum( "on-off" )
<< []( T_SRDParserData const& d ) -> bool { << M_BCL_TOGGLE_( cfInputs ) )
auto const& in{ *d.input };
auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) };
bCfg.cfInputs = ( in[ 1 ].stringValue( ) == "on" );
return true;
} )
; ;
return T_SRDParserConfig{ defs }; return T_SRDParserConfig{ defs };

View file

@ -27,6 +27,10 @@ struct T_BuildConfiguration
// Get rid of (get-input) for constant or undefined curves // Get rid of (get-input) for constant or undefined curves
bool cfInputs{ false }; bool cfInputs{ false };
// Constant propagation ------------------------------------------------
bool constantPropagation{ false };
// Dead code elimination ----------------------------------------------- // Dead code elimination -----------------------------------------------
bool deadCodeElimination{ false }; bool deadCodeElimination{ false };

View file

@ -16,13 +16,17 @@ namespace {
struct T_CompilerImpl_ struct T_CompilerImpl_
{ {
T_CompilerImpl_( F_OPLogger* logger ) noexcept T_CompilerImpl_( F_OPLogger* const logger ,
: logger( *logger ) {} const bool noUIInstructions ) noexcept
: logger( *logger ) , noUIInstructions( noUIInstructions )
{}
P_OpProgram compile( T_OpsParserOutput const& input ) noexcept; P_OpProgram compile( T_OpsParserOutput const& input ) noexcept;
private: private:
F_OPLogger& logger; F_OPLogger& logger;
const bool noUIInstructions;
T_Visitor< A_Node > astVisitor{ ASTVisitorBrowser }; T_Visitor< A_Node > astVisitor{ ASTVisitorBrowser };
T_Set< uint32_t > constants{ UseTag< IndexBacked< > >( ) }; T_Set< uint32_t > constants{ UseTag< IndexBacked< > >( ) };
T_KeyValueTable< T_String , uint32_t > locations; T_KeyValueTable< T_String , uint32_t > locations;
@ -650,6 +654,9 @@ bool T_CompilerImpl_::compileNode(
//- DEBUGGING / UI CONTROLS ----------------------------------------------------------- //- DEBUGGING / UI CONTROLS -----------------------------------------------------------
case A_Node::OP_PROFILE: case A_Node::OP_PROFILE:
if ( noUIInstructions ) {
break;
}
if ( exit ) { if ( exit ) {
addInstruction( OP_UI_PEXIT , node.location( ) ); addInstruction( OP_UI_PEXIT , node.location( ) );
} else { } else {
@ -663,6 +670,9 @@ bool T_CompilerImpl_::compileNode(
break; break;
case A_Node::OP_INPUT: case A_Node::OP_INPUT:
if ( noUIInstructions ) {
break;
}
if ( exit ) { if ( exit ) {
auto& in( (T_InputInstrNode&) node ); auto& in( (T_InputInstrNode&) node );
T_OpValue value; T_OpValue value;
@ -675,6 +685,9 @@ bool T_CompilerImpl_::compileNode(
break; break;
case A_Node::OP_ODBG: case A_Node::OP_ODBG:
if ( noUIInstructions ) {
break;
}
if ( exit ) { if ( exit ) {
auto& n( (T_OutputDebugInstrNode&) node ); auto& n( (T_OutputDebugInstrNode&) node );
if ( ! output->uiStrings.contains( n.description( ) ) ) { if ( ! output->uiStrings.contains( n.description( ) ) ) {
@ -689,6 +702,9 @@ bool T_CompilerImpl_::compileNode(
break; break;
case A_Node::OP_OVERRIDES: case A_Node::OP_OVERRIDES:
if ( noUIInstructions ) {
break;
}
if ( exit ) { if ( exit ) {
auto& n{ (T_OverridesInstrNode&) node }; auto& n{ (T_OverridesInstrNode&) node };
const auto idx{ output->overrides.add( n.extractRoot( ) ) }; const auto idx{ output->overrides.add( n.extractRoot( ) ) };
@ -917,8 +933,9 @@ void T_CompilerImpl_::applyStackEffects(
/*= T_OpsCompiler ==============================================================*/ /*= T_OpsCompiler ==============================================================*/
T_OpsCompiler::T_OpsCompiler( ) noexcept T_OpsCompiler::T_OpsCompiler(
: A_PrivateImplementation( new T_CompilerImpl_( &logger_ ) ) const bool noUIInstructions ) noexcept
: A_PrivateImplementation( new T_CompilerImpl_( &logger_ , noUIInstructions ) )
{ } { }
P_OpProgram T_OpsCompiler::compile( P_OpProgram T_OpsCompiler::compile(

View file

@ -57,7 +57,7 @@ class T_OpsCompiler : public ebcl::A_PrivateImplementation
F_OPLogger logger_{ []( auto , auto ) { } }; F_OPLogger logger_{ []( auto , auto ) { } };
public: public:
T_OpsCompiler( ) noexcept; T_OpsCompiler( bool noUIInstructions = false ) noexcept;
void setLogger( F_OPLogger logger ) void setLogger( F_OPLogger logger )
{ {

View file

@ -392,6 +392,27 @@ bool opopt::FoldConstants(
} }
/*= CONSTANT PROPAGATION =====================================================*/
bool opopt::PropagateConstants(
T_OpsParserOutput& program ,
T_OptData& optData ) noexcept
{
// We need to follow the general execution flow of the program. This is
// not as straightforward as it seems.
// - Handling locals is rather easy as they "die" at the end of
// the function in which they are defined.
// - Handling variables in init and functions that are called only
// from init is not too hard: once a variable is set to a constant, it
// can be substituted until the next set instruction.
// - Other variables need additional checks before propagating.
// For example, if a variable is set to a constant during init, but is
// updated at the end of the frame function, the value cannot be
// propagated.
return false;
}
/*= DEAD CODE REMOVAL ========================================================*/ /*= DEAD CODE REMOVAL ========================================================*/
bool opopt::RemoveDeadCode( bool opopt::RemoveDeadCode(

View file

@ -39,18 +39,28 @@ struct T_OptData
void findInputDecls( T_OpsParserOutput& program ) noexcept; void findInputDecls( T_OpsParserOutput& program ) noexcept;
}; };
/*----------------------------------------------------------------------------*/
// Attempts to fold constant expressions into single constants. Returns true if /*= INDIVIDUAL OPTIMISATIONS =================================================*/
// transformations were made, false if not. // All functions below return true if transformations were made, false if not.
// Attempts to fold constant expressions into single constants.
// //
bool FoldConstants( T_OpsParserOutput& program , bool FoldConstants(
T_OpsParserOutput& program ,
T_OptData& optData ) noexcept;
// Attempts to propagate values from variables that contain constants to the
// locations at which they are used.
//
bool PropagateConstants(
T_OpsParserOutput& program ,
T_OptData& optData ) noexcept; T_OptData& optData ) noexcept;
// Attempt to remove blocks of code that will not be executed because of // Attempt to remove blocks of code that will not be executed because of
// constant conditions. Returns true if transformations were made, false if not. // constant conditions.
// //
bool RemoveDeadCode( T_OpsParserOutput& program , bool RemoveDeadCode(
T_OpsParserOutput& program ,
T_OptData& optData ) noexcept; T_OptData& optData ) noexcept;

View file

@ -132,7 +132,7 @@ int main( int argc , char** argv )
break; break;
case 'c': case 'c':
if ( oSrcPath ) { if ( oBuildCfg ) {
fprintf( stderr , "Duplicate build configuration\n" ); fprintf( stderr , "Duplicate build configuration\n" );
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -252,22 +252,18 @@ int main( int argc , char** argv )
bool doneStuff; bool doneStuff;
do { do {
doneStuff = false; doneStuff = false;
if ( cfg.constantFolding ) { if ( cfg.constantFolding && opopt::FoldConstants( *parsed , od ) ) {
while ( opopt::FoldConstants( *parsed , od ) ) { doneStuff = true;
doneStuff = true;
}
} }
if ( cfg.deadCodeElimination ) { if ( cfg.deadCodeElimination && opopt::RemoveDeadCode( *parsed , od ) ) {
while ( opopt::RemoveDeadCode( *parsed , od ) ) { doneStuff = true;
doneStuff = true;
}
} }
} while ( doneStuff ); } while ( doneStuff );
} }
// Compile // Compile
M_LOGSTR( "Compiling script" , 1 ); M_LOGSTR( "Compiling script" , 1 );
T_OpsCompiler compiler; T_OpsCompiler compiler( true );
compiler.setLogger( logger ); compiler.setLogger( logger );
compiler.compile( *parsed ); compiler.compile( *parsed );
return 0; return 0;

View file

@ -1,4 +1,4 @@
(cfg "Default" (cfg "Optimized"
(resolutions (resolutions
(1280 720) (1280 720)
(1920 1080) (1920 1080)
@ -7,3 +7,11 @@
(constant-folding on) (constant-folding on)
) )
) )
(cfg "Basic"
(resolutions
(1280 720)
(1920 1080)
)
(optimizer off)
)

View file

@ -1,7 +1,7 @@
(duration 0.133333 450) (duration 0.133333 450)
(camera-nearplane (camera-nearplane
(segment linear (segment smooth
(values 1.1547 1.1547 4.82843) (values 1.1547 1.1547 4.82843)
(durations 225 225) (durations 225 225)
) )
@ -9,7 +9,7 @@
(camera-pos-x (camera-pos-x
(segment linear (segment linear
(values -300 -150 0) (values -4000 -2000 0)
(durations 225 225) (durations 225 225)
) )
) )
@ -51,7 +51,7 @@
(camera-lookat-x (camera-lookat-x
(segment linear (segment linear
(values -300 -150 0) (values -4000 -2000 0)
(durations 225 225) (durations 225 225)
) )
) )