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-ops.cc \
|
||||||
c-opast.cc \
|
c-opast.cc \
|
||||||
|
c-opopt.cc \
|
||||||
c-opparser.cc \
|
c-opparser.cc \
|
||||||
c-opcomp.cc \
|
c-opcomp.cc \
|
||||||
c-opmgr.cc \
|
c-opmgr.cc \
|
||||||
|
|
|
@ -215,6 +215,9 @@ class T_ArgumentNode : public A_Node
|
||||||
{ return *expr_; }
|
{ return *expr_; }
|
||||||
bool isIdentifier( ) const noexcept
|
bool isIdentifier( ) const noexcept
|
||||||
{ return expr_->type( ) == EXPR_ID; }
|
{ return expr_->type( ) == EXPR_ID; }
|
||||||
|
|
||||||
|
void expression( P_ExpressionNode expr ) noexcept
|
||||||
|
{ assert( expr ); expr_ = std::move( expr ); }
|
||||||
};
|
};
|
||||||
using P_ArgumentNode = T_OwnPtr< T_ArgumentNode >;
|
using P_ArgumentNode = T_OwnPtr< T_ArgumentNode >;
|
||||||
|
|
||||||
|
@ -454,6 +457,9 @@ class T_CondInstrNode : public A_InstructionNode
|
||||||
|
|
||||||
A_ExpressionNode& expression( ) const noexcept
|
A_ExpressionNode& expression( ) const noexcept
|
||||||
{ return *expression_; }
|
{ return *expression_; }
|
||||||
|
|
||||||
|
void expression( P_ExpressionNode expr ) noexcept
|
||||||
|
{ assert( expr ); expression_ = std::move( expr ); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class T_ValuedCase : public A_Node
|
class T_ValuedCase : public A_Node
|
||||||
|
|
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