aboutsummaryrefslogtreecommitdiffstats
path: root/libyul/optimiser
diff options
context:
space:
mode:
authorDaniel Kirchner <daniel@ekpyron.org>2019-01-16 18:44:45 +0800
committerDaniel Kirchner <daniel@ekpyron.org>2019-01-18 03:37:43 +0800
commit6de2d92f20d48d38797a628ee35e7615170cd63f (patch)
tree7d34e8c7655b8558061fd58de1bc26f6e44f1aaa /libyul/optimiser
parent7c07e9498664c9b9dec6f332490d51c7a920de8b (diff)
downloaddexon-solidity-6de2d92f20d48d38797a628ee35e7615170cd63f.tar.gz
dexon-solidity-6de2d92f20d48d38797a628ee35e7615170cd63f.tar.zst
dexon-solidity-6de2d92f20d48d38797a628ee35e7615170cd63f.zip
Add SSAReverser to the yul optimiser.
Diffstat (limited to 'libyul/optimiser')
-rw-r--r--libyul/optimiser/SSAReverser.cpp71
-rw-r--r--libyul/optimiser/SSAReverser.h54
-rw-r--r--libyul/optimiser/Suite.cpp13
3 files changed, 135 insertions, 3 deletions
diff --git a/libyul/optimiser/SSAReverser.cpp b/libyul/optimiser/SSAReverser.cpp
new file mode 100644
index 00000000..313a677a
--- /dev/null
+++ b/libyul/optimiser/SSAReverser.cpp
@@ -0,0 +1,71 @@
+/*
+ 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/SSAReverser.h>
+#include <libyul/AsmData.h>
+#include <libdevcore/CommonData.h>
+
+using namespace std;
+using namespace dev;
+using namespace yul;
+
+void SSAReverser::operator()(Block& _block)
+{
+ walkVector(_block.statements);
+ iterateReplacingWindow<2>(
+ _block.statements,
+ [&](Statement& _stmt1, Statement& _stmt2) -> boost::optional<vector<Statement>>
+ {
+ // Replaces
+ // let a_1 := E
+ // a := a_1
+ // with
+ // a := E
+ // let a_1 := a
+
+ auto* varDecl = boost::get<VariableDeclaration>(&_stmt1);
+ auto* assignment = boost::get<Assignment>(&_stmt2);
+
+ if (!varDecl || !assignment)
+ return {};
+
+ auto* identifier = boost::get<Identifier>(assignment->value.get());
+
+ if (
+ varDecl->variables.size() == 1 &&
+ varDecl->value &&
+ assignment->variableNames.size() == 1 &&
+ identifier &&
+ identifier->name == varDecl->variables.front().name
+ )
+ {
+ vector<Statement> result;
+ result.emplace_back(Assignment{
+ std::move(assignment->location),
+ assignment->variableNames,
+ std::move(varDecl->value)
+ });
+ result.emplace_back(VariableDeclaration{
+ std::move(varDecl->location),
+ std::move(varDecl->variables),
+ std::make_unique<Expression>(std::move(assignment->variableNames.front()))
+ });
+ return { std::move(result) };
+ }
+ return {};
+ }
+ );
+}
diff --git a/libyul/optimiser/SSAReverser.h b/libyul/optimiser/SSAReverser.h
new file mode 100644
index 00000000..a4a11074
--- /dev/null
+++ b/libyul/optimiser/SSAReverser.h
@@ -0,0 +1,54 @@
+/*
+ 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/optimiser/ASTWalker.h>
+
+namespace yul
+{
+
+/**
+ * Reverses the SSA transformation.
+ *
+ * In particular, the SSA transform will rewrite
+ *
+ * a := E
+ *
+ * to
+ *
+ * let a_1 := E
+ * a := a_1
+ *
+ * To undo this transformation, the SSAReverser changes this back to
+ *
+ * a := E
+ * let a_1 := a
+ *
+ * After that the CSE can replace references of a_1 by references to a,
+ * after which the unused pruner can remove the declaration of a_1.
+ *
+ * Prerequisites: None
+ *
+ */
+class SSAReverser: public ASTModifier
+{
+public:
+ using ASTModifier::operator();
+ void operator()(Block& _block) override;
+};
+
+}
diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp
index 38c0bf49..63931554 100644
--- a/libyul/optimiser/Suite.cpp
+++ b/libyul/optimiser/Suite.cpp
@@ -35,6 +35,7 @@
#include <libyul/optimiser/UnusedPruner.h>
#include <libyul/optimiser/ExpressionSimplifier.h>
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
+#include <libyul/optimiser/SSAReverser.h>
#include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/StructuralSimplifier.h>
#include <libyul/optimiser/RedundantAssignEliminator.h>
@@ -88,9 +89,10 @@ void OptimiserSuite::run(
UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
CommonSubexpressionEliminator{_dialect}(ast);
UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
- SSATransform::run(ast, dispenser);
- RedundantAssignEliminator::run(_dialect, ast);
- RedundantAssignEliminator::run(_dialect, ast);
+
+ SSAReverser{}(ast);
+ CommonSubexpressionEliminator{_dialect}(ast);
+ UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
ExpressionJoiner::run(ast);
ExpressionJoiner::run(ast);
@@ -127,6 +129,11 @@ void OptimiserSuite::run(
UnusedPruner::runUntilStabilised(_dialect, ast);
ExpressionJoiner::run(ast);
UnusedPruner::runUntilStabilised(_dialect, ast);
+
+ SSAReverser{}(ast);
+ CommonSubexpressionEliminator{_dialect}(ast);
+ UnusedPruner::runUntilStabilised(_dialect, ast, reservedIdentifiers);
+
ExpressionJoiner::run(ast);
Rematerialiser::run(_dialect, ast);
UnusedPruner::runUntilStabilised(_dialect, ast);