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: Inline external function calls to ``this``.
|
||||
* Assembler: Encode the compiler version in the deployed bytecode.
|
||||
* Yul Optimizer: Simplify single-run ``for`` loops to ``if`` statements.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -115,9 +115,51 @@ void ControlFlowSimplifier::operator()(Block& _block)
|
||||
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)
|
||||
{
|
||||
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch, ForLoop> const visitor(
|
||||
GenericFallbackReturnsVisitor<OptionalStatements, If, Switch> const visitor(
|
||||
[&](If& _ifStmt) -> OptionalStatements {
|
||||
if (_ifStmt.body.statements.empty())
|
||||
{
|
||||
@ -136,9 +178,6 @@ void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
||||
else if (_switchStmt.cases.size() == 1)
|
||||
return reduceSingleCaseSwitch(_switchStmt);
|
||||
|
||||
return {};
|
||||
},
|
||||
[&](ForLoop&) -> OptionalStatements {
|
||||
return {};
|
||||
}
|
||||
);
|
||||
|
@ -38,7 +38,7 @@ namespace yul
|
||||
* The ControlFlowSimplifier does record the presence or absence of ``break``
|
||||
* 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.
|
||||
*/
|
||||
@ -46,9 +46,17 @@ class ControlFlowSimplifier: public ASTModifier
|
||||
{
|
||||
public:
|
||||
using ASTModifier::operator();
|
||||
void operator()(Break&) override { ++m_numBreakStatements; }
|
||||
void operator()(Continue&) override { ++m_numContinueStatements; }
|
||||
void operator()(Block& _block) override;
|
||||
|
||||
void visit(Statement& _st) override;
|
||||
|
||||
private:
|
||||
void simplify(std::vector<Statement>& _statements);
|
||||
|
||||
size_t m_numBreakStatements = 0;
|
||||
size_t m_numContinueStatements = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user