aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libyul/optimiser/README.md2
-rw-r--r--libyul/optimiser/UnusedPruner.cpp10
-rw-r--r--libyul/optimiser/UnusedPruner.h6
-rw-r--r--test/libyul/yulOptimizerTests/fullSuite/medium.yul4
-rw-r--r--test/libyul/yulOptimizerTests/unusedPruner/pop.yul8
5 files changed, 23 insertions, 7 deletions
diff --git a/libyul/optimiser/README.md b/libyul/optimiser/README.md
index faef818b..c2575179 100644
--- a/libyul/optimiser/README.md
+++ b/libyul/optimiser/README.md
@@ -135,6 +135,8 @@ If there are two assignments to a variable where the first one is a movable expr
and the variable is not used between the two assignments (and the second is not inside
a loop or conditional, the first one is not inside), the first assignment is removed.
+This step also removes movable expression statements.
+
## Function Unifier
diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp
index a7b32873..71e86798 100644
--- a/libyul/optimiser/UnusedPruner.cpp
+++ b/libyul/optimiser/UnusedPruner.cpp
@@ -85,6 +85,16 @@ void UnusedPruner::operator()(Block& _block)
}};
}
}
+ else if (statement.type() == typeid(ExpressionStatement))
+ {
+ ExpressionStatement& exprStmt = boost::get<ExpressionStatement>(statement);
+ if (MovableChecker(exprStmt.expression).movable())
+ {
+ // pop(x) should be movable!
+ subtractReferences(ReferencesCounter::countReferences(exprStmt.expression));
+ statement = Block{std::move(exprStmt.location), {}};
+ }
+ }
removeEmptyBlocks(_block);
diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h
index 2dd74940..b5aea3dd 100644
--- a/libyul/optimiser/UnusedPruner.h
+++ b/libyul/optimiser/UnusedPruner.h
@@ -32,10 +32,8 @@ namespace yul
{
/**
- * Optimisation stage that removes unused variables and functions.
- *
- * TODO: Also remove intermediate variable assignments from movable expressions
- * which are not referenced until after the next assignment to the same variable.
+ * Optimisation stage that removes unused variables and functions and also
+ * removes movable expression statements.
*
* Note that this does not remove circular references.
*
diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul
index 47812fa8..deb02068 100644
--- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul
+++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul
@@ -16,9 +16,7 @@
// {
// let _18 := 0x20
// let allocate__7 := 0x40
-// let allocate_p_12 := mload(allocate__7)
-// mstore(allocate__7, add(allocate_p_12, _18))
-// pop(allocate_p_12)
+// mstore(allocate__7, add(mload(allocate__7), _18))
// let allocate_p_12_31 := mload(allocate__7)
// mstore(allocate__7, add(allocate_p_12_31, allocate__7))
// mstore(add(allocate_p_12_31, 96), 2)
diff --git a/test/libyul/yulOptimizerTests/unusedPruner/pop.yul b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul
new file mode 100644
index 00000000..542070f9
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/unusedPruner/pop.yul
@@ -0,0 +1,8 @@
+{
+ let a := 1
+ pop(a)
+}
+// ----
+// unusedPruner
+// {
+// }