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);
|
||||
|
||||
ForLoopInfo outerForLoopInfo;
|
||||
swap(outerForLoopInfo, m_forLoopInfo);
|
||||
|
||||
TrackedAssignments zeroRuns{m_assignments};
|
||||
|
||||
(*this)(_forLoop.body);
|
||||
merge(m_assignments, move(m_forLoopInfo.pendingContinueStmts));
|
||||
m_forLoopInfo.pendingContinueStmts = {};
|
||||
(*this)(_forLoop.post);
|
||||
|
||||
visit(*_forLoop.condition);
|
||||
@ -143,6 +148,8 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
|
||||
TrackedAssignments oneRun{m_assignments};
|
||||
|
||||
(*this)(_forLoop.body);
|
||||
|
||||
merge(m_assignments, move(m_forLoopInfo.pendingContinueStmts));
|
||||
(*this)(_forLoop.post);
|
||||
|
||||
visit(*_forLoop.condition);
|
||||
@ -150,16 +157,20 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
|
||||
// Order does not matter because "max" is commutative and associative.
|
||||
merge(m_assignments, move(oneRun));
|
||||
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&)
|
||||
{
|
||||
yulAssert(false, "Not implemented yet.");
|
||||
m_forLoopInfo.pendingBreakStmts.push_back(m_assignments);
|
||||
}
|
||||
|
||||
void RedundantAssignEliminator::operator()(Continue const&)
|
||||
{
|
||||
yulAssert(false, "Not implemented yet.");
|
||||
m_forLoopInfo.pendingContinueStmts.push_back(m_assignments);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (auto& assignment: m_assignments[_variable])
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace yul
|
||||
{
|
||||
@ -171,6 +172,7 @@ private:
|
||||
/// above.
|
||||
/// Will destroy @a _source.
|
||||
static void merge(TrackedAssignments& _target, TrackedAssignments&& _source);
|
||||
static void merge(TrackedAssignments& _target, std::vector<TrackedAssignments>&& _source);
|
||||
void changeUndecidedTo(YulString _variable, State _newState);
|
||||
void finalize(YulString _variable);
|
||||
|
||||
@ -178,6 +180,16 @@ private:
|
||||
std::set<YulString> m_declaredVariables;
|
||||
std::set<Assignment const*> m_pendingRemovals;
|
||||
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
|
||||
|
@ -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