[Yul] Refactors RedundantAssignEliminator for future changes wrt. break/continue statements.

This commit is contained in:
Christian Parpart 2019-03-18 17:38:25 +01:00
parent 304ef77b4a
commit 89f1dbfbb6
No known key found for this signature in database
GPG Key ID: 19BC8DD20312C929
2 changed files with 38 additions and 36 deletions

View File

@ -61,41 +61,44 @@ void RedundantAssignEliminator::operator()(If const& _if)
{
visit(*_if.condition);
RedundantAssignEliminator branch{*this};
branch(_if.body);
TrackedAssignments skipBranch{m_assignments};
(*this)(_if.body);
join(branch);
merge(m_assignments, move(skipBranch));
}
void RedundantAssignEliminator::operator()(Switch const& _switch)
{
visit(*_switch.expression);
TrackedAssignments const preState{m_assignments};
bool hasDefault = false;
vector<RedundantAssignEliminator> branches;
vector<TrackedAssignments> branches;
for (auto const& c: _switch.cases)
{
if (!c.value)
hasDefault = true;
branches.emplace_back(*this);
branches.back()(c.body);
(*this)(c.body);
branches.emplace_back(move(m_assignments));
m_assignments = preState;
}
if (hasDefault)
{
*this = std::move(branches.back());
m_assignments = move(branches.back());
branches.pop_back();
}
for (auto& branch: branches)
join(branch);
merge(m_assignments, move(branch));
}
void RedundantAssignEliminator::operator()(FunctionDefinition const& _functionDefinition)
{
std::set<YulString> declaredVariables;
std::map<YulString, std::map<Assignment const*, State>> assignments;
swap(m_declaredVariables, declaredVariables);
swap(m_assignments, assignments);
std::set<YulString> outerDeclaredVariables;
TrackedAssignments outerAssignments;
swap(m_declaredVariables, outerDeclaredVariables);
swap(m_assignments, outerAssignments);
(*this)(_functionDefinition.body);
@ -110,8 +113,8 @@ void RedundantAssignEliminator::operator()(FunctionDefinition const& _functionDe
finalize(retParam.name);
}
swap(m_declaredVariables, declaredVariables);
swap(m_assignments, assignments);
swap(m_declaredVariables, outerDeclaredVariables);
swap(m_assignments, outerAssignments);
}
void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
@ -130,14 +133,14 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
visit(*_forLoop.condition);
RedundantAssignEliminator zeroRuns{*this};
TrackedAssignments zeroRuns{m_assignments};
(*this)(_forLoop.body);
(*this)(_forLoop.post);
visit(*_forLoop.condition);
RedundantAssignEliminator oneRun{*this};
TrackedAssignments oneRun{m_assignments};
(*this)(_forLoop.body);
(*this)(_forLoop.post);
@ -145,8 +148,8 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
visit(*_forLoop.condition);
// Order does not matter because "max" is commutative and associative.
join(oneRun);
join(zeroRuns);
merge(m_assignments, move(oneRun));
merge(m_assignments, move(zeroRuns));
}
void RedundantAssignEliminator::operator()(Break const&)
@ -173,7 +176,7 @@ void RedundantAssignEliminator::run(Dialect const& _dialect, Block& _ast)
RedundantAssignEliminator rae{_dialect};
rae(_ast);
AssignmentRemover remover{rae.m_assignmentsToRemove};
AssignmentRemover remover{rae.m_pendingRemovals};
remover(_ast);
}
@ -204,16 +207,14 @@ void joinMap(std::map<K, V>& _a, std::map<K, V>&& _b, F _conflictSolver)
}
}
void RedundantAssignEliminator::join(RedundantAssignEliminator& _other)
void RedundantAssignEliminator::merge(TrackedAssignments& _target, TrackedAssignments&& _other)
{
m_assignmentsToRemove.insert(begin(_other.m_assignmentsToRemove), end(_other.m_assignmentsToRemove));
joinMap(m_assignments, std::move(_other.m_assignments), [](
joinMap(_target, move(_other), [](
map<Assignment const*, State>& _assignmentHere,
map<Assignment const*, State>&& _assignmentThere
)
{
return joinMap(_assignmentHere, std::move(_assignmentThere), State::join);
return joinMap(_assignmentHere, move(_assignmentThere), State::join);
});
}
@ -232,7 +233,7 @@ void RedundantAssignEliminator::finalize(YulString _variable)
if (assignment.second == State{State::Unused} && MovableChecker{*m_dialect, *assignment.first->value}.movable())
// TODO the only point where we actually need this
// to be a set is for the for loop
m_assignmentsToRemove.insert(assignment.first);
m_pendingRemovals.insert(assignment.first);
}
m_assignments.erase(_variable);
}

View File

@ -100,8 +100,9 @@ class RedundantAssignEliminator: public ASTWalker
{
public:
explicit RedundantAssignEliminator(Dialect const& _dialect): m_dialect(&_dialect) {}
RedundantAssignEliminator(RedundantAssignEliminator const&) = default;
RedundantAssignEliminator& operator=(RedundantAssignEliminator const&) = default;
RedundantAssignEliminator() = delete;
RedundantAssignEliminator(RedundantAssignEliminator const&) = delete;
RedundantAssignEliminator& operator=(RedundantAssignEliminator const&) = delete;
RedundantAssignEliminator(RedundantAssignEliminator&&) = default;
RedundantAssignEliminator& operator=(RedundantAssignEliminator&&) = default;
@ -119,8 +120,6 @@ public:
static void run(Dialect const& _dialect, Block& _ast);
private:
RedundantAssignEliminator() = default;
class State
{
public:
@ -164,19 +163,21 @@ private:
std::set<YulString> m_outerDeclaredVariables;
};
/// Joins the assignment mapping with @a _other according to the rules laid out
// TODO check that this does not cause nondeterminism!
// This could also be a pseudo-map from state to assignment.
using TrackedAssignments = std::map<YulString, std::map<Assignment const*, State>>;
/// Joins the assignment mapping of @a _source into @a _target according to the rules laid out
/// above.
/// Will destroy @a _other.
void join(RedundantAssignEliminator& _other);
/// Will destroy @a _source.
static void merge(TrackedAssignments& _target, TrackedAssignments&& _source);
void changeUndecidedTo(YulString _variable, State _newState);
void finalize(YulString _variable);
Dialect const* m_dialect;
std::set<YulString> m_declaredVariables;
// TODO check that this does not cause nondeterminism!
// This could also be a pseudo-map from state to assignment.
std::map<YulString, std::map<Assignment const*, State>> m_assignments;
std::set<Assignment const*> m_assignmentsToRemove;
std::set<Assignment const*> m_pendingRemovals;
TrackedAssignments m_assignments;
};
class AssignmentRemover: public ASTModifier