mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul] RedundantAssignEliminator: Implements break/continue handling within ForLoop.
This commit is contained in:
parent
d8c42a0270
commit
a1ec49409d
@ -133,9 +133,14 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
|
|||||||
|
|
||||||
visit(*_forLoop.condition);
|
visit(*_forLoop.condition);
|
||||||
|
|
||||||
|
ForLoopInfo outerForLoopInfo;
|
||||||
|
swap(outerForLoopInfo, m_forLoopInfo);
|
||||||
|
|
||||||
TrackedAssignments zeroRuns{m_assignments};
|
TrackedAssignments zeroRuns{m_assignments};
|
||||||
|
|
||||||
(*this)(_forLoop.body);
|
(*this)(_forLoop.body);
|
||||||
|
merge(m_assignments, move(m_forLoopInfo.pendingContinueStmts));
|
||||||
|
m_forLoopInfo.pendingContinueStmts = {};
|
||||||
(*this)(_forLoop.post);
|
(*this)(_forLoop.post);
|
||||||
|
|
||||||
visit(*_forLoop.condition);
|
visit(*_forLoop.condition);
|
||||||
@ -143,6 +148,8 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
|
|||||||
TrackedAssignments oneRun{m_assignments};
|
TrackedAssignments oneRun{m_assignments};
|
||||||
|
|
||||||
(*this)(_forLoop.body);
|
(*this)(_forLoop.body);
|
||||||
|
|
||||||
|
merge(m_assignments, move(m_forLoopInfo.pendingContinueStmts));
|
||||||
(*this)(_forLoop.post);
|
(*this)(_forLoop.post);
|
||||||
|
|
||||||
visit(*_forLoop.condition);
|
visit(*_forLoop.condition);
|
||||||
@ -150,16 +157,20 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
|
|||||||
// Order does not matter because "max" is commutative and associative.
|
// Order does not matter because "max" is commutative and associative.
|
||||||
merge(m_assignments, move(oneRun));
|
merge(m_assignments, move(oneRun));
|
||||||
merge(m_assignments, move(zeroRuns));
|
merge(m_assignments, move(zeroRuns));
|
||||||
|
merge(m_assignments, move(m_forLoopInfo.pendingBreakStmts));
|
||||||
|
|
||||||
|
// Oestore potential outer for-loop states.
|
||||||
|
swap(m_forLoopInfo, outerForLoopInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedundantAssignEliminator::operator()(Break const&)
|
void RedundantAssignEliminator::operator()(Break const&)
|
||||||
{
|
{
|
||||||
yulAssert(false, "Not implemented yet.");
|
m_forLoopInfo.pendingBreakStmts.push_back(m_assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedundantAssignEliminator::operator()(Continue const&)
|
void RedundantAssignEliminator::operator()(Continue const&)
|
||||||
{
|
{
|
||||||
yulAssert(false, "Not implemented yet.");
|
m_forLoopInfo.pendingContinueStmts.push_back(m_assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedundantAssignEliminator::operator()(Block const& _block)
|
void RedundantAssignEliminator::operator()(Block const& _block)
|
||||||
@ -218,6 +229,13 @@ void RedundantAssignEliminator::merge(TrackedAssignments& _target, TrackedAssign
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RedundantAssignEliminator::merge(TrackedAssignments& _target, vector<TrackedAssignments>&& _source)
|
||||||
|
{
|
||||||
|
for (TrackedAssignments& ts: _source)
|
||||||
|
merge(_target, move(ts));
|
||||||
|
_source.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void RedundantAssignEliminator::changeUndecidedTo(YulString _variable, RedundantAssignEliminator::State _newState)
|
void RedundantAssignEliminator::changeUndecidedTo(YulString _variable, RedundantAssignEliminator::State _newState)
|
||||||
{
|
{
|
||||||
for (auto& assignment: m_assignments[_variable])
|
for (auto& assignment: m_assignments[_variable])
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <libyul/optimiser/ASTWalker.h>
|
#include <libyul/optimiser/ASTWalker.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace yul
|
namespace yul
|
||||||
{
|
{
|
||||||
@ -171,6 +172,7 @@ private:
|
|||||||
/// above.
|
/// above.
|
||||||
/// Will destroy @a _source.
|
/// Will destroy @a _source.
|
||||||
static void merge(TrackedAssignments& _target, TrackedAssignments&& _source);
|
static void merge(TrackedAssignments& _target, TrackedAssignments&& _source);
|
||||||
|
static void merge(TrackedAssignments& _target, std::vector<TrackedAssignments>&& _source);
|
||||||
void changeUndecidedTo(YulString _variable, State _newState);
|
void changeUndecidedTo(YulString _variable, State _newState);
|
||||||
void finalize(YulString _variable);
|
void finalize(YulString _variable);
|
||||||
|
|
||||||
@ -178,6 +180,16 @@ private:
|
|||||||
std::set<YulString> m_declaredVariables;
|
std::set<YulString> m_declaredVariables;
|
||||||
std::set<Assignment const*> m_pendingRemovals;
|
std::set<Assignment const*> m_pendingRemovals;
|
||||||
TrackedAssignments m_assignments;
|
TrackedAssignments m_assignments;
|
||||||
|
|
||||||
|
/// Working data for traversing for-loops.
|
||||||
|
struct ForLoopInfo
|
||||||
|
{
|
||||||
|
/// Tracked assignment states for each break statement.
|
||||||
|
std::vector<TrackedAssignments> pendingBreakStmts;
|
||||||
|
/// Tracked assignment states for each continue statement.
|
||||||
|
std::vector<TrackedAssignments> pendingContinueStmts;
|
||||||
|
};
|
||||||
|
ForLoopInfo m_forLoopInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AssignmentRemover: public ASTModifier
|
class AssignmentRemover: public ASTModifier
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
// Cannot be removed, because we might run the loop only once
|
||||||
|
let x := 1
|
||||||
|
for { } calldataload(0) { }
|
||||||
|
{
|
||||||
|
if callvalue() {
|
||||||
|
x := 2 // is preserved because of break stmt below.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := 3
|
||||||
|
}
|
||||||
|
mstore(x, 0x42)
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// redundantAssignEliminator
|
||||||
|
// {
|
||||||
|
// let x := 1
|
||||||
|
// for {
|
||||||
|
// }
|
||||||
|
// calldataload(0)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// if callvalue()
|
||||||
|
// {
|
||||||
|
// x := 2
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// x := 3
|
||||||
|
// }
|
||||||
|
// mstore(x, 0x42)
|
||||||
|
// }
|
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
// Cannot be removed, because we might run the loop only once
|
||||||
|
let x := 1
|
||||||
|
for { } calldataload(0) { }
|
||||||
|
{
|
||||||
|
x := 2 // Will not be removed as if-condition can be false.
|
||||||
|
if callvalue() {
|
||||||
|
x := 3
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mstore(x, 2)
|
||||||
|
}
|
||||||
|
x := 3
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// redundantAssignEliminator
|
||||||
|
// {
|
||||||
|
// let x := 1
|
||||||
|
// for {
|
||||||
|
// }
|
||||||
|
// calldataload(0)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// x := 2
|
||||||
|
// if callvalue()
|
||||||
|
// {
|
||||||
|
// x := 3
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// mstore(x, 2)
|
||||||
|
// }
|
||||||
|
// }
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
// Cannot be removed, because we might run the loop only once
|
||||||
|
let x := 1
|
||||||
|
for { } calldataload(0) { }
|
||||||
|
{
|
||||||
|
if callvalue() {
|
||||||
|
x := 2 // is preserved because of continue stmt below.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
x := 3
|
||||||
|
}
|
||||||
|
mstore(x, 0x42)
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// redundantAssignEliminator
|
||||||
|
// {
|
||||||
|
// let x := 1
|
||||||
|
// for {
|
||||||
|
// }
|
||||||
|
// calldataload(0)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// if callvalue()
|
||||||
|
// {
|
||||||
|
// x := 2
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// x := 3
|
||||||
|
// }
|
||||||
|
// mstore(x, 0x42)
|
||||||
|
// }
|
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
// Cannot be removed, because we might run the loop only once
|
||||||
|
let x := 1
|
||||||
|
for { } calldataload(0) { mstore(x, 0x42) }
|
||||||
|
{
|
||||||
|
if callvalue() {
|
||||||
|
x := 2 // is preserved because of continue stmt below.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
x := 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// redundantAssignEliminator
|
||||||
|
// {
|
||||||
|
// let x := 1
|
||||||
|
// for {
|
||||||
|
// }
|
||||||
|
// calldataload(0)
|
||||||
|
// {
|
||||||
|
// mstore(x, 0x42)
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
// if callvalue()
|
||||||
|
// {
|
||||||
|
// x := 2
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// x := 3
|
||||||
|
// }
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user