Swap literals to the end if optimizing.

This commit is contained in:
Christian 2014-12-11 17:35:23 +01:00
parent 6fcdfdc353
commit 66d95abfd9
6 changed files with 42 additions and 18 deletions

View File

@ -246,7 +246,7 @@ bool Compiler::visit(FunctionDefinition const& _function)
bool Compiler::visit(IfStatement const& _ifStatement) bool Compiler::visit(IfStatement const& _ifStatement)
{ {
ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition()); compileExpression(_ifStatement.getCondition());
eth::AssemblyItem trueTag = m_context.appendConditionalJump(); eth::AssemblyItem trueTag = m_context.appendConditionalJump();
if (_ifStatement.getFalseStatement()) if (_ifStatement.getFalseStatement())
_ifStatement.getFalseStatement()->accept(*this); _ifStatement.getFalseStatement()->accept(*this);
@ -265,7 +265,7 @@ bool Compiler::visit(WhileStatement const& _whileStatement)
m_breakTags.push_back(loopEnd); m_breakTags.push_back(loopEnd);
m_context << loopStart; m_context << loopStart;
ExpressionCompiler::compileExpression(m_context, _whileStatement.getCondition()); compileExpression(_whileStatement.getCondition());
m_context << eth::Instruction::ISZERO; m_context << eth::Instruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd); m_context.appendConditionalJumpTo(loopEnd);
@ -298,7 +298,7 @@ bool Compiler::visit(Return const& _return)
//@todo modifications are needed to make this work with functions returning multiple values //@todo modifications are needed to make this work with functions returning multiple values
if (Expression const* expression = _return.getExpression()) if (Expression const* expression = _return.getExpression())
{ {
ExpressionCompiler::compileExpression(m_context, *expression); compileExpression(*expression);
VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front(); VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType()); ExpressionCompiler::appendTypeConversion(m_context, *expression->getType(), *firstVariable.getType());
@ -312,7 +312,7 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition)
{ {
if (Expression const* expression = _variableDefinition.getExpression()) if (Expression const* expression = _variableDefinition.getExpression())
{ {
ExpressionCompiler::compileExpression(m_context, *expression); compileExpression(*expression);
ExpressionCompiler::appendTypeConversion(m_context, ExpressionCompiler::appendTypeConversion(m_context,
*expression->getType(), *expression->getType(),
*_variableDefinition.getDeclaration().getType()); *_variableDefinition.getDeclaration().getType());
@ -324,10 +324,15 @@ bool Compiler::visit(VariableDefinition const& _variableDefinition)
bool Compiler::visit(ExpressionStatement const& _expressionStatement) bool Compiler::visit(ExpressionStatement const& _expressionStatement)
{ {
Expression const& expression = _expressionStatement.getExpression(); Expression const& expression = _expressionStatement.getExpression();
ExpressionCompiler::compileExpression(m_context, expression); compileExpression(expression);
CompilerUtils(m_context).popStackElement(*expression.getType()); CompilerUtils(m_context).popStackElement(*expression.getType());
return false; return false;
} }
void Compiler::compileExpression(Expression const& _expression)
{
ExpressionCompiler::compileExpression(m_context, _expression, m_optimize);
}
} }
} }

View File

@ -30,10 +30,10 @@ namespace solidity {
class Compiler: private ASTConstVisitor class Compiler: private ASTConstVisitor
{ {
public: public:
Compiler(): m_returnTag(m_context.newTag()) {} explicit Compiler(bool _optimize = false): m_optimize(_optimize), m_returnTag(m_context.newTag()) {}
void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals); void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals);
bytes getAssembledBytecode(bool _optimize = false) { return m_context.getAssembledBytecode(_optimize); } bytes getAssembledBytecode() { return m_context.getAssembledBytecode(m_optimize); }
void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); }
private: private:
@ -57,7 +57,9 @@ private:
virtual bool visit(VariableDefinition const& _variableDefinition) override; virtual bool visit(VariableDefinition const& _variableDefinition) override;
virtual bool visit(ExpressionStatement const& _expressionStatement) override; virtual bool visit(ExpressionStatement const& _expressionStatement) override;
void compileExpression(Expression const& _expression);
bool const m_optimize;
CompilerContext m_context; CompilerContext m_context;
std::vector<eth::AssemblyItem> m_breakTags; ///< tag to jump to for a "break" statement std::vector<eth::AssemblyItem> m_breakTags; ///< tag to jump to for a "break" statement
std::vector<eth::AssemblyItem> m_continueTags; ///< tag to jump to for a "continue" statement std::vector<eth::AssemblyItem> m_continueTags; ///< tag to jump to for a "continue" statement

View File

@ -101,10 +101,10 @@ void CompilerStack::compile(bool _optimize)
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{ {
m_globalContext->setCurrentContract(*contract); m_globalContext->setCurrentContract(*contract);
shared_ptr<Compiler> compiler = make_shared<Compiler>(); shared_ptr<Compiler> compiler = make_shared<Compiler>(_optimize);
compiler->compileContract(*contract, m_globalContext->getMagicVariables()); compiler->compileContract(*contract, m_globalContext->getMagicVariables());
Contract& compiledContract = m_contracts[contract->getName()]; Contract& compiledContract = m_contracts[contract->getName()];
compiledContract.bytecode = compiler->getAssembledBytecode(_optimize); compiledContract.bytecode = compiler->getAssembledBytecode();
compiledContract.compiler = move(compiler); compiledContract.compiler = move(compiler);
} }
} }

View File

@ -33,9 +33,9 @@ using namespace std;
namespace dev { namespace dev {
namespace solidity { namespace solidity {
void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression) void ExpressionCompiler::compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize)
{ {
ExpressionCompiler compiler(_context); ExpressionCompiler compiler(_context, _optimize);
_expression.accept(compiler); _expression.accept(compiler);
} }
@ -145,10 +145,24 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD) if (Token::isCompareOp(op) || op == Token::DIV || op == Token::MOD)
cleanupNeeded = true; cleanupNeeded = true;
rightExpression.accept(*this); // for commutative operators, push the literal as late as possible to allow improved optimization
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded); //@todo this has to be extended for literal expressions
leftExpression.accept(*this); bool swap = (m_optimize && Token::isCommutativeOp(op) && dynamic_cast<Literal const*>(&rightExpression)
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded); && !dynamic_cast<Literal const*>(&leftExpression));
if (swap)
{
leftExpression.accept(*this);
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
rightExpression.accept(*this);
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
}
else
{
rightExpression.accept(*this);
appendTypeConversion(*rightExpression.getType(), commonType, cleanupNeeded);
leftExpression.accept(*this);
appendTypeConversion(*leftExpression.getType(), commonType, cleanupNeeded);
}
if (Token::isCompareOp(op)) if (Token::isCompareOp(op))
appendCompareOperatorCode(op, commonType); appendCompareOperatorCode(op, commonType);
else else

View File

@ -45,14 +45,14 @@ class ExpressionCompiler: private ASTConstVisitor
{ {
public: public:
/// Compile the given @a _expression into the @a _context. /// Compile the given @a _expression into the @a _context.
static void compileExpression(CompilerContext& _context, Expression const& _expression); static void compileExpression(CompilerContext& _context, Expression const& _expression, bool _optimize = false);
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type. /// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType); static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType);
private: private:
ExpressionCompiler(CompilerContext& _compilerContext): explicit ExpressionCompiler(CompilerContext& _compilerContext, bool _optimize = false):
m_context(_compilerContext), m_currentLValue(m_context) {} m_optimize(_optimize), m_context(_compilerContext), m_currentLValue(m_context) {}
virtual bool visit(Assignment const& _assignment) override; virtual bool visit(Assignment const& _assignment) override;
virtual void endVisit(UnaryOperation const& _unaryOperation) override; virtual void endVisit(UnaryOperation const& _unaryOperation) override;
@ -132,6 +132,7 @@ private:
unsigned m_stackSize; unsigned m_stackSize;
}; };
bool m_optimize;
CompilerContext& m_context; CompilerContext& m_context;
LValue m_currentLValue; LValue m_currentLValue;
}; };

View File

@ -317,6 +317,8 @@ public:
static bool isElementaryTypeName(Value tok) { return INT <= tok && tok < TYPES_END; } static bool isElementaryTypeName(Value tok) { return INT <= tok && tok < TYPES_END; }
static bool isAssignmentOp(Value tok) { return ASSIGN <= tok && tok <= ASSIGN_MOD; } static bool isAssignmentOp(Value tok) { return ASSIGN <= tok && tok <= ASSIGN_MOD; }
static bool isBinaryOp(Value op) { return COMMA <= op && op <= MOD; } static bool isBinaryOp(Value op) { return COMMA <= op && op <= MOD; }
static bool isCommutativeOp(Value op) { return op == BIT_OR || op == BIT_XOR || op == BIT_AND ||
op == ADD || op == MUL || op == EQ || op == NE; }
static bool isArithmeticOp(Value op) { return ADD <= op && op <= MOD; } static bool isArithmeticOp(Value op) { return ADD <= op && op <= MOD; }
static bool isCompareOp(Value op) { return EQ <= op && op <= IN; } static bool isCompareOp(Value op) { return EQ <= op && op <= IN; }