Optimizer - Began working on constant folding
This commit is contained in:
parent
59b23de5ed
commit
0175bed077
4 changed files with 218 additions and 2 deletions
1
Makefile
1
Makefile
|
@ -34,6 +34,7 @@ COMMON = \
|
|||
\
|
||||
c-ops.cc \
|
||||
c-opast.cc \
|
||||
c-opopt.cc \
|
||||
c-opparser.cc \
|
||||
c-opcomp.cc \
|
||||
c-opmgr.cc \
|
||||
|
|
10
c-opast.hh
10
c-opast.hh
|
@ -215,6 +215,9 @@ class T_ArgumentNode : public A_Node
|
|||
{ return *expr_; }
|
||||
bool isIdentifier( ) const noexcept
|
||||
{ return expr_->type( ) == EXPR_ID; }
|
||||
|
||||
void expression( P_ExpressionNode expr ) noexcept
|
||||
{ assert( expr ); expr_ = std::move( expr ); }
|
||||
};
|
||||
using P_ArgumentNode = T_OwnPtr< T_ArgumentNode >;
|
||||
|
||||
|
@ -454,6 +457,9 @@ class T_CondInstrNode : public A_InstructionNode
|
|||
|
||||
A_ExpressionNode& expression( ) const noexcept
|
||||
{ return *expression_; }
|
||||
|
||||
void expression( P_ExpressionNode expr ) noexcept
|
||||
{ assert( expr ); expression_ = std::move( expr ); }
|
||||
};
|
||||
|
||||
class T_ValuedCase : public A_Node
|
||||
|
@ -1216,8 +1222,8 @@ class T_ConstantExprNode : public A_ExpressionNode
|
|||
|
||||
T_ConstantExprNode( A_Node& parent ,
|
||||
int64_t value ) noexcept
|
||||
: A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( false ) ,
|
||||
vFloat_( value ) , vInt_( value )
|
||||
: A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( false ) ,
|
||||
vFloat_( value ) , vInt_( value )
|
||||
{ }
|
||||
|
||||
T_ConstantExprNode( A_Node& parent ,
|
||||
|
|
172
c-opopt.cc
Normal file
172
c-opopt.cc
Normal file
|
@ -0,0 +1,172 @@
|
|||
#include "externals.hh"
|
||||
|
||||
#include "c-opopt.hh"
|
||||
#include "c-sync.hh"
|
||||
|
||||
using namespace ebcl;
|
||||
using namespace opast;
|
||||
using namespace opopt;
|
||||
|
||||
|
||||
// Macro to use either the specified visitor or a visitor created just for the
|
||||
// occation
|
||||
#define M_VISITOR_( E ) \
|
||||
T_OwnPtr< T_Visitor< A_Node > > localVisitor_; \
|
||||
if ( !(E) ) { \
|
||||
localVisitor_ = NewOwned< T_Visitor< A_Node > >( ASTVisitorBrowser ); \
|
||||
} \
|
||||
T_Visitor< A_Node >& visitor{ (E) ? *(E) : *localVisitor_ }
|
||||
|
||||
|
||||
|
||||
/*= CONSTANT FOLDING =========================================================*/
|
||||
|
||||
namespace {
|
||||
|
||||
struct T_ConstantFolder_
|
||||
{
|
||||
// Input
|
||||
T_Optional< std::pair< uint32_t , uint32_t > > fixedSize;
|
||||
T_SyncCurves const* curves;
|
||||
|
||||
// Result
|
||||
bool didFold{ false };
|
||||
|
||||
bool operator()( A_Node& node , bool exit ) noexcept;
|
||||
|
||||
private:
|
||||
using F_ExprGet_ = std::function< A_ExpressionNode&( A_Node& ) >;
|
||||
using F_ExprSet_ = std::function< void( A_Node& , P_ExpressionNode ) >;
|
||||
|
||||
void handleParentNode(
|
||||
A_Node& node ,
|
||||
F_ExprGet_ get ,
|
||||
F_ExprSet_ set ) noexcept;
|
||||
|
||||
P_ExpressionNode checkExpression(
|
||||
A_ExpressionNode const& node ) noexcept;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
bool T_ConstantFolder_::operator()(
|
||||
A_Node& node ,
|
||||
const bool exit ) noexcept
|
||||
{
|
||||
if ( exit ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ( node.type( ) ) {
|
||||
|
||||
case A_Node::TN_ARG:
|
||||
handleParentNode( node ,
|
||||
[]( A_Node& n ) -> A_ExpressionNode& {
|
||||
return ((T_ArgumentNode&)n).expression( );
|
||||
} ,
|
||||
[]( A_Node& n , P_ExpressionNode e ) {
|
||||
((T_ArgumentNode&)n).expression( std::move( e ) );
|
||||
} );
|
||||
return false;
|
||||
|
||||
case A_Node::TN_CONDITION:
|
||||
handleParentNode( node ,
|
||||
[]( A_Node& n ) -> A_ExpressionNode& {
|
||||
return ((T_CondInstrNode::T_Expression&)n).expression( );
|
||||
} ,
|
||||
[]( A_Node& n , P_ExpressionNode e ) {
|
||||
((T_CondInstrNode::T_Expression&)n).expression( std::move( e ) );
|
||||
} );
|
||||
return false;
|
||||
|
||||
case A_Node::OP_SET:
|
||||
handleParentNode( node ,
|
||||
[]( A_Node& n ) -> A_ExpressionNode& {
|
||||
return ((T_SetInstrNode&)n).expression( );
|
||||
} ,
|
||||
[]( A_Node& n , P_ExpressionNode e ) {
|
||||
((T_SetInstrNode&)n).setExpression( std::move( e ) );
|
||||
} );
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void T_ConstantFolder_::handleParentNode(
|
||||
A_Node& node ,
|
||||
F_ExprGet_ get ,
|
||||
F_ExprSet_ set ) noexcept
|
||||
{
|
||||
auto r{ checkExpression( get( node ) ) };
|
||||
if ( r ) {
|
||||
set( node , std::move( r ) );
|
||||
didFold = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
P_ExpressionNode T_ConstantFolder_::checkExpression(
|
||||
A_ExpressionNode const& node ) noexcept
|
||||
{
|
||||
#warning TODO optimize the fuck
|
||||
// 1/ Replace inputs with value if no curve/constant curve
|
||||
// Replace $width/$height with value if fixedSize
|
||||
// 2/ Replace UnOp( Cnst ) with result
|
||||
// Replace BinOp( Cnst , Cnst ) with result
|
||||
// 3/ Try to find other optimisations, e.g. for Add( Cnst , Add( Cnst , Expr ) )
|
||||
|
||||
if ( node.type( ) == A_Node::EXPR_ID ) {
|
||||
if ( !fixedSize ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
T_IdentifierExprNode& n{ (T_IdentifierExprNode&) node };
|
||||
if ( n.id( ) == "width" ) {
|
||||
auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) ,
|
||||
double( fixedSize->first ) ) };
|
||||
c->location( ) = n.location( );
|
||||
return c;
|
||||
}
|
||||
if ( n.id( ) == "height" ) {
|
||||
auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) ,
|
||||
float( fixedSize->second ) ) };
|
||||
c->location( ) = n.location( );
|
||||
return c;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace <anon>
|
||||
|
||||
|
||||
bool opopt::FoldConstants(
|
||||
T_RootNode& root ,
|
||||
const T_Optional< std::pair< uint32_t , uint32_t > > fixedSize ,
|
||||
T_SyncCurves const* curves ,
|
||||
T_Visitor< A_Node >* const extVisitor ) noexcept
|
||||
{
|
||||
M_VISITOR_( extVisitor );
|
||||
T_ConstantFolder_ folder;
|
||||
folder.fixedSize = fixedSize;
|
||||
folder.curves = curves;
|
||||
visitor.visit( root , folder );
|
||||
return folder.didFold;
|
||||
}
|
||||
|
||||
|
||||
/*= DEAD CODE REMOVAL ========================================================*/
|
||||
|
||||
bool opopt::RemoveDeadCode( opast::T_RootNode& root ,
|
||||
ebcl::T_Visitor< opast::A_Node >* extVisitor ) noexcept
|
||||
{
|
||||
M_VISITOR_( extVisitor );
|
||||
|
||||
#warning blargh
|
||||
return false;
|
||||
}
|
37
c-opopt.hh
Normal file
37
c-opopt.hh
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
#include "c-opast.hh"
|
||||
|
||||
#include <ebcl/Algorithms.hh>
|
||||
|
||||
struct T_SyncCurves;
|
||||
|
||||
namespace opopt {
|
||||
|
||||
// Attempts to fold constant expressions into single constants. Returns true if
|
||||
// transformations were made, false if not.
|
||||
//
|
||||
// Parameters:
|
||||
// root the root node
|
||||
// fixedSize the size of the output, if it is fixed
|
||||
// curves the curves that will be bound to the inputs
|
||||
// extVisitor a node visitor instance to be used instead of creating
|
||||
// one
|
||||
//
|
||||
bool FoldConstants( opast::T_RootNode& root ,
|
||||
T_Optional< std::pair< uint32_t , uint32_t > > fixedSize = { } ,
|
||||
T_SyncCurves const* curves = nullptr ,
|
||||
ebcl::T_Visitor< opast::A_Node >* extVisitor = nullptr ) noexcept;
|
||||
|
||||
// Attempt to remove blocks of code that will not be executed because of
|
||||
// constant conditions. Returns true if transformations were made, false if not.
|
||||
//
|
||||
// Parameters:
|
||||
// root the root node
|
||||
// extVisitor a node visitor instance to be used instead of creating
|
||||
// one
|
||||
//
|
||||
bool RemoveDeadCode( opast::T_RootNode& root ,
|
||||
ebcl::T_Visitor< opast::A_Node >* extVisitor = nullptr ) noexcept;
|
||||
|
||||
|
||||
} // namespace opopt
|
Loading…
Reference in a new issue