diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt
index 3d6beefee..175a443a1 100644
--- a/libyul/CMakeLists.txt
+++ b/libyul/CMakeLists.txt
@@ -52,6 +52,8 @@ add_library(yul
optimiser/ASTCopier.h
optimiser/ASTWalker.cpp
optimiser/ASTWalker.h
+ optimiser/BlockDeepener.cpp
+ optimiser/BlockDeepener.h
optimiser/BlockFlattener.cpp
optimiser/BlockFlattener.h
optimiser/BlockClassFinder.cpp
diff --git a/libyul/optimiser/BlockDeepener.cpp b/libyul/optimiser/BlockDeepener.cpp
new file mode 100644
index 000000000..0c094b21e
--- /dev/null
+++ b/libyul/optimiser/BlockDeepener.cpp
@@ -0,0 +1,47 @@
+/*
+ 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 .
+*/
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+using namespace dev;
+using namespace yul;
+
+void BlockDeepener::operator()(Block& _block)
+{
+ ASTModifier::operator()(_block);
+
+ if (_block.statements.size() <= 1)
+ return ;
+ std::vector result;
+ std::vector *current = &result;
+ for (std::size_t i = 0; i < _block.statements.size() - 1; ++i)
+ {
+ current->emplace_back(std::move(_block.statements[i]));
+ current->emplace_back(Block{
+ _block.location,
+ {}
+ });
+ current = &boost::get(current->back()).statements;
+ }
+ current->emplace_back(std::move(_block.statements.back()));
+
+ _block.statements = std::move(result);
+}
diff --git a/libyul/optimiser/BlockDeepener.h b/libyul/optimiser/BlockDeepener.h
new file mode 100644
index 000000000..a0521fe95
--- /dev/null
+++ b/libyul/optimiser/BlockDeepener.h
@@ -0,0 +1,31 @@
+/*
+ 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 .
+*/
+#pragma once
+
+#include
+
+namespace yul
+{
+
+class BlockDeepener: public ASTModifier
+{
+public:
+ using ASTModifier::operator();
+ void operator()(Block& _block) override;
+};
+
+}
diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp
index fedc2ff0b..229889809 100644
--- a/test/libyul/YulOptimizerTest.cpp
+++ b/test/libyul/YulOptimizerTest.cpp
@@ -19,6 +19,7 @@
#include
+#include
#include
#include
#include
@@ -112,6 +113,11 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
if (m_optimizerStep == "disambiguator")
disambiguate();
+ else if (m_optimizerStep == "blockDeepener")
+ {
+ disambiguate();
+ BlockDeepener{}(*m_ast);
+ }
else if (m_optimizerStep == "blockFlattener")
{
disambiguate();
diff --git a/test/libyul/yulOptimizerTests/blockDeepener/basic.yul b/test/libyul/yulOptimizerTests/blockDeepener/basic.yul
new file mode 100644
index 000000000..776045df2
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/blockDeepener/basic.yul
@@ -0,0 +1,27 @@
+{
+ let _1 := mload(0)
+ let f_a := mload(1)
+ let f_r
+ f_a := mload(f_a)
+ f_r := add(f_a, calldatasize())
+ let z := mload(2)
+}
+// ====
+// step: blockDeepener
+// ----
+// {
+// let _1 := mload(0)
+// {
+// let f_a := mload(1)
+// {
+// let f_r
+// {
+// f_a := mload(f_a)
+// {
+// f_r := add(f_a, calldatasize())
+// { let z := mload(2) }
+// }
+// }
+// }
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul
new file mode 100644
index 000000000..efb88eb2d
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul
@@ -0,0 +1,14 @@
+{
+ for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) }
+ { a := add(a, 1) a := add(a,1) }
+}
+// ====
+// step: blockDeepener
+// ----
+// {
+// for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) }
+// {
+// a := add(a, 1)
+// { a := add(a, 1) }
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul
new file mode 100644
index 000000000..5d9f1eb43
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul
@@ -0,0 +1,19 @@
+{
+ if add(mload(7), sload(mload(3)))
+ {
+ let y := add(mload(3), 3)
+ y := add(y, 7)
+ }
+ let t := add(3, 9)
+}
+// ====
+// step: blockDeepener
+// ----
+// {
+// if add(mload(7), sload(mload(3)))
+// {
+// let y := add(mload(3), 3)
+// { y := add(y, 7) }
+// }
+// { let t := add(3, 9) }
+// }
diff --git a/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul b/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul
new file mode 100644
index 000000000..8d8d319b3
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul
@@ -0,0 +1,35 @@
+{
+ let a := 3
+ let b := 4
+ a := add(b, 3)
+ let c := 5
+ b := add(b, 4)
+ c := add(a, 5)
+ b := add(a, b)
+ a := add(a, c)
+}
+// ====
+// step: blockDeepener
+// ----
+// {
+// let a := 3
+// {
+// let b := 4
+// {
+// a := add(b, 3)
+// {
+// let c := 5
+// {
+// b := add(b, 4)
+// {
+// c := add(a, 5)
+// {
+// b := add(a, b)
+// { a := add(a, c) }
+// }
+// }
+// }
+// }
+// }
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul
new file mode 100644
index 000000000..b3d5288c0
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul
@@ -0,0 +1,31 @@
+{
+ let a := 1
+ switch calldataload(0)
+ case 0 {
+ mstore(0, 1)
+ a := 8
+ }
+ default {
+ a := 3
+ a := 4
+ }
+ a := 5
+}
+// ====
+// step: blockDeepener
+// ----
+// {
+// let a := 1
+// {
+// switch calldataload(0)
+// case 0 {
+// mstore(0, 1)
+// { a := 8 }
+// }
+// default {
+// a := 3
+// { a := 4 }
+// }
+// { a := 5 }
+// }
+// }