mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Prototype of a full SSA transformation.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/*(
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libyul/optimiser/FullSSAReverse.h>
|
||||
#include <libyul/optimiser/ASTCopier.h>
|
||||
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
#include <libyul/optimiser/NameDispenser.h>
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
|
||||
#include <libsolutil/CommonData.h>
|
||||
#include <libsolutil/Visitor.h>
|
||||
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::yul;
|
||||
|
||||
class FullSSAReverseLoad: public ASTCopier
|
||||
{
|
||||
public:
|
||||
FullSSAReverseLoad(std::map<YulString, YulString> const& _variableNames): m_variableNames(_variableNames) {}
|
||||
Expression operator()(FunctionCall const& _funCall) override
|
||||
{
|
||||
if (_funCall.functionName.name == "phi_load"_yulstring)
|
||||
{
|
||||
yulAssert(_funCall.arguments.size() == 1, "");
|
||||
Literal const* literal = std::get_if<Literal>(&_funCall.arguments.front());
|
||||
yulAssert(literal && literal->kind == LiteralKind::String, "");
|
||||
yulAssert(m_variableNames.count(literal->value), "");
|
||||
return Identifier{
|
||||
_funCall.location,
|
||||
m_variableNames.at(literal->value)
|
||||
};
|
||||
}
|
||||
return ASTCopier::operator()(_funCall);
|
||||
}
|
||||
private:
|
||||
map<YulString, YulString> const& m_variableNames;
|
||||
};
|
||||
|
||||
void FullSSAReverse::run(OptimiserStepContext& _context, Block& _ast)
|
||||
{
|
||||
FullSSAReverse fullSSAReverse{_context.dispenser};
|
||||
fullSSAReverse(_ast);
|
||||
_ast = FullSSAReverseLoad{fullSSAReverse.m_variableNames}.translate(_ast);
|
||||
}
|
||||
|
||||
void FullSSAReverse::operator()(Block& _block)
|
||||
{
|
||||
util::iterateReplacing(
|
||||
_block.statements,
|
||||
[&](Statement& _stmt) -> std::optional<vector<Statement>>
|
||||
{
|
||||
if (auto* expressionStatement = std::get_if<ExpressionStatement>(&_stmt))
|
||||
if (auto* functionCall = std::get_if<FunctionCall>(&expressionStatement->expression))
|
||||
if (functionCall->functionName.name == "phi_store"_yulstring)
|
||||
{
|
||||
yulAssert(functionCall->arguments.size() == 2, "");
|
||||
Literal const* literal = std::get_if<Literal>(&functionCall->arguments.front());
|
||||
yulAssert(literal && literal->kind == LiteralKind::String, "");
|
||||
|
||||
vector<Statement> result;
|
||||
if (m_variableNames.count(literal->value))
|
||||
result.emplace_back(Assignment{
|
||||
functionCall->location,
|
||||
{Identifier{literal->location, m_variableNames.at(literal->value)}},
|
||||
make_unique<Expression>(move(functionCall->arguments.back()))
|
||||
});
|
||||
else
|
||||
{
|
||||
YulString newName = m_nameDispenser.newName(literal->value);
|
||||
m_variableNames[literal->value] = newName;
|
||||
result.emplace_back(VariableDeclaration{
|
||||
functionCall->location,
|
||||
{TypedName{literal->location, newName, YulString{}}},
|
||||
make_unique<Expression>(move(functionCall->arguments.back()))
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
visit(_stmt);
|
||||
return {};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void FullSSAReverse::operator()(FunctionDefinition& _funDef)
|
||||
{
|
||||
set<YulString> oldFunctionReturns;
|
||||
swap(m_currentFunctionReturns, oldFunctionReturns);
|
||||
vector<Statement> bodyPrefix;
|
||||
for (auto& var: _funDef.returnVariables)
|
||||
{
|
||||
YulString newName = m_nameDispenser.newName(var.name);
|
||||
m_variableNames[var.name] = newName;
|
||||
m_currentFunctionReturns.emplace(var.name);
|
||||
bodyPrefix.emplace_back(VariableDeclaration{
|
||||
var.location,
|
||||
{var},
|
||||
make_unique<Expression>(Identifier{var.location, newName})
|
||||
});
|
||||
var.name = newName;
|
||||
}
|
||||
|
||||
bodyPrefix += std::move(_funDef.body.statements);
|
||||
_funDef.body.statements = std::move(bodyPrefix);
|
||||
|
||||
ASTModifier::operator()(_funDef);
|
||||
|
||||
swap(m_currentFunctionReturns, oldFunctionReturns);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
#include <libyul/optimiser/KnowledgeBase.h>
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/YulString.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/SideEffects.h>
|
||||
|
||||
#include <libsolutil/InvertibleMap.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace solidity::yul
|
||||
{
|
||||
struct Dialect;
|
||||
|
||||
class FullSSAReverse: public ASTModifier
|
||||
{
|
||||
public:
|
||||
static constexpr char const* name{"FullSSAReverse"};
|
||||
static void run(OptimiserStepContext& _context, Block& _ast);
|
||||
using ASTModifier::operator();
|
||||
void operator()(Block& _block) override;
|
||||
void operator()(FunctionDefinition& _funDef) override;
|
||||
private:
|
||||
FullSSAReverse(NameDispenser& _nameDispenser): m_nameDispenser(_nameDispenser) {}
|
||||
NameDispenser& m_nameDispenser;
|
||||
std::map<YulString, YulString> m_variableNames;
|
||||
std::set<YulString> m_currentFunctionReturns;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libyul/optimiser/FullSSATransform.h>
|
||||
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
#include <libyul/optimiser/NameDispenser.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
|
||||
#include <libsolutil/CommonData.h>
|
||||
#include <libsolutil/Visitor.h>
|
||||
|
||||
#include <variant>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::yul;
|
||||
|
||||
void FullSSATransform::run(OptimiserStepContext& _context, Block& _ast)
|
||||
{
|
||||
FullSSATransform transform{_context};
|
||||
transform(_ast);
|
||||
}
|
||||
|
||||
FullSSATransform::FullSSATransform(OptimiserStepContext& _context): m_nameDispenser(_context.dispenser)
|
||||
{
|
||||
}
|
||||
|
||||
void FullSSATransform::operator()(VariableDeclaration& _varDecl)
|
||||
{
|
||||
ASTModifier::operator()(_varDecl);
|
||||
for (auto const& _var: _varDecl.variables)
|
||||
{
|
||||
yulAssert(!m_currentSSANames.count(_var.name), "");
|
||||
m_currentSSANames[_var.name] = _var.name;
|
||||
}
|
||||
}
|
||||
|
||||
void FullSSATransform::operator()(Identifier& _identifier)
|
||||
{
|
||||
yulAssert(m_currentSSANames.count(_identifier.name), "");
|
||||
_identifier.name = m_currentSSANames[_identifier.name];
|
||||
}
|
||||
|
||||
void FullSSATransform::operator()(FunctionDefinition& _functionDefinition)
|
||||
{
|
||||
vector<YulString> oldFunctionReturnVariables;
|
||||
swap(oldFunctionReturnVariables, m_currentFunctionReturnVariables);
|
||||
|
||||
for (auto const& var: _functionDefinition.returnVariables)
|
||||
m_currentFunctionReturnVariables.emplace_back(var.name);
|
||||
|
||||
for (auto const& argument: _functionDefinition.parameters + _functionDefinition.returnVariables)
|
||||
{
|
||||
yulAssert(!m_currentSSANames.count(argument.name), "");
|
||||
m_currentSSANames[argument.name] = argument.name;
|
||||
}
|
||||
|
||||
(*this)(_functionDefinition.body);
|
||||
|
||||
for (auto const& var: _functionDefinition.returnVariables)
|
||||
_functionDefinition.body.statements.emplace_back(makePhiStore(var.name, m_currentSSANames[var.name]));
|
||||
|
||||
swap(m_currentFunctionReturnVariables, oldFunctionReturnVariables);
|
||||
}
|
||||
|
||||
Statement FullSSATransform::makePhiStore(YulString _var, YulString _value)
|
||||
{
|
||||
return ExpressionStatement{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
FunctionCall{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
Identifier{
|
||||
langutil::SourceLocation{},
|
||||
YulString{"phi_store"}
|
||||
},
|
||||
{
|
||||
Literal{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
LiteralKind::String,
|
||||
_var,
|
||||
YulString{} // TODO
|
||||
},
|
||||
Identifier{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
_value
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Expression FullSSATransform::makePhiLoad(YulString _var)
|
||||
{
|
||||
return FunctionCall{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
Identifier{
|
||||
langutil::SourceLocation{},
|
||||
YulString{"phi_load"}
|
||||
},
|
||||
{
|
||||
Literal{
|
||||
langutil::SourceLocation{}, // TODO
|
||||
LiteralKind::String,
|
||||
_var,
|
||||
YulString{} // TODO
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void FullSSATransform::operator()(Block& _block)
|
||||
{
|
||||
auto addReloads = [&](map<YulString, YulString> const& _variables, vector<Statement>& _statements) {
|
||||
for (auto [origName, oldName]: _variables)
|
||||
{
|
||||
YulString newName = m_nameDispenser.newName(origName);
|
||||
_statements.emplace_back(
|
||||
VariableDeclaration{
|
||||
langutil::SourceLocation{},
|
||||
{TypedName{langutil::SourceLocation{}, newName, YulString{}}},
|
||||
make_unique<Expression>(makePhiLoad(oldName))
|
||||
}
|
||||
);
|
||||
m_currentSSANames[origName] = newName;
|
||||
}
|
||||
};
|
||||
auto saveAssignedVariables = [&](auto const& _names, vector<Statement>& _result) {
|
||||
map<YulString, YulString> storedNames;
|
||||
for (YulString var: _names)
|
||||
if (m_currentSSANames.count(var))
|
||||
{
|
||||
YulString currentName = m_currentSSANames[var];
|
||||
_result.emplace_back(makePhiStore(currentName, currentName));
|
||||
storedNames[var] = currentName;
|
||||
}
|
||||
return storedNames;
|
||||
};
|
||||
auto restoreAssignedVariables = [&](map<YulString, YulString> const& _storedNames, vector<Statement>& _result) {
|
||||
for (auto [origName, oldName]: _storedNames)
|
||||
{
|
||||
yulAssert(m_currentSSANames.count(origName), "");
|
||||
YulString currentName = m_currentSSANames[origName];
|
||||
_result.emplace_back(makePhiStore(oldName, currentName));
|
||||
}
|
||||
};
|
||||
|
||||
using OptionalStatements = optional<vector<Statement>>;
|
||||
util::iterateReplacing(
|
||||
_block.statements,
|
||||
[&](Statement& _stmt) -> OptionalStatements
|
||||
{
|
||||
return std::visit(util::GenericVisitor{
|
||||
[&](Assignment& _assignment) -> OptionalStatements {
|
||||
visit(*_assignment.value);
|
||||
vector<Statement> result;
|
||||
VariableDeclaration varDecl{
|
||||
_assignment.location,
|
||||
{},
|
||||
std::move(_assignment.value)
|
||||
};
|
||||
for (auto& var: _assignment.variableNames)
|
||||
{
|
||||
yulAssert(m_currentSSANames.count(var.name), "");
|
||||
YulString newName = m_nameDispenser.newName(var.name);
|
||||
varDecl.variables.emplace_back(TypedName{
|
||||
var.location,
|
||||
newName,
|
||||
YulString{}
|
||||
});
|
||||
m_currentSSANames[var.name] = newName;
|
||||
}
|
||||
result.emplace_back(move(varDecl));
|
||||
return result;
|
||||
},
|
||||
[&](If& _if) -> OptionalStatements {
|
||||
Assignments assignments;
|
||||
assignments(_if);
|
||||
vector<Statement> result;
|
||||
auto storedAssignedVariables = saveAssignedVariables(assignments.names(), result);
|
||||
|
||||
(*this)(_if);
|
||||
restoreAssignedVariables(storedAssignedVariables, _if.body.statements);
|
||||
result.emplace_back(std::move(_if));
|
||||
|
||||
addReloads(storedAssignedVariables, result);
|
||||
return result;
|
||||
},
|
||||
[&](Switch& _switch) -> OptionalStatements {
|
||||
Assignments assignments;
|
||||
assignments(_switch);
|
||||
vector<Statement> result;
|
||||
auto storedAssignedVariables = saveAssignedVariables(assignments.names(), result);
|
||||
|
||||
visit(*_switch.expression);
|
||||
auto saved = m_currentSSANames;
|
||||
for (auto& switchCase: _switch.cases)
|
||||
{
|
||||
m_currentSSANames = saved;
|
||||
if (switchCase.value)
|
||||
(*this)(*switchCase.value);
|
||||
(*this)(switchCase.body);
|
||||
restoreAssignedVariables(storedAssignedVariables, switchCase.body.statements);
|
||||
}
|
||||
result.emplace_back(std::move(_switch));
|
||||
|
||||
addReloads(storedAssignedVariables, result);
|
||||
return result;
|
||||
},
|
||||
[&](ForLoop& _loop) -> OptionalStatements {
|
||||
yulAssert(_loop.pre.statements.empty(), "");
|
||||
std::map<YulString, YulString> oldLoopAssignments;
|
||||
swap(oldLoopAssignments, m_currentLoopAssignments);
|
||||
Assignments assignments;
|
||||
assignments(_loop);
|
||||
|
||||
vector<Statement> result;
|
||||
|
||||
if (auto* identifier = std::get_if<Identifier>(_loop.condition.get()))
|
||||
{
|
||||
if (assignments.names().count(identifier->name))
|
||||
{
|
||||
yulAssert(m_currentSSANames.count(identifier->name), "");
|
||||
_loop.condition = make_unique<Expression>(makePhiLoad(m_currentSSANames[identifier->name]));
|
||||
}
|
||||
}
|
||||
else
|
||||
yulAssert(holds_alternative<Literal>(*_loop.condition), "for loop into body required");
|
||||
|
||||
m_currentLoopAssignments = saveAssignedVariables(assignments.names(), result);
|
||||
|
||||
vector<Statement> newBody;
|
||||
addReloads(m_currentLoopAssignments, newBody);
|
||||
|
||||
(*this)(_loop.body);
|
||||
|
||||
newBody += std::move(_loop.body.statements);
|
||||
_loop.body.statements = std::move(newBody);
|
||||
|
||||
restoreAssignedVariables(m_currentLoopAssignments, _loop.body.statements);
|
||||
|
||||
vector<Statement> newPost;
|
||||
addReloads(m_currentLoopAssignments, newPost);
|
||||
|
||||
(*this)(_loop.post);
|
||||
|
||||
restoreAssignedVariables(m_currentLoopAssignments, _loop.post.statements);
|
||||
|
||||
newPost += std::move(_loop.post.statements);
|
||||
_loop.post.statements = std::move(newPost);
|
||||
|
||||
result.emplace_back(move(_loop));
|
||||
|
||||
addReloads(m_currentLoopAssignments, result);
|
||||
|
||||
swap(m_currentLoopAssignments, oldLoopAssignments);
|
||||
return result;
|
||||
},
|
||||
[&](Continue& _continue) -> OptionalStatements {
|
||||
vector<Statement> result;
|
||||
restoreAssignedVariables(m_currentLoopAssignments, result);
|
||||
result.emplace_back(std::move(_continue));
|
||||
return result;
|
||||
},
|
||||
[&](Break& _break) -> OptionalStatements {
|
||||
vector<Statement> result;
|
||||
restoreAssignedVariables(m_currentLoopAssignments, result);
|
||||
result.emplace_back(std::move(_break));
|
||||
return result;
|
||||
},
|
||||
[&](Leave& _leaveStatement) -> OptionalStatements {
|
||||
vector<Statement> result;
|
||||
for (YulString var: m_currentFunctionReturnVariables)
|
||||
{
|
||||
yulAssert(m_currentSSANames.count(var), "");
|
||||
result.emplace_back(makePhiStore(var, m_currentSSANames[var]));
|
||||
}
|
||||
result.emplace_back(std::move(_leaveStatement));
|
||||
return result;
|
||||
},
|
||||
[&](auto& _stmt) -> OptionalStatements { (*this)(_stmt); return std::nullopt; }
|
||||
}, _stmt);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
#include <libyul/optimiser/KnowledgeBase.h>
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/YulString.h>
|
||||
#include <libyul/AST.h>
|
||||
#include <libyul/SideEffects.h>
|
||||
|
||||
#include <libsolutil/InvertibleMap.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace solidity::yul
|
||||
{
|
||||
struct Dialect;
|
||||
|
||||
class FullSSATransform: public ASTModifier
|
||||
{
|
||||
public:
|
||||
static constexpr char const* name{"FullSSATransform"};
|
||||
static void run(OptimiserStepContext& _context, Block& _ast);
|
||||
explicit FullSSATransform(OptimiserStepContext& _context);
|
||||
|
||||
using ASTModifier::operator();
|
||||
void operator()(VariableDeclaration& _varDecl) override;
|
||||
void operator()(Identifier& _varDecl) override;
|
||||
void operator()(FunctionDefinition& _functionDefinition) override;
|
||||
void operator()(Block& _block) override;
|
||||
private:
|
||||
std::map<YulString, YulString> m_currentSSANames;
|
||||
NameDispenser& m_nameDispenser;
|
||||
std::vector<YulString> m_currentFunctionReturnVariables;
|
||||
std::map<YulString, YulString> m_currentLoopAssignments;
|
||||
|
||||
static Statement makePhiStore(YulString _var, YulString _value);
|
||||
static Expression makePhiLoad(YulString _var);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -44,6 +44,18 @@ void NameCollector::operator ()(FunctionDefinition const& _funDef)
|
||||
ASTWalker::operator ()(_funDef);
|
||||
}
|
||||
|
||||
void NameCollector::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
if (_funCall.functionName.name == "phi_store"_yulstring || _funCall.functionName.name == "phi_load"_yulstring)
|
||||
{
|
||||
yulAssert(!_funCall.arguments.empty(), "");
|
||||
auto const* literal = std::get_if<Literal>(&_funCall.arguments.front());
|
||||
yulAssert(literal && literal->kind == LiteralKind::String, "");
|
||||
m_names.emplace(literal->value);
|
||||
}
|
||||
ASTWalker::operator ()(_funCall);
|
||||
}
|
||||
|
||||
void ReferencesCounter::operator()(Identifier const& _identifier)
|
||||
{
|
||||
++m_references[_identifier.name];
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
using ASTWalker::operator ();
|
||||
void operator()(VariableDeclaration const& _varDecl) override;
|
||||
void operator()(FunctionDefinition const& _funDef) override;
|
||||
void operator()(FunctionCall const& _funCall) override;
|
||||
|
||||
std::set<YulString> names() const { return m_names; }
|
||||
private:
|
||||
|
||||
@@ -308,7 +308,19 @@ void RedundantAssignEliminator::finalize(YulString _variable, RedundantAssignEli
|
||||
void AssignmentRemover::operator()(Block& _block)
|
||||
{
|
||||
boost::range::remove_erase_if(_block.statements, [&](Statement const& _statement) -> bool {
|
||||
return holds_alternative<Assignment>(_statement) && m_toRemove.count(&std::get<Assignment>(_statement));
|
||||
if (auto const* assignment = std::get_if<Assignment>(&_statement))
|
||||
{
|
||||
if (m_toRemove.count(assignment))
|
||||
return true;
|
||||
// TODO: hack to generally get rid of assignments like a := a
|
||||
if (assignment->variableNames.size() == 1)
|
||||
{
|
||||
if (auto const* identifier = std::get_if<Identifier>(assignment->value.get()))
|
||||
if (identifier->name == assignment->variableNames.front().name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
ASTModifier::operator()(_block);
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||
#include <libyul/optimiser/ExpressionInliner.h>
|
||||
#include <libyul/optimiser/FullInliner.h>
|
||||
#include <libyul/optimiser/FullSSAReverse.h>
|
||||
#include <libyul/optimiser/FullSSATransform.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||
@@ -190,6 +192,8 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
||||
ForLoopConditionOutOfBody,
|
||||
ForLoopInitRewriter,
|
||||
FullInliner,
|
||||
FullSSAReverse,
|
||||
FullSSATransform,
|
||||
FunctionGrouper,
|
||||
FunctionHoister,
|
||||
LiteralRematerialiser,
|
||||
@@ -229,6 +233,8 @@ map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
|
||||
{ForLoopConditionOutOfBody::name, 'O'},
|
||||
{ForLoopInitRewriter::name, 'o'},
|
||||
{FullInliner::name, 'i'},
|
||||
{FullSSAReverse::name, 'Z'},
|
||||
{FullSSATransform::name, 'z'},
|
||||
{FunctionGrouper::name, 'g'},
|
||||
{FunctionHoister::name, 'h'},
|
||||
{LiteralRematerialiser::name, 'T'},
|
||||
|
||||
Reference in New Issue
Block a user