mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Simplify single-run for loops to if statements.
This commit is contained in:
parent
99e96c2d66
commit
439a225cee
@ -10,6 +10,7 @@ Compiler Features:
|
|||||||
* SMTChecker: Support ``delete``.
|
* SMTChecker: Support ``delete``.
|
||||||
* SMTChecker: Inline external function calls to ``this``.
|
* SMTChecker: Inline external function calls to ``this``.
|
||||||
* Assembler: Encode the compiler version in the deployed bytecode.
|
* Assembler: Encode the compiler version in the deployed bytecode.
|
||||||
|
* Yul Optimizer: Simplify single-run ``for`` loops to ``if`` statements.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -115,9 +115,51 @@ void ControlFlowSimplifier::operator()(Block& _block)
|
|||||||
simplify(_block.statements);
|
simplify(_block.statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControlFlowSimplifier::visit(Statement& _st)
|
||||||
|
{
|
||||||
|
if (_st.type() == typeid(ForLoop))
|
||||||
|
{
|
||||||
|
ForLoop& forLoop = boost::get<ForLoop>(_st);
|
||||||
|
yulAssert(forLoop.pre.statements.empty(), "");
|
||||||
|
|
||||||
|
size_t outerBreak = m_numBreakStatements;
|
||||||
|
size_t outerContinue = m_numContinueStatements;
|
||||||
|
m_numBreakStatements = 0;
|
||||||
|
m_numContinueStatements = 0;
|
||||||
|
|
||||||
|
ASTModifier::visit(_st);
|
||||||
|
|
||||||
|
if (!forLoop.body.statements.empty())
|
||||||
|
{
|
||||||
|
bool isTerminating = false;
|
||||||
|
TerminationFinder::ControlFlow controlFlow = TerminationFinder::controlFlowKind(forLoop.body.statements.back());
|
||||||
|
if (controlFlow == TerminationFinder::ControlFlow::Break)
|
||||||
|
{
|
||||||
|
isTerminating = true;
|
||||||
|
--m_numBreakStatements;
|
||||||
|
}
|
||||||
|
else if (controlFlow == TerminationFinder::ControlFlow::Terminate)
|
||||||
|
isTerminating = true;
|
||||||
|
|
||||||
|
if (isTerminating && m_numContinueStatements == 0 && m_numBreakStatements == 0)
|
||||||
|
{
|
||||||
|
If replacement{forLoop.location, std::move(forLoop.condition), std::move(forLoop.body)};
|
||||||
|
if (controlFlow == TerminationFinder::ControlFlow::Break)
|
||||||
|
replacement.body.statements.resize(replacement.body.statements.size() - 1);
|
||||||
|
_st = std::move(replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_numBreakStatements = outerBreak;
|
||||||
|
m_numContinueStatements = outerContinue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ASTModifier::visit(_st);
|
||||||
|
}
|
||||||
|
|
||||||
void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
||||||
{
|
{
|
||||||
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch, ForLoop> const visitor(
|
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch> const visitor(
|
||||||
[&](If& _ifStmt) -> OptionalStatements {
|
[&](If& _ifStmt) -> OptionalStatements {
|
||||||
if (_ifStmt.body.statements.empty())
|
if (_ifStmt.body.statements.empty())
|
||||||
{
|
{
|
||||||
@ -136,9 +178,6 @@ void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
|||||||
else if (_switchStmt.cases.size() == 1)
|
else if (_switchStmt.cases.size() == 1)
|
||||||
return reduceSingleCaseSwitch(_switchStmt);
|
return reduceSingleCaseSwitch(_switchStmt);
|
||||||
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
[&](ForLoop&) -> OptionalStatements {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -38,7 +38,7 @@ namespace yul
|
|||||||
* The ControlFlowSimplifier does record the presence or absence of ``break``
|
* The ControlFlowSimplifier does record the presence or absence of ``break``
|
||||||
* and ``continue`` statements during its traversal.
|
* and ``continue`` statements during its traversal.
|
||||||
*
|
*
|
||||||
* Prerequisite: Disambiguator, ForLoopInitRewriter.
|
* Prerequisite: Disambiguator, FunctionHoister, ForLoopInitRewriter.
|
||||||
*
|
*
|
||||||
* Important: Introduces EVM opcodes and thus can only be used on EVM code for now.
|
* Important: Introduces EVM opcodes and thus can only be used on EVM code for now.
|
||||||
*/
|
*/
|
||||||
@ -46,9 +46,17 @@ class ControlFlowSimplifier: public ASTModifier
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ASTModifier::operator();
|
using ASTModifier::operator();
|
||||||
|
void operator()(Break&) override { ++m_numBreakStatements; }
|
||||||
|
void operator()(Continue&) override { ++m_numContinueStatements; }
|
||||||
void operator()(Block& _block) override;
|
void operator()(Block& _block) override;
|
||||||
|
|
||||||
|
void visit(Statement& _st) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void simplify(std::vector<Statement>& _statements);
|
void simplify(std::vector<Statement>& _statements);
|
||||||
|
|
||||||
|
size_t m_numBreakStatements = 0;
|
||||||
|
size_t m_numContinueStatements = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user