Yul] RedundantAssignEliminator: Implements break/continue handling within ForLoop.

This commit is contained in:
Christian Parpart
2019-03-26 17:36:43 +01:00
committed by chriseth
parent d8c42a0270
commit a1ec49409d
6 changed files with 160 additions and 2 deletions
+20 -2
View File
@@ -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