Merge pull request #5655 from ethereum/removeUnassignedVarDefs

Add variable declaration initializer.
This commit is contained in:
chriseth 2018-12-13 17:30:26 +01:00 committed by GitHub
commit 8d3617b7c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 249 additions and 349 deletions

View File

@ -43,6 +43,6 @@ add_library(yul
optimiser/SyntacticalEquality.cpp optimiser/SyntacticalEquality.cpp
optimiser/UnusedPruner.cpp optimiser/UnusedPruner.cpp
optimiser/Utilities.cpp optimiser/Utilities.cpp
optimiser/VarDeclPropagator.cpp optimiser/VarDeclInitializer.cpp
) )
target_link_libraries(yul PUBLIC evmasm devcore langutil) target_link_libraries(yul PUBLIC evmasm devcore langutil)

View File

@ -168,6 +168,8 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
m_driver.tentativelyUpdateCodeSize(function->name, m_currentFunction); m_driver.tentativelyUpdateCodeSize(function->name, m_currentFunction);
static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}};
// helper function to create a new variable that is supposed to model // helper function to create a new variable that is supposed to model
// an existing variable. // an existing variable.
auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) { auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) {
@ -176,6 +178,8 @@ vector<Statement> InlineModifier::performInline(Statement& _statement, FunctionC
VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}}; VariableDeclaration varDecl{_funCall.location, {{_funCall.location, newName, _existingVariable.type}}, {}};
if (_value) if (_value)
varDecl.value = make_shared<Expression>(std::move(*_value)); varDecl.value = make_shared<Expression>(std::move(*_value));
else
varDecl.value = make_shared<Expression>(zero);
newStatements.emplace_back(std::move(varDecl)); newStatements.emplace_back(std::move(varDecl));
}; };

View File

@ -21,6 +21,7 @@
#include <libyul/optimiser/Suite.h> #include <libyul/optimiser/Suite.h>
#include <libyul/optimiser/Disambiguator.h> #include <libyul/optimiser/Disambiguator.h>
#include <libyul/optimiser/VarDeclInitializer.h>
#include <libyul/optimiser/FunctionGrouper.h> #include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/FunctionHoister.h>
#include <libyul/optimiser/ExpressionSplitter.h> #include <libyul/optimiser/ExpressionSplitter.h>
@ -35,7 +36,6 @@
#include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/StructuralSimplifier.h> #include <libyul/optimiser/StructuralSimplifier.h>
#include <libyul/optimiser/RedundantAssignEliminator.h> #include <libyul/optimiser/RedundantAssignEliminator.h>
#include <libyul/optimiser/VarDeclPropagator.h>
#include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmAnalysisInfo.h>
#include <libyul/AsmData.h> #include <libyul/AsmData.h>
#include <libyul/AsmPrinter.h> #include <libyul/AsmPrinter.h>
@ -56,6 +56,7 @@ void OptimiserSuite::run(
Block ast = boost::get<Block>(Disambiguator(_analysisInfo, reservedIdentifiers)(_ast)); Block ast = boost::get<Block>(Disambiguator(_analysisInfo, reservedIdentifiers)(_ast));
(VarDeclInitializer{})(ast);
(FunctionHoister{})(ast); (FunctionHoister{})(ast);
(FunctionGrouper{})(ast); (FunctionGrouper{})(ast);
(ForLoopInitRewriter{})(ast); (ForLoopInitRewriter{})(ast);
@ -68,7 +69,6 @@ void OptimiserSuite::run(
ExpressionSplitter{dispenser}(ast); ExpressionSplitter{dispenser}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
VarDeclPropagator{}(ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{}(ast);
@ -95,27 +95,22 @@ void OptimiserSuite::run(
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{}(ast);
FullInliner{ast, dispenser}.run(); FullInliner{ast, dispenser}.run();
VarDeclPropagator{}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
VarDeclPropagator{}(ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
ExpressionSimplifier::run(ast); ExpressionSimplifier::run(ast);
StructuralSimplifier{}(ast); StructuralSimplifier{}(ast);
CommonSubexpressionEliminator{}(ast); CommonSubexpressionEliminator{}(ast);
SSATransform::run(ast, dispenser); SSATransform::run(ast, dispenser);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
VarDeclPropagator{}(ast);
RedundantAssignEliminator::run(ast); RedundantAssignEliminator::run(ast);
UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); UnusedPruner::runUntilStabilised(ast, reservedIdentifiers);
} }
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
VarDeclPropagator{}(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
VarDeclPropagator{}(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(ast);
ExpressionJoiner::run(ast); ExpressionJoiner::run(ast);
UnusedPruner::runUntilStabilised(ast); UnusedPruner::runUntilStabilised(ast);

View File

@ -0,0 +1,56 @@
/*
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/VarDeclInitializer.h>
#include <libyul/AsmData.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/Visitor.h>
using namespace std;
using namespace dev;
using namespace yul;
void VarDeclInitializer::operator()(Block& _block)
{
ASTModifier::operator()(_block);
static Expression const zero{Literal{{}, LiteralKind::Number, YulString{"0"}, {}}};
using OptionalStatements = boost::optional<vector<Statement>>;
GenericFallbackReturnsVisitor<OptionalStatements, VariableDeclaration> visitor{
[](VariableDeclaration& _varDecl) -> OptionalStatements
{
if (_varDecl.value)
return {};
else if (_varDecl.variables.size() == 1)
{
_varDecl.value = make_shared<Expression>(zero);
return {};
}
else
{
OptionalStatements ret{vector<Statement>{}};
langutil::SourceLocation loc{std::move(_varDecl.location)};
for (auto& var: _varDecl.variables)
ret->push_back(VariableDeclaration{loc, {std::move(var)}, make_shared<Expression>(zero)});
return ret;
}
}
};
iterateReplacing(_block.statements, boost::apply_visitor(visitor));
}

View File

@ -0,0 +1,38 @@
/*
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/>.
*/
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/optimiser/ASTWalker.h>
namespace yul
{
/**
* Rewrites variable declarations so that all of them are initialized.
* Declarations like ``let x, y`` are split into multiple declaration
* statements.
* Only supports initializing with the zero literal for now.
*/
class VarDeclInitializer: public ASTModifier
{
public:
void operator()(Block& _block) override;
};
}

View File

@ -1,126 +0,0 @@
/*
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/VarDeclPropagator.h>
#include <libyul/AsmData.h>
#include <libdevcore/CommonData.h>
#include <boost/range/algorithm_ext/erase.hpp>
#include <algorithm>
#include <map>
using namespace std;
using namespace dev;
using namespace yul;
void VarDeclPropagator::operator()(Block& _block)
{
map<YulString, TypedName> outerEmptyVarDecls;
map<YulString, TypedName> outerLazyInitializedVarDecls;
swap(m_emptyVarDecls, outerEmptyVarDecls);
swap(m_lazyInitializedVarDecls, outerLazyInitializedVarDecls);
ASTModifier::operator()(_block);
iterateReplacing(
_block.statements,
[this](Statement& _stmt) -> boost::optional<vector<Statement>>
{
if (_stmt.type() == typeid(VariableDeclaration))
{
VariableDeclaration& varDecl = boost::get<VariableDeclaration>(_stmt);
boost::remove_erase_if(
varDecl.variables,
[&](TypedName const& _typedName) { return m_lazyInitializedVarDecls.count(_typedName.name); }
);
if (varDecl.variables.empty())
return vector<Statement>{};
else
return {};
}
else if (_stmt.type() == typeid(Assignment))
{
Assignment& assignment = boost::get<Assignment>(_stmt);
if (isFullyLazyInitialized(assignment.variableNames))
return vector<Statement>{recreateVariableDeclaration(assignment)};
else
return {};
}
else
return {};
}
);
swap(m_emptyVarDecls, outerEmptyVarDecls);
swap(m_lazyInitializedVarDecls, outerLazyInitializedVarDecls);
}
void VarDeclPropagator::operator()(VariableDeclaration& _varDecl)
{
if (_varDecl.value)
visit(*_varDecl.value);
else
for (TypedName const& typedName: _varDecl.variables)
m_emptyVarDecls[typedName.name] = typedName;
}
void VarDeclPropagator::operator()(Assignment& _assignment)
{
visit(*_assignment.value);
if (allVarNamesUninitialized(_assignment.variableNames))
for (Identifier const& ident: _assignment.variableNames)
m_lazyInitializedVarDecls[ident.name] = m_emptyVarDecls[ident.name];
for (Identifier& name: _assignment.variableNames)
(*this)(name);
}
void VarDeclPropagator::operator()(Identifier& _ident)
{
m_emptyVarDecls.erase(_ident.name);
}
bool VarDeclPropagator::allVarNamesUninitialized(vector<Identifier> const& _variableNames) const
{
return all_of(
begin(_variableNames),
end(_variableNames),
[&](Identifier const& _ident) -> bool { return m_emptyVarDecls.count(_ident.name); }
);
}
bool VarDeclPropagator::isFullyLazyInitialized(vector<Identifier> const& _variableNames) const
{
return all_of(
begin(_variableNames),
end(_variableNames),
[&](Identifier const& ident) -> bool { return m_lazyInitializedVarDecls.count(ident.name); }
);
}
VariableDeclaration VarDeclPropagator::recreateVariableDeclaration(Assignment& _assignment)
{
TypedNameList variables;
for (Identifier const& varName: _assignment.variableNames)
{
variables.emplace_back(move(m_lazyInitializedVarDecls.at(varName.name)));
m_lazyInitializedVarDecls.erase(varName.name);
}
return VariableDeclaration{move(_assignment.location), move(variables), std::move(_assignment.value)};
}

View File

@ -1,60 +0,0 @@
/*
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/>.
*/
#pragma once
#include <libyul/AsmDataForward.h>
#include <libyul/optimiser/ASTWalker.h>
#include <libyul/Exceptions.h>
#include <libyul/AsmDataForward.h>
#include <vector>
#include <set>
#include <map>
namespace yul
{
/**
* Rewrites Assignment statements into VariableDeclaration when the assignment's LHS
* variables had no value yet.
*
* It recursively walks through the AST and moves each declaration of variables to
* the first assignment within the same block (if possible)..
*/
class VarDeclPropagator: public ASTModifier
{
public:
using ASTModifier::operator();
void operator()(Block& _block) override;
void operator()(VariableDeclaration& _varDecl) override;
void operator()(Assignment& _assignment) override;
void operator()(Identifier& _ident) override;
private:
bool allVarNamesUninitialized(std::vector<Identifier> const& _variableNames) const;
bool isFullyLazyInitialized(std::vector<Identifier> const& _variableNames) const;
VariableDeclaration recreateVariableDeclaration(Assignment& _assignment);
private:
/// Holds a list of variables from current Block that have no value assigned yet.
std::map<YulString, TypedName> m_emptyVarDecls;
/// Holds a list variables (and their TypedName) within the current block.
std::map<YulString, TypedName> m_lazyInitializedVarDecls;
};
}

View File

@ -22,7 +22,7 @@
#include <test/Options.h> #include <test/Options.h>
#include <libyul/optimiser/BlockFlattener.h> #include <libyul/optimiser/BlockFlattener.h>
#include <libyul/optimiser/VarDeclPropagator.h> #include <libyul/optimiser/VarDeclInitializer.h>
#include <libyul/optimiser/Disambiguator.h> #include <libyul/optimiser/Disambiguator.h>
#include <libyul/optimiser/CommonSubexpressionEliminator.h> #include <libyul/optimiser/CommonSubexpressionEliminator.h>
#include <libyul/optimiser/NameCollector.h> #include <libyul/optimiser/NameCollector.h>
@ -107,11 +107,8 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
disambiguate(); disambiguate();
BlockFlattener{}(*m_ast); BlockFlattener{}(*m_ast);
} }
else if (m_optimizerStep == "varDeclPropagator") else if (m_optimizerStep == "varDeclInitializer")
{ VarDeclInitializer{}(*m_ast);
disambiguate();
VarDeclPropagator{}(*m_ast);
}
else if (m_optimizerStep == "forLoopInitRewriter") else if (m_optimizerStep == "forLoopInitRewriter")
{ {
disambiguate(); disambiguate();

View File

@ -9,14 +9,14 @@
// { // {
// { // {
// let f_a := calldataload(0) // let f_a := calldataload(0)
// let f_b // let f_b := 0
// let f_c // let f_c := 0
// f_b := sload(mload(f_a)) // f_b := sload(mload(f_a))
// f_c := 3 // f_c := 3
// let b3 := f_b // let b3 := f_b
// let f_a_2 := f_c // let f_a_2 := f_c
// let f_b_3 // let f_b_3 := 0
// let f_c_4 // let f_c_4 := 0
// f_b_3 := sload(mload(f_a_2)) // f_b_3 := sload(mload(f_a_2))
// f_c_4 := 3 // f_c_4 := 3
// let b4 := f_b_3 // let b4 := f_b_3

View File

@ -14,7 +14,7 @@
// { // {
// let _2 := mload(0) // let _2 := mload(0)
// let f_a := mload(1) // let f_a := mload(1)
// let f_r // let f_r := 0
// f_a := mload(f_a) // f_a := mload(f_a)
// f_r := add(f_a, calldatasize()) // f_r := add(f_a, calldatasize())
// if gt(f_r, _2) // if gt(f_r, _2)

View File

@ -23,7 +23,7 @@
// let a2 := 2 // let a2 := 2
// let r := f(a_1) // let r := f(a_1)
// let f_a := a2 // let f_a := a2
// let f_b // let f_b := 0
// let f_x := mload(f_a) // let f_x := mload(f_a)
// f_b := sload(f_x) // f_b := sload(f_x)
// let f_y := add(f_a, f_x) // let f_y := add(f_a, f_x)
@ -31,7 +31,7 @@
// let t := f_b // let t := f_b
// let a3 // let a3
// let f_a_3 := a3 // let f_a_3 := a3
// let f_b_4 // let f_b_4 := 0
// let f_x_5 := mload(f_a_3) // let f_x_5 := mload(f_a_3)
// f_b_4 := sload(f_x_5) // f_b_4 := sload(f_x_5)
// let f_y_6 := add(f_a_3, f_x_5) // let f_y_6 := add(f_a_3, f_x_5)

View File

@ -15,7 +15,7 @@
// { // {
// { // {
// let f_a := mload(1) // let f_a := mload(1)
// let f_b // let f_b := 0
// let f_x := mload(f_a) // let f_x := mload(f_a)
// f_b := sload(f_x) // f_b := sload(f_x)
// let f_c := 3 // let f_c := 3

View File

@ -13,7 +13,7 @@
// { // {
// let verylongvariablename2_1 := 3 // let verylongvariablename2_1 := 3
// let verylongfu_verylongvariablename := verylongvariablename2_1 // let verylongfu_verylongvariablename := verylongvariablename2_1
// let verylongfu_verylongvariablename2 // let verylongfu_verylongvariablename2 := 0
// verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename) // verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename)
// mstore(0, verylongfu_verylongvariablename2) // mstore(0, verylongfu_verylongvariablename2)
// mstore(1, verylongvariablename2_1) // mstore(1, verylongvariablename2_1)

View File

@ -15,7 +15,7 @@
// let f_a := mload(2) // let f_a := mload(2)
// let f_b := _6 // let f_b := _6
// let f_c := _4 // let f_c := _4
// let f_x // let f_x := 0
// f_x := add(f_a, f_b) // f_x := add(f_a, f_b)
// f_x := mul(f_x, f_c) // f_x := mul(f_x, f_c)
// let _10 := add(f_x, _2) // let _10 := add(f_x, _2)

View File

@ -9,11 +9,11 @@
// { // {
// let _1 := 7 // let _1 := 7
// let f_a := 3 // let f_a := 3
// let f_x // let f_x := 0
// f_x := add(f_a, f_a) // f_x := add(f_a, f_a)
// let g_b := f_x // let g_b := f_x
// let g_c := _1 // let g_c := _1
// let g_y // let g_y := 0
// g_y := mul(mload(g_c), f(g_b)) // g_y := mul(mload(g_c), f(g_b))
// let y_1 := g_y // let y_1 := g_y
// } // }
@ -24,7 +24,7 @@
// function g(b, c) -> y // function g(b, c) -> y
// { // {
// let f_a_6 := b // let f_a_6 := b
// let f_x_7 // let f_x_7 := 0
// f_x_7 := add(f_a_6, f_a_6) // f_x_7 := add(f_a_6, f_a_6)
// y := mul(mload(c), f_x_7) // y := mul(mload(c), f_x_7)
// } // }

View File

@ -37,7 +37,7 @@
// function f(x) // function f(x)
// { // {
// mstore(0, x) // mstore(0, x)
// let h_t // let h_t := 0
// h_t := 2 // h_t := 2
// mstore(7, h_t) // mstore(7, h_t)
// let g_x_1 := 10 // let g_x_1 := 10

View File

@ -11,8 +11,8 @@
// { // {
// { // {
// let f_a := mload(0) // let f_a := mload(0)
// let f_x // let f_x := 0
// let f_y // let f_y := 0
// f_x := mul(f_a, f_a) // f_x := mul(f_a, f_a)
// f_y := add(f_a, f_x) // f_y := add(f_a, f_x)
// let r := f_x // let r := f_x

View File

@ -19,25 +19,25 @@
// function g() -> x_1 // function g() -> x_1
// { // {
// let f_a := 2 // let f_a := 2
// let f_b // let f_b := 0
// f_b := sload(mload(f_a)) // f_b := sload(mload(f_a))
// let f_a_20 := f_b // let f_a_20 := f_b
// let f_b_21 // let f_b_21 := 0
// f_b_21 := sload(mload(f_a_20)) // f_b_21 := sload(mload(f_a_20))
// let f_a_23 := f_b_21 // let f_a_23 := f_b_21
// let f_b_24 // let f_b_24 := 0
// f_b_24 := sload(mload(f_a_23)) // f_b_24 := sload(mload(f_a_23))
// let f_a_26 := f_b_24 // let f_a_26 := f_b_24
// let f_b_27 // let f_b_27 := 0
// f_b_27 := sload(mload(f_a_26)) // f_b_27 := sload(mload(f_a_26))
// let f_a_29 := f_b_27 // let f_a_29 := f_b_27
// let f_b_30 // let f_b_30 := 0
// f_b_30 := sload(mload(f_a_29)) // f_b_30 := sload(mload(f_a_29))
// let f_a_32 := f_b_30 // let f_a_32 := f_b_30
// let f_b_33 // let f_b_33 := 0
// f_b_33 := sload(mload(f_a_32)) // f_b_33 := sload(mload(f_a_32))
// let f_a_35 := f_b_33 // let f_a_35 := f_b_33
// let f_b_36 // let f_b_36 := 0
// f_b_36 := sload(mload(f_a_35)) // f_b_36 := sload(mload(f_a_35))
// x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36)))))))))))) // x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36))))))))))))
// } // }

View File

@ -12,25 +12,25 @@
// { // {
// { // {
// let f_a := 2 // let f_a := 2
// let f_b // let f_b := 0
// f_b := sload(mload(f_a)) // f_b := sload(mload(f_a))
// let f_a_20 := f_b // let f_a_20 := f_b
// let f_b_21 // let f_b_21 := 0
// f_b_21 := sload(mload(f_a_20)) // f_b_21 := sload(mload(f_a_20))
// let f_a_23 := f_b_21 // let f_a_23 := f_b_21
// let f_b_24 // let f_b_24 := 0
// f_b_24 := sload(mload(f_a_23)) // f_b_24 := sload(mload(f_a_23))
// let f_a_26 := f_b_24 // let f_a_26 := f_b_24
// let f_b_27 // let f_b_27 := 0
// f_b_27 := sload(mload(f_a_26)) // f_b_27 := sload(mload(f_a_26))
// let f_a_29 := f_b_27 // let f_a_29 := f_b_27
// let f_b_30 // let f_b_30 := 0
// f_b_30 := sload(mload(f_a_29)) // f_b_30 := sload(mload(f_a_29))
// let f_a_32 := f_b_30 // let f_a_32 := f_b_30
// let f_b_33 // let f_b_33 := 0
// f_b_33 := sload(mload(f_a_32)) // f_b_33 := sload(mload(f_a_32))
// let f_a_35 := f_b_33 // let f_a_35 := f_b_33
// let f_b_36 // let f_b_36 := 0
// f_b_36 := sload(mload(f_a_35)) // f_b_36 := sload(mload(f_a_35))
// let x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36)))))))))))) // let x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36))))))))))))
// } // }

View File

@ -14,7 +14,7 @@
// { // {
// for { // for {
// let f_a := 0 // let f_a := 0
// let f_r // let f_r := 0
// sstore(f_a, 0) // sstore(f_a, 0)
// f_r := f_a // f_r := f_a
// let x := f_r // let x := f_r
@ -22,14 +22,14 @@
// f(x) // f(x)
// { // {
// let f_a_3 := x // let f_a_3 := x
// let f_r_4 // let f_r_4 := 0
// sstore(f_a_3, 0) // sstore(f_a_3, 0)
// f_r_4 := f_a_3 // f_r_4 := f_a_3
// x := f_r_4 // x := f_r_4
// } // }
// { // {
// let f_a_6 := x // let f_a_6 := x
// let f_r_7 // let f_r_7 := 0
// sstore(f_a_6, 0) // sstore(f_a_6, 0)
// f_r_7 := f_a_6 // f_r_7 := f_a_6
// let t := f_r_7 // let t := f_r_7

View File

@ -14,7 +14,7 @@
// { // {
// let _1 := 2 // let _1 := 2
// let f_a := 7 // let f_a := 7
// let f_x // let f_x := 0
// let f_r := mul(f_a, f_a) // let f_r := mul(f_a, f_a)
// f_x := add(f_r, f_r) // f_x := add(f_r, f_r)
// pop(add(f_x, _1)) // pop(add(f_x, _1))

View File

@ -11,7 +11,7 @@
// { // {
// let _2 := mload(7) // let _2 := mload(7)
// let f_a := sload(mload(2)) // let f_a := sload(mload(2))
// let f_x // let f_x := 0
// let f_r := mul(f_a, f_a) // let f_r := mul(f_a, f_a)
// f_x := add(f_r, f_r) // f_x := add(f_r, f_r)
// let y := add(f_x, _2) // let y := add(f_x, _2)

View File

@ -463,12 +463,11 @@
// let _2 := 0 // let _2 := 0
// let _485 := mload(_2) // let _485 := mload(_2)
// let abi_encode_pos := _1 // let abi_encode_pos := _1
// let abi_encode_end_67_610
// let abi_encode_length_68 := mload(_485) // let abi_encode_length_68 := mload(_485)
// mstore(_1, abi_encode_length_68) // mstore(_1, abi_encode_length_68)
// abi_encode_pos := 64 // abi_encode_pos := 64
// let abi_encode_srcPtr := add(_485, _1) // let abi_encode_srcPtr := add(_485, _1)
// let abi_encode_i_69 := abi_encode_end_67_610 // let abi_encode_i_69 := _2
// for { // for {
// } // }
// lt(abi_encode_i_69, abi_encode_length_68) // lt(abi_encode_i_69, abi_encode_length_68)
@ -476,21 +475,21 @@
// abi_encode_i_69 := add(abi_encode_i_69, 1) // abi_encode_i_69 := add(abi_encode_i_69, 1)
// } // }
// { // {
// let _857 := mload(abi_encode_srcPtr) // let _863 := mload(abi_encode_srcPtr)
// let abi_encode_pos_71_965 := abi_encode_pos // let abi_encode_pos_71_971 := abi_encode_pos
// let abi_encode_length_72_966 := 0x3 // let abi_encode_length_72_972 := 0x3
// let abi_encode_srcPtr_73_967 := _857 // let abi_encode_srcPtr_73_973 := _863
// let abi_encode_i_74_968 := _2 // let abi_encode_i_74_974 := _2
// for { // for {
// } // }
// lt(abi_encode_i_74_968, abi_encode_length_72_966) // lt(abi_encode_i_74_974, abi_encode_length_72_972)
// { // {
// abi_encode_i_74_968 := add(abi_encode_i_74_968, 1) // abi_encode_i_74_974 := add(abi_encode_i_74_974, 1)
// } // }
// { // {
// mstore(abi_encode_pos_71_965, and(mload(abi_encode_srcPtr_73_967), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) // mstore(abi_encode_pos_71_971, and(mload(abi_encode_srcPtr_73_973), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
// abi_encode_srcPtr_73_967 := add(abi_encode_srcPtr_73_967, _1) // abi_encode_srcPtr_73_973 := add(abi_encode_srcPtr_73_973, _1)
// abi_encode_pos_71_965 := add(abi_encode_pos_71_965, _1) // abi_encode_pos_71_971 := add(abi_encode_pos_71_971, _1)
// } // }
// abi_encode_srcPtr := add(abi_encode_srcPtr, _1) // abi_encode_srcPtr := add(abi_encode_srcPtr, _1)
// abi_encode_pos := add(abi_encode_pos, 0x60) // abi_encode_pos := add(abi_encode_pos, 0x60)

View File

@ -0,0 +1,29 @@
{
// This component does not need the disambiguator
function f() -> x, y {
let a, b
mstore(a, b)
let d
d := 2
}
let a
a := 4
let b := 2
let x, y := f()
}
// ----
// varDeclInitializer
// {
// function f() -> x, y
// {
// let a := 0
// let b := 0
// mstore(a, b)
// let d := 0
// d := 2
// }
// let a := 0
// a := 4
// let b := 2
// let x, y := f()
// }

View File

@ -0,0 +1,24 @@
{
function f() -> x, y {
let a, b
mstore(a, b)
let d
d := 2
}
let r
r := 4
}
// ----
// varDeclInitializer
// {
// function f() -> x, y
// {
// let a := 0
// let b := 0
// mstore(a, b)
// let d := 0
// d := 2
// }
// let r := 0
// r := 4
// }

View File

@ -0,0 +1,14 @@
{
let x, y, z
let a
let b
}
// ----
// varDeclInitializer
// {
// let x := 0
// let y := 0
// let z := 0
// let a := 0
// let b := 0
// }

View File

@ -0,0 +1,21 @@
{
function f() -> x, y {
let a, b := f()
let u
}
let r
let s := 3
let t
}
// ----
// varDeclInitializer
// {
// function f() -> x, y
// {
// let a, b := f()
// let u := 0
// }
// let r := 0
// let s := 3
// let t := 0
// }

View File

@ -0,0 +1,8 @@
{
let a
}
// ----
// varDeclInitializer
// {
// let a := 0
// }

View File

@ -1,17 +0,0 @@
{
let a := 4
let x
if a {
x := 2
}
}
// ----
// varDeclPropagator
// {
// let a := 4
// let x
// if a
// {
// x := 2
// }
// }

View File

@ -1,13 +0,0 @@
{
function f() -> a, b, c {}
let x, y, z
z, x, y := f()
}
// ----
// varDeclPropagator
// {
// function f() -> a, b, c
// {
// }
// let z, x, y := f()
// }

View File

@ -1,11 +0,0 @@
{
let a
a := 4
a := 5
}
// ----
// varDeclPropagator
// {
// let a := 4
// a := 5
// }

View File

@ -1,10 +0,0 @@
{
let a, b
a := mload(0)
}
// ----
// varDeclPropagator
// {
// let b
// let a := mload(0)
// }

View File

@ -1,9 +0,0 @@
{
let f
f := mload(0)
}
// ----
// varDeclPropagator
// {
// let f := mload(0)
// }

View File

@ -1,11 +0,0 @@
{
let a, b
a := mload(0)
b := mload(1)
}
// ----
// varDeclPropagator
// {
// let a := mload(0)
// let b := mload(1)
// }

View File

@ -1,12 +0,0 @@
{
let b
let a := b
b := 1
}
// ----
// varDeclPropagator
// {
// let b
// let a := b
// b := 1
// }

View File

@ -1,16 +0,0 @@
{
function f(x) {}
let a
f(a)
a := 4
}
// ----
// varDeclPropagator
// {
// function f(x)
// {
// }
// let a
// f(a)
// a := 4
// }

View File

@ -47,7 +47,7 @@
#include <libyul/optimiser/RedundantAssignEliminator.h> #include <libyul/optimiser/RedundantAssignEliminator.h>
#include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/StructuralSimplifier.h> #include <libyul/optimiser/StructuralSimplifier.h>
#include <libyul/optimiser/VarDeclPropagator.h> #include <libyul/optimiser/VarDeclInitializer.h>
#include <libyul/backends/evm/EVMDialect.h> #include <libyul/backends/evm/EVMDialect.h>
@ -125,7 +125,7 @@ public:
m_nameDispenser = make_shared<NameDispenser>(*m_ast); m_nameDispenser = make_shared<NameDispenser>(*m_ast);
disambiguated = true; disambiguated = true;
} }
cout << "(q)quit/(f)flatten/(c)se/propagate var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl;
cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl; cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl;
cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter/" << endl; cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter/" << endl;
cout << " s(t)ructural simplifier? " << endl; cout << " s(t)ructural simplifier? " << endl;
@ -146,7 +146,7 @@ public:
(CommonSubexpressionEliminator{})(*m_ast); (CommonSubexpressionEliminator{})(*m_ast);
break; break;
case 'd': case 'd':
(VarDeclPropagator{})(*m_ast); (VarDeclInitializer{})(*m_ast);
break; break;
case 'x': case 'x':
ExpressionSplitter{*m_nameDispenser}(*m_ast); ExpressionSplitter{*m_nameDispenser}(*m_ast);