aboutsummaryrefslogtreecommitdiffstats
path: root/test/libyul
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-12-20 01:06:13 +0800
committerGitHub <noreply@github.com>2018-12-20 01:06:13 +0800
commit1df8f40cd2fd7b47698d847907b8ca7b47eb488d (patch)
tree5ed5816fe2d1a8a207e750d39884aca7957c8289 /test/libyul
parentc8a2cb62832afb2dc09ccee6fd42c1516dfdb981 (diff)
parentddf54b21d1d002903624f61173ab4af197f50053 (diff)
downloaddexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.tar.gz
dexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.tar.zst
dexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.zip
Merge pull request #5697 from ethereum/develop
Merge develop into release for 0.5.2
Diffstat (limited to 'test/libyul')
-rw-r--r--test/libyul/Common.cpp13
-rw-r--r--test/libyul/Common.h3
-rw-r--r--test/libyul/ObjectCompilerTest.cpp134
-rw-r--r--test/libyul/ObjectCompilerTest.h69
-rw-r--r--test/libyul/Parser.cpp65
-rw-r--r--test/libyul/StackReuseCodegen.cpp353
-rw-r--r--test/libyul/YulOptimizerTest.cpp30
-rw-r--r--test/libyul/YulOptimizerTest.h2
-rw-r--r--test/libyul/objectCompiler/data.yul11
-rw-r--r--test/libyul/objectCompiler/datacopy.yul48
-rw-r--r--test/libyul/objectCompiler/dataoffset_code.yul29
-rw-r--r--test/libyul/objectCompiler/dataoffset_data.yul16
-rw-r--r--test/libyul/objectCompiler/dataoffset_self.yul16
-rw-r--r--test/libyul/objectCompiler/datasize_code.yul29
-rw-r--r--test/libyul/objectCompiler/datasize_data.yul16
-rw-r--r--test/libyul/objectCompiler/datasize_self.yul16
-rw-r--r--test/libyul/objectCompiler/namedObject.yul6
-rw-r--r--test/libyul/objectCompiler/namedObjectCode.yul13
-rw-r--r--test/libyul/objectCompiler/nested_optimizer.yul49
-rw-r--r--test/libyul/objectCompiler/simple.yul13
-rw-r--r--test/libyul/objectCompiler/simple_optimizer.yul23
-rw-r--r--test/libyul/objectCompiler/smoke.yul5
-rw-r--r--test/libyul/objectCompiler/subObject.yul21
-rw-r--r--test/libyul/objectCompiler/subSubObject.yul39
-rw-r--r--test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul23
-rw-r--r--test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul14
-rw-r--r--test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul14
-rw-r--r--test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul14
-rw-r--r--test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul11
-rw-r--r--test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul13
-rw-r--r--test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul48
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/double_inline.yul8
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul19
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/long_names.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul6
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/multi_return.yul4
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul44
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul41
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul6
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/pop_result.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullInliner/simple.yul2
-rw-r--r--test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul288
-rw-r--r--test/libyul/yulOptimizerTests/fullSuite/medium.yul19
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul7
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul6
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol10
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul5
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul10
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul6
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul9
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul6
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul11
-rw-r--r--test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul11
-rw-r--r--test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul29
-rw-r--r--test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul24
-rw-r--r--test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul14
-rw-r--r--test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul21
-rw-r--r--test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul8
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul17
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul13
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul11
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul10
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul9
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul11
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul12
-rw-r--r--test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul16
70 files changed, 1575 insertions, 306 deletions
diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp
index a247a169..a337fa8d 100644
--- a/test/libyul/Common.cpp
+++ b/test/libyul/Common.cpp
@@ -29,6 +29,7 @@
#include <libyul/AsmParser.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmPrinter.h>
+#include <libyul/backends/evm/EVMDialect.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h>
@@ -40,9 +41,9 @@ using namespace langutil;
using namespace yul;
using namespace dev::solidity;
-void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner)
+void yul::test::printErrors(ErrorList const& _errors)
{
- SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; });
+ SourceReferenceFormatter formatter(cout);
for (auto const& error: _errors)
formatter.printExceptionInformation(
@@ -54,11 +55,11 @@ void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner)
pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul)
{
- auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict;
+ shared_ptr<Dialect> dialect = _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM();
ErrorList errors;
ErrorReporter errorReporter(errors);
auto scanner = make_shared<Scanner>(CharStream(_source, ""));
- auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false);
+ auto parserResult = yul::Parser(errorReporter, dialect).parse(scanner, false);
if (parserResult)
{
BOOST_REQUIRE(errorReporter.errors().empty());
@@ -68,7 +69,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin
errorReporter,
dev::test::Options::get().evmVersion(),
boost::none,
- flavour
+ dialect
);
if (analyzer.analyze(*parserResult))
{
@@ -76,7 +77,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin
return make_pair(parserResult, analysisInfo);
}
}
- printErrors(errors, *scanner);
+ printErrors(errors);
BOOST_FAIL("Invalid source.");
// Unreachable.
diff --git a/test/libyul/Common.h b/test/libyul/Common.h
index a1c64ca5..01fc416a 100644
--- a/test/libyul/Common.h
+++ b/test/libyul/Common.h
@@ -29,7 +29,6 @@
namespace langutil
{
-class Scanner;
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
}
@@ -44,7 +43,7 @@ namespace yul
namespace test
{
-void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner);
+void printErrors(langutil::ErrorList const& _errors);
std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>>
parse(std::string const& _source, bool _yul = true);
Block disambiguate(std::string const& _source, bool _yul = true);
diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp
new file mode 100644
index 00000000..e60f718d
--- /dev/null
+++ b/test/libyul/ObjectCompilerTest.cpp
@@ -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 <test/libyul/ObjectCompilerTest.h>
+
+#include <test/libsolidity/FormattedScope.h>
+
+#include <libsolidity/interface/AssemblyStack.h>
+
+#include <libevmasm/Instruction.h>
+
+#include <liblangutil/SourceReferenceFormatter.h>
+
+#include <boost/algorithm/string.hpp>
+
+#include <fstream>
+
+using namespace dev;
+using namespace langutil;
+using namespace yul;
+using namespace yul::test;
+using namespace dev::solidity;
+using namespace dev::solidity::test;
+using namespace std;
+
+ObjectCompilerTest::ObjectCompilerTest(string const& _filename)
+{
+ boost::filesystem::path path(_filename);
+
+ ifstream file(_filename);
+ if (!file)
+ BOOST_THROW_EXCEPTION(runtime_error("Cannot open test case: \"" + _filename + "\"."));
+ file.exceptions(ios::badbit);
+
+ string line;
+ while (getline(file, line))
+ {
+ if (boost::algorithm::starts_with(line, "// ----"))
+ break;
+ if (m_source.empty() && boost::algorithm::starts_with(line, "// optimize"))
+ m_optimize = true;
+ m_source += line + "\n";
+ }
+ while (getline(file, line))
+ if (boost::algorithm::starts_with(line, "//"))
+ m_expectation += line.substr((line.size() >= 3 && line[2] == ' ') ? 3 : 2) + "\n";
+ else
+ m_expectation += line + "\n";
+}
+
+bool ObjectCompilerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
+{
+ AssemblyStack stack(EVMVersion(), AssemblyStack::Language::StrictAssembly);
+ if (!stack.parseAndAnalyze("source", m_source))
+ {
+ FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
+ printErrors(_stream, stack.errors());
+ return false;
+ }
+ if (m_optimize)
+ stack.optimize();
+
+ MachineAssemblyObject obj = stack.assemble(AssemblyStack::Machine::EVM);
+ solAssert(obj.bytecode, "");
+
+ m_obtainedResult = "Assembly:\n" + obj.assembly;
+ if (obj.bytecode->bytecode.empty())
+ m_obtainedResult += "-- empty bytecode --\n";
+ else
+ m_obtainedResult +=
+ "Bytecode: " +
+ toHex(obj.bytecode->bytecode) +
+ "\nOpcodes: " +
+ boost::trim_copy(solidity::disassemble(obj.bytecode->bytecode)) +
+ "\n";
+
+ if (m_expectation != m_obtainedResult)
+ {
+ string nextIndentLevel = _linePrefix + " ";
+ FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl;
+ printIndented(_stream, m_expectation, nextIndentLevel);
+ FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Obtained result:" << endl;
+ printIndented(_stream, m_obtainedResult, nextIndentLevel);
+ return false;
+ }
+ return true;
+}
+
+void ObjectCompilerTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const
+{
+ printIndented(_stream, m_source, _linePrefix);
+}
+
+void ObjectCompilerTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const
+{
+ printIndented(_stream, m_obtainedResult, _linePrefix);
+}
+
+void ObjectCompilerTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const
+{
+ stringstream output(_output);
+ string line;
+ while (getline(output, line))
+ if (line.empty())
+ // Avoid trailing spaces.
+ _stream << boost::trim_right_copy(_linePrefix) << endl;
+ else
+ _stream << _linePrefix << line << endl;
+}
+
+void ObjectCompilerTest::printErrors(ostream& _stream, ErrorList const& _errors)
+{
+ SourceReferenceFormatter formatter(_stream);
+
+ for (auto const& error: _errors)
+ formatter.printExceptionInformation(
+ *error,
+ (error->type() == Error::Type::Warning) ? "Warning" : "Error"
+ );
+}
diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h
new file mode 100644
index 00000000..a5f8d777
--- /dev/null
+++ b/test/libyul/ObjectCompilerTest.h
@@ -0,0 +1,69 @@
+/*
+ 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 <test/TestCase.h>
+
+namespace langutil
+{
+class Scanner;
+class Error;
+using ErrorList = std::vector<std::shared_ptr<Error const>>;
+}
+
+namespace yul
+{
+struct AsmAnalysisInfo;
+struct Block;
+}
+
+namespace yul
+{
+namespace test
+{
+
+class ObjectCompilerTest: public dev::solidity::test::TestCase
+{
+public:
+ static std::unique_ptr<TestCase> create(std::string const& _filename)
+ {
+ return std::unique_ptr<TestCase>(new ObjectCompilerTest(_filename));
+ }
+
+ explicit ObjectCompilerTest(std::string const& _filename);
+
+ bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override;
+
+ void printSource(std::ostream& _stream, std::string const &_linePrefix = "", bool const _formatted = false) const override;
+ void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override;
+
+private:
+ void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const;
+ bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted);
+ void disambiguate();
+
+ static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors);
+
+ std::string m_source;
+ bool m_optimize = false;
+ std::string m_expectation;
+ std::string m_obtainedResult;
+};
+
+}
+}
diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp
index caaf2719..df7e32a1 100644
--- a/test/libyul/Parser.cpp
+++ b/test/libyul/Parser.cpp
@@ -22,10 +22,12 @@
#include <test/Options.h>
#include <test/libsolidity/ErrorCheck.h>
+#include <test/libyul/Common.h>
#include <libyul/AsmParser.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
+#include <libyul/Dialect.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h>
@@ -47,12 +49,12 @@ namespace test
namespace
{
-bool parse(string const& _source, ErrorReporter& errorReporter)
+bool parse(string const& _source, std::shared_ptr<Dialect> _dialect, ErrorReporter& errorReporter)
{
try
{
auto scanner = make_shared<Scanner>(CharStream(_source, ""));
- auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Yul).parse(scanner, false);
+ auto parserResult = yul::Parser(errorReporter, _dialect).parse(scanner, false);
if (parserResult)
{
yul::AsmAnalysisInfo analysisInfo;
@@ -61,7 +63,7 @@ bool parse(string const& _source, ErrorReporter& errorReporter)
errorReporter,
dev::test::Options::get().evmVersion(),
boost::none,
- yul::AsmFlavour::Yul
+ _dialect
)).analyze(*parserResult);
}
}
@@ -72,13 +74,14 @@ bool parse(string const& _source, ErrorReporter& errorReporter)
return false;
}
-boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true)
+boost::optional<Error> parseAndReturnFirstError(string const& _source, shared_ptr<Dialect> _dialect, bool _allowWarnings = true)
{
ErrorList errors;
ErrorReporter errorReporter(errors);
- if (!parse(_source, errorReporter))
+ if (!parse(_source, _dialect, errorReporter))
{
- BOOST_REQUIRE_EQUAL(errors.size(), 1);
+ BOOST_REQUIRE(!errors.empty());
+ BOOST_CHECK_EQUAL(errors.size(), 1);
return *errors.front();
}
else
@@ -96,29 +99,31 @@ boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _all
return {};
}
-bool successParse(std::string const& _source, bool _allowWarnings = true)
+bool successParse(std::string const& _source, shared_ptr<Dialect> _dialect = Dialect::yul(), bool _allowWarnings = true)
{
- return !parseAndReturnFirstError(_source, _allowWarnings);
+ return !parseAndReturnFirstError(_source, _dialect, _allowWarnings);
}
-Error expectError(std::string const& _source, bool _allowWarnings = false)
+Error expectError(std::string const& _source, shared_ptr<Dialect> _dialect = Dialect::yul(), bool _allowWarnings = false)
{
- auto error = parseAndReturnFirstError(_source, _allowWarnings);
+ auto error = parseAndReturnFirstError(_source, _dialect, _allowWarnings);
BOOST_REQUIRE(error);
return *error;
}
}
-#define CHECK_ERROR(text, typ, substring) \
+#define CHECK_ERROR_DIALECT(text, typ, substring, dialect) \
do \
{ \
- Error err = expectError((text), false); \
+ Error err = expectError((text), dialect, false); \
BOOST_CHECK(err.type() == (Error::Type::typ)); \
BOOST_CHECK(dev::solidity::searchErrorMessage(err, (substring))); \
} while(0)
+#define CHECK_ERROR(text, typ, substring) CHECK_ERROR_DIALECT(text, typ, substring, Dialect::yul())
+
BOOST_AUTO_TEST_SUITE(YulParser)
BOOST_AUTO_TEST_CASE(smoke_test)
@@ -299,6 +304,42 @@ BOOST_AUTO_TEST_CASE(if_statement_invalid)
BOOST_CHECK(successParse("{ if 42:u256 { } }"));
}
+BOOST_AUTO_TEST_CASE(builtins_parser)
+{
+ struct SimpleDialect: public Dialect
+ {
+ SimpleDialect(): Dialect(AsmFlavour::Strict) {}
+ BuiltinFunction const* builtin(YulString _name) const override
+ {
+ return _name == "builtin"_yulstring ? &f : nullptr;
+ }
+ BuiltinFunction f;
+ };
+
+ shared_ptr<Dialect> dialect = make_shared<SimpleDialect>();
+ CHECK_ERROR_DIALECT("{ let builtin := 6 }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect);
+ CHECK_ERROR_DIALECT("{ function builtin() {} }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect);
+ CHECK_ERROR_DIALECT("{ builtin := 6 }", ParserError, "Cannot assign to builtin function \"builtin\".", dialect);
+}
+
+BOOST_AUTO_TEST_CASE(builtins_analysis)
+{
+ struct SimpleDialect: public Dialect
+ {
+ SimpleDialect(): Dialect(AsmFlavour::Strict) {}
+ BuiltinFunction const* builtin(YulString _name) const override
+ {
+ return _name == "builtin"_yulstring ? &f : nullptr;
+ }
+ BuiltinFunction f{"builtin"_yulstring, vector<Type>(2), vector<Type>(3), false};
+ };
+
+ shared_ptr<Dialect> dialect = make_shared<SimpleDialect>();
+ BOOST_CHECK(successParse("{ let a, b, c := builtin(1, 2) }", dialect));
+ CHECK_ERROR_DIALECT("{ let a, b, c := builtin(1) }", TypeError, "Function expects 2 arguments but got 1", dialect);
+ CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch: 2 variables and 3 values.", dialect);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libyul/StackReuseCodegen.cpp b/test/libyul/StackReuseCodegen.cpp
new file mode 100644
index 00000000..97be11d3
--- /dev/null
+++ b/test/libyul/StackReuseCodegen.cpp
@@ -0,0 +1,353 @@
+/*
+ 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/>.
+*/
+/**
+ * Unit tests for stack-reusing code generator.
+ */
+
+#include <test/Options.h>
+
+#include <libsolidity/interface/AssemblyStack.h>
+#include <libevmasm/Instruction.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace yul
+{
+namespace test
+{
+
+namespace
+{
+string assemble(string const& _input)
+{
+ solidity::AssemblyStack asmStack;
+ BOOST_REQUIRE_MESSAGE(asmStack.parseAndAnalyze("", _input), "Source did not parse: " + _input);
+ return solidity::disassemble(asmStack.assemble(solidity::AssemblyStack::Machine::EVM, true).bytecode->bytecode);
+}
+}
+
+BOOST_AUTO_TEST_SUITE(StackReuseCodegen)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ string out = assemble("{}");
+ BOOST_CHECK_EQUAL(out, "");
+}
+
+BOOST_AUTO_TEST_CASE(single_var)
+{
+ string out = assemble("{ let x }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x0 POP ");
+}
+
+BOOST_AUTO_TEST_CASE(single_var_assigned)
+{
+ string out = assemble("{ let x := 1 }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x1 POP ");
+}
+
+BOOST_AUTO_TEST_CASE(single_var_assigned_plus_code)
+{
+ string out = assemble("{ let x := 1 mstore(3, 4) }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x1 POP PUSH1 0x4 PUSH1 0x3 MSTORE ");
+}
+
+BOOST_AUTO_TEST_CASE(single_var_assigned_plus_code_and_reused)
+{
+ string out = assemble("{ let x := 1 mstore(3, 4) pop(mload(x)) }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x4 PUSH1 0x3 MSTORE DUP1 MLOAD POP POP ");
+}
+
+BOOST_AUTO_TEST_CASE(multi_reuse_single_slot)
+{
+ string out = assemble("{ let x := 1 x := 6 let y := 2 y := 4 }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x6 SWAP1 POP POP PUSH1 0x2 PUSH1 0x4 SWAP1 POP POP ");
+}
+
+BOOST_AUTO_TEST_CASE(multi_reuse_single_slot_nested)
+{
+ string out = assemble("{ let x := 1 x := 6 { let y := 2 y := 4 } }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x6 SWAP1 POP POP PUSH1 0x2 PUSH1 0x4 SWAP1 POP POP ");
+}
+
+BOOST_AUTO_TEST_CASE(multi_reuse_same_variable_name)
+{
+ string out = assemble("{ let z := mload(0) { let x := 1 x := 6 z := x } { let x := 2 z := x x := 4 } }");
+ BOOST_CHECK_EQUAL(out,
+ "PUSH1 0x0 MLOAD "
+ "PUSH1 0x1 PUSH1 0x6 SWAP1 POP DUP1 SWAP2 POP POP "
+ "PUSH1 0x2 DUP1 SWAP2 POP PUSH1 0x4 SWAP1 POP POP "
+ "POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(last_use_in_nested_block)
+{
+ string out = assemble("{ let z := 0 { pop(z) } let x := 1 }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x0 DUP1 POP POP PUSH1 0x1 POP ");
+}
+
+BOOST_AUTO_TEST_CASE(if_)
+{
+ // z is only removed after the if (after the jumpdest)
+ string out = assemble("{ let z := mload(0) if z { let x := z } let t := 3 }");
+ BOOST_CHECK_EQUAL(out, "PUSH1 0x0 MLOAD DUP1 ISZERO PUSH1 0xA JUMPI DUP1 POP JUMPDEST POP PUSH1 0x3 POP ");
+}
+
+BOOST_AUTO_TEST_CASE(switch_)
+{
+ string out = assemble("{ let z := 0 switch z case 0 { let x := 2 let y := 3 } default { z := 3 } let t := 9 }");
+ BOOST_CHECK_EQUAL(out,
+ "PUSH1 0x0 DUP1 "
+ "PUSH1 0x0 DUP2 EQ PUSH1 0x11 JUMPI "
+ "PUSH1 0x3 SWAP2 POP PUSH1 0x18 JUMP "
+ "JUMPDEST PUSH1 0x2 POP PUSH1 0x3 POP "
+ "JUMPDEST POP POP " // This is where z and its copy (switch condition) can be removed.
+ "PUSH1 0x9 POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(reuse_slots)
+{
+ // x and y should reuse the slots of b and d
+ string out = assemble("{ let a, b, c, d let x := 2 let y := 3 mstore(x, a) mstore(y, c) }");
+ BOOST_CHECK_EQUAL(out,
+ "PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 "
+ "POP " // d is removed right away
+ "PUSH1 0x2 SWAP2 POP " // x is stored at b's slot
+ "PUSH1 0x3 DUP4 DUP4 MSTORE "
+ "DUP2 DUP2 MSTORE "
+ "POP POP POP POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(for_1)
+{
+ // Special scoping rules, but can remove z early
+ string out = assemble("{ for { let z := 0 } 1 { } { let x := 3 } let t := 2 }");
+ BOOST_CHECK_EQUAL(out,
+ "PUSH1 0x0 POP "
+ "JUMPDEST PUSH1 0x1 ISZERO PUSH1 0x11 JUMPI "
+ "PUSH1 0x3 POP JUMPDEST PUSH1 0x3 JUMP "
+ "JUMPDEST PUSH1 0x2 POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(for_2)
+{
+ // Special scoping rules, cannot remove z until after the loop!
+ string out = assemble("{ for { let z := 0 } 1 { } { z := 8 let x := 3 } let t := 2 }");
+ BOOST_CHECK_EQUAL(out,
+ "PUSH1 0x0 "
+ "JUMPDEST PUSH1 0x1 ISZERO PUSH1 0x14 JUMPI "
+ "PUSH1 0x8 SWAP1 POP "
+ "PUSH1 0x3 POP "
+ "JUMPDEST PUSH1 0x2 JUMP "
+ "JUMPDEST POP " // z is removed
+ "PUSH1 0x2 POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_trivial)
+{
+ string in = R"({
+ function f() { }
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x5 JUMP JUMPDEST JUMP JUMPDEST "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_retparam)
+{
+ string in = R"({
+ function f() -> x, y { }
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0xB JUMP "
+ "JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 JUMP "
+ "JUMPDEST "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_params)
+{
+ string in = R"({
+ function f(a, b) { }
+ })";
+ BOOST_CHECK_EQUAL(assemble(in), "PUSH1 0x7 JUMP JUMPDEST POP POP JUMP JUMPDEST ");
+}
+
+BOOST_AUTO_TEST_CASE(function_params_and_retparams)
+{
+ string in = R"({
+ function f(a, b, c, d) -> x, y { }
+ })";
+ // This does not re-use the parameters for the return parameters
+ // We do not expect parameters to be fully unused, so the stack
+ // layout for a function is still fixed, even though parameters
+ // can be re-used.
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x10 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP5 POP SWAP5 SWAP3 POP POP POP JUMP JUMPDEST "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_params_and_retparams_partly_unused)
+{
+ string in = R"({
+ function f(a, b, c, d) -> x, y { b := 3 let s := 9 y := 2 mstore(s, y) }
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x1E JUMP "
+ "JUMPDEST PUSH1 0x0 PUSH1 0x0 "
+ "PUSH1 0x3 SWAP4 POP "
+ "PUSH1 0x9 PUSH1 0x2 SWAP2 POP "
+ "DUP2 DUP2 MSTORE "
+ "POP SWAP5 POP SWAP5 SWAP3 POP POP POP JUMP "
+ "JUMPDEST "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_with_body_embedded)
+{
+ string in = R"({
+ let b := 3
+ function f(a, r) -> t {
+ // r could be removed right away, but a cannot - this is not implemented, though
+ let x := a a := 3 t := a
+ }
+ b := 7
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x3 PUSH1 "
+ "0x16 JUMP "
+ "JUMPDEST PUSH1 0x0 " // start of f, initialize t
+ "DUP2 POP " // let x := a
+ "PUSH1 0x3 SWAP2 POP "
+ "DUP2 SWAP1 POP "
+ "SWAP3 SWAP2 POP POP JUMP "
+ "JUMPDEST PUSH1 0x7 SWAP1 "
+ "POP POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(function_call)
+{
+ string in = R"({
+ let b := f(1, 2)
+ function f(a, r) -> t { }
+ b := f(3, 4)
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x9 PUSH1 0x2 PUSH1 0x1 PUSH1 0xD JUMP "
+ "JUMPDEST PUSH1 0x15 JUMP " // jump over f
+ "JUMPDEST PUSH1 0x0 SWAP3 SWAP2 POP POP JUMP " // f
+ "JUMPDEST PUSH1 0x1F PUSH1 0x4 PUSH1 0x3 PUSH1 0xD JUMP "
+ "JUMPDEST SWAP1 POP POP "
+ );
+}
+
+
+BOOST_AUTO_TEST_CASE(functions_multi_return)
+{
+ string in = R"({
+ function f(a, b) -> t { }
+ function g() -> r, s { }
+ let x := f(1, 2)
+ x := f(3, 4)
+ let y, z := g()
+ y, z := g()
+ let unused := 7
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0xB JUMP "
+ "JUMPDEST PUSH1 0x0 SWAP3 SWAP2 POP POP JUMP " // f
+ "JUMPDEST PUSH1 0x17 JUMP "
+ "JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 JUMP " // g
+ "JUMPDEST PUSH1 0x21 PUSH1 0x2 PUSH1 0x1 PUSH1 0x3 JUMP " // f(1, 2)
+ "JUMPDEST PUSH1 0x2B PUSH1 0x4 PUSH1 0x3 PUSH1 0x3 JUMP " // f(3, 4)
+ "JUMPDEST SWAP1 POP " // assignment to x
+ "POP " // remove x
+ "PUSH1 0x34 PUSH1 0xF JUMP " // g()
+ "JUMPDEST PUSH1 0x3A PUSH1 0xF JUMP " // g()
+ "JUMPDEST SWAP2 POP SWAP2 POP " // assignments
+ "POP POP " // removal of y and z
+ "PUSH1 0x7 POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(reuse_slots_function)
+{
+ string in = R"({
+ function f() -> x, y, z, t {}
+ let a, b, c, d := f() let x1 := 2 let y1 := 3 mstore(x1, a) mstore(y1, c)
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x11 JUMP "
+ "JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 SWAP3 SWAP4 JUMP "
+ "JUMPDEST PUSH1 0x17 PUSH1 0x3 JUMP "
+ // Stack: a b c d
+ "JUMPDEST POP " // d is unused
+ // Stack: a b c
+ "PUSH1 0x2 SWAP2 POP " // x1 reuses b's slot
+ "PUSH1 0x3 "
+ // Stack: a x1 c y1
+ "DUP4 DUP4 MSTORE "
+ "DUP2 DUP2 MSTORE "
+ "POP POP POP POP "
+ );
+}
+
+BOOST_AUTO_TEST_CASE(reuse_slots_function_with_gaps)
+{
+ string in = R"({
+ // Only x3 is actually used, the slots of
+ // x1 and x2 will be reused right away.
+ let x1 := 5 let x2 := 6 let x3 := 7
+ mstore(x1, x2)
+ function f() -> x, y, z, t {}
+ let a, b, c, d := f() mstore(x3, a) mstore(c, d)
+ })";
+ BOOST_CHECK_EQUAL(assemble(in),
+ "PUSH1 0x5 PUSH1 0x6 PUSH1 0x7 "
+ "DUP2 DUP4 MSTORE "
+ "PUSH1 0x1A JUMP " // jump across function
+ "JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 SWAP3 SWAP4 JUMP "
+ "JUMPDEST PUSH1 0x20 PUSH1 0xC JUMP "
+ // stack: x1 x2 x3 a b c d
+ "JUMPDEST SWAP6 POP " // move d into x1
+ // stack: d x2 x3 a b c
+ "SWAP4 POP "
+ // stack: d c x3 a b
+ "POP "
+ // stack: d c x3 a
+ "DUP1 DUP3 MSTORE "
+ "POP POP "
+ // stack: d c
+ "DUP2 DUP2 MSTORE "
+ "POP POP "
+ );
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+}
diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp
index 15d70faa..9643a1e9 100644
--- a/test/libyul/YulOptimizerTest.cpp
+++ b/test/libyul/YulOptimizerTest.cpp
@@ -22,7 +22,7 @@
#include <test/Options.h>
#include <libyul/optimiser/BlockFlattener.h>
-#include <libyul/optimiser/VarDeclPropagator.h>
+#include <libyul/optimiser/VarDeclInitializer.h>
#include <libyul/optimiser/Disambiguator.h>
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
#include <libyul/optimiser/NameCollector.h>
@@ -39,7 +39,9 @@
#include <libyul/optimiser/ExpressionJoiner.h>
#include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/RedundantAssignEliminator.h>
+#include <libyul/optimiser/StructuralSimplifier.h>
#include <libyul/optimiser/Suite.h>
+#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmPrinter.h>
#include <libyul/AsmParser.h>
#include <libyul/AsmAnalysis.h>
@@ -105,11 +107,8 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
disambiguate();
BlockFlattener{}(*m_ast);
}
- else if (m_optimizerStep == "varDeclPropagator")
- {
- disambiguate();
- VarDeclPropagator{}(*m_ast);
- }
+ else if (m_optimizerStep == "varDeclInitializer")
+ VarDeclInitializer{}(*m_ast);
else if (m_optimizerStep == "forLoopInitRewriter")
{
disambiguate();
@@ -213,6 +212,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
SSATransform::run(*m_ast, nameDispenser);
RedundantAssignEliminator::run(*m_ast);
}
+ else if (m_optimizerStep == "structuralSimplifier")
+ {
+ disambiguate();
+ StructuralSimplifier{}(*m_ast);
+ }
else if (m_optimizerStep == "fullSuite")
OptimiserSuite::run(*m_ast, *m_analysisInfo);
else
@@ -256,15 +260,15 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st
bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
{
- yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict;
+ shared_ptr<yul::Dialect> dialect = m_yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM();
ErrorList errors;
ErrorReporter errorReporter(errors);
shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, ""));
- m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false);
+ m_ast = yul::Parser(errorReporter, dialect).parse(scanner, false);
if (!m_ast || !errorReporter.errors().empty())
{
FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
- printErrors(_stream, errorReporter.errors(), *scanner);
+ printErrors(_stream, errorReporter.errors());
return false;
}
m_analysisInfo = make_shared<yul::AsmAnalysisInfo>();
@@ -273,12 +277,12 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
errorReporter,
dev::test::Options::get().evmVersion(),
boost::none,
- flavour
+ dialect
);
if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty())
{
FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error analyzing source." << endl;
- printErrors(_stream, errorReporter.errors(), *scanner);
+ printErrors(_stream, errorReporter.errors());
return false;
}
return true;
@@ -290,9 +294,9 @@ void YulOptimizerTest::disambiguate()
m_analysisInfo.reset();
}
-void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors, Scanner const& _scanner)
+void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors)
{
- SourceReferenceFormatter formatter(_stream, [&](string const&) -> Scanner const& { return _scanner; });
+ SourceReferenceFormatter formatter(_stream);
for (auto const& error: _errors)
formatter.printExceptionInformation(
diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h
index 90026e24..5648e995 100644
--- a/test/libyul/YulOptimizerTest.h
+++ b/test/libyul/YulOptimizerTest.h
@@ -57,7 +57,7 @@ private:
bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted);
void disambiguate();
- static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors, langutil::Scanner const& _scanner);
+ static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors);
std::string m_source;
bool m_yul = false;
diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul
new file mode 100644
index 00000000..daa22d21
--- /dev/null
+++ b/test/libyul/objectCompiler/data.yul
@@ -0,0 +1,11 @@
+object "a" {
+ code {}
+ // Unreferenced data is not added to the assembled bytecode.
+ data "str" "Hello, World!"
+}
+// ----
+// Assembly:
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// Bytecode: fe
+// Opcodes: INVALID
diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul
new file mode 100644
index 00000000..2259e5dc
--- /dev/null
+++ b/test/libyul/objectCompiler/datacopy.yul
@@ -0,0 +1,48 @@
+object "a" {
+ code {
+ datacopy(0, dataoffset("sub"), datasize("sub"))
+ return(0, datasize("sub"))
+ }
+ object "sub" {
+ code {
+ sstore(0, dataoffset("sub"))
+ mstore(0, datasize("data1"))
+ }
+ data "data1" "Hello, World!"
+ }
+}
+// ----
+// Assembly:
+// /* "source":26:73 */
+// dataSize(sub_0)
+// dataOffset(sub_0)
+// /* "source":35:36 */
+// 0x00
+// /* "source":26:73 */
+// codecopy
+// /* "source":78:104 */
+// dataSize(sub_0)
+// /* "source":85:86 */
+// 0x00
+// /* "source":78:104 */
+// return
+// stop
+//
+// sub_0: assembly {
+// /* "source":143:171 */
+// 0x00
+// /* "source":150:151 */
+// 0x00
+// /* "source":143:171 */
+// sstore
+// /* "source":178:206 */
+// 0x0d
+// /* "source":185:186 */
+// 0x00
+// /* "source":178:206 */
+// mstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// }
+// Bytecode: 600b600d600039600b6000f3fe6000600055600d600052fe
+// Opcodes: PUSH1 0xB PUSH1 0xD PUSH1 0x0 CODECOPY PUSH1 0xB PUSH1 0x0 RETURN INVALID PUSH1 0x0 PUSH1 0x0 SSTORE PUSH1 0xD PUSH1 0x0 MSTORE INVALID
diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul
new file mode 100644
index 00000000..725267f2
--- /dev/null
+++ b/test/libyul/objectCompiler/dataoffset_code.yul
@@ -0,0 +1,29 @@
+object "a" {
+ code { sstore(0, dataoffset("sub")) }
+ object "sub" {
+ code { sstore(0, 8) }
+ data "data1" "Hello, World!"
+ }
+}
+// ----
+// Assembly:
+// /* "source":22:50 */
+// dataOffset(sub_0)
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:50 */
+// sstore
+// stop
+//
+// sub_0: assembly {
+// /* "source":91:92 */
+// 0x08
+// /* "source":88:89 */
+// 0x00
+// /* "source":81:93 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// }
+// Bytecode: 6006600055fe6008600055fe
+// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID PUSH1 0x8 PUSH1 0x0 SSTORE INVALID
diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul
new file mode 100644
index 00000000..9a0a461d
--- /dev/null
+++ b/test/libyul/objectCompiler/dataoffset_data.yul
@@ -0,0 +1,16 @@
+object "a" {
+ code { sstore(0, dataoffset("data1")) }
+ data "data1" "Hello, World!"
+}
+// ----
+// Assembly:
+// /* "source":22:52 */
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:52 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// Bytecode: 6006600055fe48656c6c6f2c20576f726c6421
+// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID 0x48 PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000
diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul
new file mode 100644
index 00000000..b7740735
--- /dev/null
+++ b/test/libyul/objectCompiler/dataoffset_self.yul
@@ -0,0 +1,16 @@
+object "a" {
+ code { sstore(0, dataoffset("a")) }
+ data "data1" "Hello, World!"
+}
+// ----
+// Assembly:
+// /* "source":22:48 */
+// 0x00
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:48 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// Bytecode: 6000600055fe
+// Opcodes: PUSH1 0x0 PUSH1 0x0 SSTORE INVALID
diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul
new file mode 100644
index 00000000..cff68515
--- /dev/null
+++ b/test/libyul/objectCompiler/datasize_code.yul
@@ -0,0 +1,29 @@
+object "a" {
+ code { sstore(0, datasize("sub")) }
+ object "sub" {
+ code { sstore(0, 8) }
+ data "data1" "Hello, World!"
+ }
+}
+// ----
+// Assembly:
+// /* "source":22:48 */
+// dataSize(sub_0)
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:48 */
+// sstore
+// stop
+//
+// sub_0: assembly {
+// /* "source":89:90 */
+// 0x08
+// /* "source":86:87 */
+// 0x00
+// /* "source":79:91 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// }
+// Bytecode: 6006600055fe
+// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID
diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul
new file mode 100644
index 00000000..f8341469
--- /dev/null
+++ b/test/libyul/objectCompiler/datasize_data.yul
@@ -0,0 +1,16 @@
+object "a" {
+ code { sstore(0, datasize("data1")) }
+ data "data1" "Hello, World!"
+}
+// ----
+// Assembly:
+// /* "source":22:50 */
+// 0x0d
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:50 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// Bytecode: 600d600055fe
+// Opcodes: PUSH1 0xD PUSH1 0x0 SSTORE INVALID
diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul
new file mode 100644
index 00000000..4579fe67
--- /dev/null
+++ b/test/libyul/objectCompiler/datasize_self.yul
@@ -0,0 +1,16 @@
+object "a" {
+ code { sstore(0, datasize("a")) }
+ data "data1" "Hello, World!"
+}
+// ----
+// Assembly:
+// /* "source":22:46 */
+// bytecodeSize
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:46 */
+// sstore
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+// Bytecode: 6006600055fe
+// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID
diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul
new file mode 100644
index 00000000..940160fd
--- /dev/null
+++ b/test/libyul/objectCompiler/namedObject.yul
@@ -0,0 +1,6 @@
+object "a" {
+ code {}
+}
+// ----
+// Assembly:
+// -- empty bytecode --
diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul
new file mode 100644
index 00000000..4fc6891c
--- /dev/null
+++ b/test/libyul/objectCompiler/namedObjectCode.yul
@@ -0,0 +1,13 @@
+object "a" {
+ code { sstore(0, 1) }
+}
+// ----
+// Assembly:
+// /* "source":32:33 */
+// 0x01
+// /* "source":29:30 */
+// 0x00
+// /* "source":22:34 */
+// sstore
+// Bytecode: 6001600055
+// Opcodes: PUSH1 0x1 PUSH1 0x0 SSTORE
diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul
new file mode 100644
index 00000000..7739ce61
--- /dev/null
+++ b/test/libyul/objectCompiler/nested_optimizer.yul
@@ -0,0 +1,49 @@
+// optimize
+object "a" {
+ code {
+ let x := calldataload(0)
+ let y := calldataload(0)
+ let z := sub(y, x)
+ sstore(add(x, 0), z)
+ }
+ object "sub" {
+ code {
+ let x := calldataload(0)
+ let y := calldataload(0)
+ let z := sub(y, x)
+ sstore(add(x, 0), z)
+ }
+ }
+}
+// ----
+// Assembly:
+// /* "source":60:61 */
+// 0x00
+// /* "source":137:138 */
+// dup1
+// /* "source":60:61 */
+// dup2
+// /* "source":47:62 */
+// calldataload
+// /* "source":119:139 */
+// sstore
+// /* "source":32:143 */
+// pop
+// stop
+//
+// sub_0: assembly {
+// /* "source":200:201 */
+// 0x00
+// /* "source":283:284 */
+// dup1
+// /* "source":200:201 */
+// dup2
+// /* "source":187:202 */
+// calldataload
+// /* "source":265:285 */
+// sstore
+// /* "source":170:291 */
+// pop
+// }
+// Bytecode: 60008081355550fe
+// Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP INVALID
diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul
new file mode 100644
index 00000000..d41b527c
--- /dev/null
+++ b/test/libyul/objectCompiler/simple.yul
@@ -0,0 +1,13 @@
+{
+ sstore(0, 1)
+}
+// ----
+// Assembly:
+// /* "source":14:15 */
+// 0x01
+// /* "source":11:12 */
+// 0x00
+// /* "source":4:16 */
+// sstore
+// Bytecode: 6001600055
+// Opcodes: PUSH1 0x1 PUSH1 0x0 SSTORE
diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul
new file mode 100644
index 00000000..43b33553
--- /dev/null
+++ b/test/libyul/objectCompiler/simple_optimizer.yul
@@ -0,0 +1,23 @@
+// optimize
+{
+ let x := calldataload(0)
+ let y := calldataload(0)
+ let z := sub(y, x)
+ sstore(add(x, 0), z)
+}
+// ----
+// Assembly:
+// /* "source":38:39 */
+// 0x00
+// /* "source":109:110 */
+// dup1
+// /* "source":38:39 */
+// dup2
+// /* "source":25:40 */
+// calldataload
+// /* "source":91:111 */
+// sstore
+// /* "source":12:113 */
+// pop
+// Bytecode: 60008081355550
+// Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP
diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul
new file mode 100644
index 00000000..b2e44d4d
--- /dev/null
+++ b/test/libyul/objectCompiler/smoke.yul
@@ -0,0 +1,5 @@
+{
+}
+// ----
+// Assembly:
+// -- empty bytecode --
diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul
new file mode 100644
index 00000000..98ea4d07
--- /dev/null
+++ b/test/libyul/objectCompiler/subObject.yul
@@ -0,0 +1,21 @@
+object "a" {
+ code {}
+ // Unreferenced data is not added to the assembled bytecode.
+ data "str" "Hello, World!"
+ object "sub" { code { sstore(0, 1) } }
+}
+// ----
+// Assembly:
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+//
+// sub_0: assembly {
+// /* "source":149:150 */
+// 0x01
+// /* "source":146:147 */
+// 0x00
+// /* "source":139:151 */
+// sstore
+// }
+// Bytecode: fe
+// Opcodes: INVALID
diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul
new file mode 100644
index 00000000..5e01f6dd
--- /dev/null
+++ b/test/libyul/objectCompiler/subSubObject.yul
@@ -0,0 +1,39 @@
+object "a" {
+ code {}
+ // Unreferenced data is not added to the assembled bytecode.
+ data "str" "Hello, World!"
+ object "sub" {
+ code { sstore(0, 1) }
+ object "subsub" {
+ code { sstore(2, 3) }
+ data "str" hex"123456"
+ }
+ }
+}
+// ----
+// Assembly:
+// stop
+// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
+//
+// sub_0: assembly {
+// /* "source":153:154 */
+// 0x01
+// /* "source":150:151 */
+// 0x00
+// /* "source":143:155 */
+// sstore
+// stop
+//
+// sub_0: assembly {
+// /* "source":203:204 */
+// 0x03
+// /* "source":200:201 */
+// 0x02
+// /* "source":193:205 */
+// sstore
+// stop
+// data_6adf031833174bbe4c85eafe59ddb54e6584648c2c962c6f94791ab49caa0ad4 123456
+// }
+// }
+// Bytecode: fe
+// Opcodes: INVALID
diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul
new file mode 100644
index 00000000..5283ef9a
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul
@@ -0,0 +1,23 @@
+{
+ function f() -> x {
+ // can re-use x
+ let y := 0
+ mstore(y, 7)
+ }
+ let a
+ // can re-use a
+ let b := 0
+ sstore(a, b)
+}
+// ----
+// commonSubexpressionEliminator
+// {
+// function f() -> x
+// {
+// let y := x
+// mstore(x, 7)
+// }
+// let a
+// let b := a
+// sstore(a, a)
+// }
diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul
new file mode 100644
index 00000000..a790ca65
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul
@@ -0,0 +1,14 @@
+{
+ // This does not replace b by a because there is no
+ // explicit assignment, even though both hold the same value.
+ let a
+ let b
+ mstore(sub(a, b), 7)
+}
+// ----
+// commonSubexpressionEliminator
+// {
+// let a
+// let b
+// mstore(sub(a, b), 7)
+// }
diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul
new file mode 100644
index 00000000..51f5df40
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul
@@ -0,0 +1,14 @@
+{
+ function f() -> x, z {}
+ let c, d := f()
+ let y := add(d, add(c, 7))
+}
+// ----
+// expressionSimplifier
+// {
+// function f() -> x, z
+// {
+// }
+// let c, d := f()
+// let y := add(add(d, c), 7)
+// }
diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul
new file mode 100644
index 00000000..46f9bc40
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul
@@ -0,0 +1,14 @@
+// return variables are assumed to be zero initially.
+{
+ function f() -> c, d {
+ let y := add(d, add(c, 7))
+ }
+}
+// ----
+// expressionSimplifier
+// {
+// function f() -> c, d
+// {
+// let y := 7
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul
new file mode 100644
index 00000000..f260db0b
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul
@@ -0,0 +1,11 @@
+// Unassigned variables are assumed to be zero.
+{
+ let c, d
+ let y := add(d, add(c, 7))
+}
+// ----
+// expressionSimplifier
+// {
+// let c, d
+// let y := 7
+// }
diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul
new file mode 100644
index 00000000..7b1430f3
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul
@@ -0,0 +1,13 @@
+// Unassigned variables are assumed to be zero.
+{
+ let c
+ let d
+ let y := add(d, add(c, 7))
+}
+// ----
+// expressionSimplifier
+// {
+// let c
+// let d
+// let y := 7
+// }
diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul
new file mode 100644
index 00000000..3f7aa089
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul
@@ -0,0 +1,48 @@
+{
+ let random := 42
+ for {
+ for { let a := 1} iszero(eq(a,10)) {} {
+ a := add(a, 1)
+ }
+ let b := 1
+ } iszero(eq(b, 10)) {
+ for { let c := 1 } iszero(eq(c,2)) { c := add(c, 1) } {
+ b := add(b, 1)
+ }
+ } {
+ mstore(b,b)
+ }
+}
+// ----
+// forLoopInitRewriter
+// {
+// let random := 42
+// let a := 1
+// for {
+// }
+// iszero(eq(a, 10))
+// {
+// }
+// {
+// a := add(a, 1)
+// }
+// let b := 1
+// for {
+// }
+// iszero(eq(b, 10))
+// {
+// let c := 1
+// for {
+// }
+// iszero(eq(c, 2))
+// {
+// c := add(c, 1)
+// }
+// {
+// b := add(b, 1)
+// }
+// }
+// {
+// mstore(b, b)
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul
index ee7f5bf5..b3f51593 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul
@@ -9,14 +9,14 @@
// {
// {
// let f_a := calldataload(0)
-// let f_b
-// let f_c
+// let f_b := 0
+// let f_c := 0
// f_b := sload(mload(f_a))
// f_c := 3
// let b3 := f_b
// let f_a_2 := f_c
-// let f_b_3
-// let f_c_4
+// let f_b_3 := 0
+// let f_c_4 := 0
// f_b_3 := sload(mload(f_a_2))
// f_c_4 := 3
// let b4 := f_b_3
diff --git a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul
index 00bb6577..9e6c4e76 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul
@@ -14,7 +14,7 @@
// {
// let _2 := mload(0)
// let f_a := mload(1)
-// let f_r
+// let f_r := 0
// f_a := mload(f_a)
// f_r := add(f_a, calldatasize())
// if gt(f_r, _2)
diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul
index 0972ac56..c00b1163 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul
@@ -2,8 +2,6 @@
function f(a) -> b {
let x := mload(a)
b := sload(x)
- let c := 3
- mstore(mul(a, b), mload(x))
let y := add(a, x)
sstore(y, 10)
}
@@ -13,6 +11,9 @@
let r := f(a)
// This should be inlined because it is a constant
let t := f(a2)
+ let a3
+ // This should be inlined because it is a constant as well (zero)
+ let s := f(a3)
}
// ----
// fullInliner
@@ -22,21 +23,25 @@
// let a2 := 2
// let r := f(a_1)
// let f_a := a2
-// let f_b
+// let f_b := 0
// let f_x := mload(f_a)
// f_b := sload(f_x)
-// let f_c := 3
-// mstore(mul(f_a, f_b), mload(f_x))
// let f_y := add(f_a, f_x)
// sstore(f_y, 10)
// let t := f_b
+// let a3
+// let f_a_3 := a3
+// let f_b_4 := 0
+// let f_x_5 := mload(f_a_3)
+// f_b_4 := sload(f_x_5)
+// let f_y_6 := add(f_a_3, f_x_5)
+// sstore(f_y_6, 10)
+// let s := f_b_4
// }
// function f(a) -> b
// {
// let x := mload(a)
// b := sload(x)
-// let c := 3
-// mstore(mul(a, b), mload(x))
// let y := add(a, x)
// sstore(y, 10)
// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul
index 3302a35c..72beb8b1 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul
@@ -15,7 +15,7 @@
// {
// {
// let f_a := mload(1)
-// let f_b
+// let f_b := 0
// let f_x := mload(f_a)
// f_b := sload(f_x)
// let f_c := 3
diff --git a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul
index 644e9126..869abbc9 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul
@@ -13,7 +13,7 @@
// {
// let verylongvariablename2_1 := 3
// let verylongfu_verylongvariablename := verylongvariablename2_1
-// let verylongfu_verylongvariablename2
+// let verylongfu_verylongvariablename2 := 0
// verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename)
// mstore(0, verylongfu_verylongvariablename2)
// mstore(1, verylongvariablename2_1)
diff --git a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul
index f3d0b286..0b46a3c6 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul
@@ -15,7 +15,7 @@
// let f_a := mload(2)
// let f_b := _6
// let f_c := _4
-// let f_x
+// let f_x := 0
// f_x := add(f_a, f_b)
// f_x := mul(f_x, f_c)
// let _10 := add(f_x, _2)
diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul
index 8bc6ec58..5d658e96 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul
@@ -9,11 +9,11 @@
// {
// let _1 := 7
// let f_a := 3
-// let f_x
+// let f_x := 0
// f_x := add(f_a, f_a)
// let g_b := f_x
// let g_c := _1
-// let g_y
+// let g_y := 0
// g_y := mul(mload(g_c), f(g_b))
// let y_1 := g_y
// }
@@ -24,7 +24,7 @@
// function g(b, c) -> y
// {
// let f_a_6 := b
-// let f_x_7
+// let f_x_7 := 0
// f_x_7 := add(f_a_6, f_a_6)
// y := mul(mload(c), f_x_7)
// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul
index 19ac945e..6e4acb97 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul
@@ -37,7 +37,7 @@
// function f(x)
// {
// mstore(0, x)
-// let h_t
+// let h_t := 0
// h_t := 2
// mstore(7, h_t)
// let g_x_1 := 10
diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul
index eebdec38..a4cbbef0 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul
@@ -11,8 +11,8 @@
// {
// {
// let f_a := mload(0)
-// let f_x
-// let f_y
+// let f_x := 0
+// let f_y := 0
// f_x := mul(f_a, f_a)
// f_y := add(f_a, f_x)
// let r := f_x
diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul
new file mode 100644
index 00000000..f59e2c11
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul
@@ -0,0 +1,44 @@
+{
+ function f(a) -> b {
+ let x := mload(a)
+ b := sload(x)
+ }
+ // This will stop inlining at some point because
+ // the function gets too big.
+ function g() -> x {
+ x := f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(2)))))))))))))))))))
+ }
+}
+// ----
+// fullInliner
+// {
+// function f(a) -> b
+// {
+// b := sload(mload(a))
+// }
+// function g() -> x_1
+// {
+// let f_a := 2
+// let f_b := 0
+// f_b := sload(mload(f_a))
+// let f_a_20 := f_b
+// let f_b_21 := 0
+// f_b_21 := sload(mload(f_a_20))
+// let f_a_23 := f_b_21
+// let f_b_24 := 0
+// f_b_24 := sload(mload(f_a_23))
+// let f_a_26 := f_b_24
+// let f_b_27 := 0
+// f_b_27 := sload(mload(f_a_26))
+// let f_a_29 := f_b_27
+// let f_b_30 := 0
+// f_b_30 := sload(mload(f_a_29))
+// let f_a_32 := f_b_30
+// let f_b_33 := 0
+// f_b_33 := sload(mload(f_a_32))
+// let f_a_35 := f_b_33
+// let f_b_36 := 0
+// 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))))))))))))
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul
new file mode 100644
index 00000000..f20b7221
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul
@@ -0,0 +1,41 @@
+{
+ function f(a) -> b {
+ let x := mload(a)
+ b := sload(x)
+ }
+ // This will stop inlining at some point because
+ // the global context gets too big.
+ let x := f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(2)))))))))))))))))))
+}
+// ----
+// fullInliner
+// {
+// {
+// let f_a := 2
+// let f_b := 0
+// f_b := sload(mload(f_a))
+// let f_a_20 := f_b
+// let f_b_21 := 0
+// f_b_21 := sload(mload(f_a_20))
+// let f_a_23 := f_b_21
+// let f_b_24 := 0
+// f_b_24 := sload(mload(f_a_23))
+// let f_a_26 := f_b_24
+// let f_b_27 := 0
+// f_b_27 := sload(mload(f_a_26))
+// let f_a_29 := f_b_27
+// let f_b_30 := 0
+// f_b_30 := sload(mload(f_a_29))
+// let f_a_32 := f_b_30
+// let f_b_33 := 0
+// f_b_33 := sload(mload(f_a_32))
+// let f_a_35 := f_b_33
+// let f_b_36 := 0
+// 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))))))))))))
+// }
+// function f(a) -> b
+// {
+// b := sload(mload(a))
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul
index 9644e6c1..96d806bd 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul
@@ -14,7 +14,7 @@
// {
// for {
// let f_a := 0
-// let f_r
+// let f_r := 0
// sstore(f_a, 0)
// f_r := f_a
// let x := f_r
@@ -22,14 +22,14 @@
// f(x)
// {
// let f_a_3 := x
-// let f_r_4
+// let f_r_4 := 0
// sstore(f_a_3, 0)
// f_r_4 := f_a_3
// x := f_r_4
// }
// {
// let f_a_6 := x
-// let f_r_7
+// let f_r_7 := 0
// sstore(f_a_6, 0)
// f_r_7 := f_a_6
// let t := f_r_7
diff --git a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul
index cd9e2746..c1bed208 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul
@@ -14,7 +14,7 @@
// {
// let _1 := 2
// let f_a := 7
-// let f_x
+// let f_x := 0
// let f_r := mul(f_a, f_a)
// f_x := add(f_r, f_r)
// pop(add(f_x, _1))
diff --git a/test/libyul/yulOptimizerTests/fullInliner/simple.yul b/test/libyul/yulOptimizerTests/fullInliner/simple.yul
index fcdf453b..1ada8f53 100644
--- a/test/libyul/yulOptimizerTests/fullInliner/simple.yul
+++ b/test/libyul/yulOptimizerTests/fullInliner/simple.yul
@@ -11,7 +11,7 @@
// {
// let _2 := mload(7)
// let f_a := sload(mload(2))
-// let f_x
+// let f_x := 0
// let f_r := mul(f_a, f_a)
// f_x := add(f_r, f_r)
// let y := add(f_x, _2)
diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul
index a34da198..efb846f2 100644
--- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul
+++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul
@@ -465,178 +465,166 @@
// let abi_encode_pos := _1
// let abi_encode_length_68 := mload(_485)
// mstore(_1, abi_encode_length_68)
-// let abi_encode_pos_590 := 64
-// abi_encode_pos := abi_encode_pos_590
+// abi_encode_pos := 64
// let abi_encode_srcPtr := add(_485, _1)
+// let abi_encode_i_69 := _2
// for {
-// let abi_encode_i_69 := _2
// }
// lt(abi_encode_i_69, abi_encode_length_68)
// {
// abi_encode_i_69 := add(abi_encode_i_69, 1)
// }
// {
-// let _931 := mload(abi_encode_srcPtr)
-// let abi_encode_pos_71_1037 := abi_encode_pos
-// let abi_encode_length_72_1038 := 0x3
-// let abi_encode_srcPtr_73_1039 := _931
+// let _863 := mload(abi_encode_srcPtr)
+// let abi_encode_pos_71_971 := abi_encode_pos
+// let abi_encode_length_72_972 := 0x3
+// let abi_encode_srcPtr_73_973 := _863
+// let abi_encode_i_74_974 := _2
// for {
-// let abi_encode_i_74_1040 := _2
// }
-// lt(abi_encode_i_74_1040, abi_encode_length_72_1038)
+// lt(abi_encode_i_74_974, abi_encode_length_72_972)
// {
-// abi_encode_i_74_1040 := add(abi_encode_i_74_1040, 1)
+// abi_encode_i_74_974 := add(abi_encode_i_74_974, 1)
// }
// {
-// mstore(abi_encode_pos_71_1037, and(mload(abi_encode_srcPtr_73_1039), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
-// abi_encode_srcPtr_73_1039 := add(abi_encode_srcPtr_73_1039, _1)
-// abi_encode_pos_71_1037 := add(abi_encode_pos_71_1037, _1)
+// mstore(abi_encode_pos_71_971, and(mload(abi_encode_srcPtr_73_973), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
+// abi_encode_srcPtr_73_973 := add(abi_encode_srcPtr_73_973, _1)
+// abi_encode_pos_71_971 := add(abi_encode_pos_71_971, _1)
// }
// abi_encode_srcPtr := add(abi_encode_srcPtr, _1)
// abi_encode_pos := add(abi_encode_pos, 0x60)
// }
-// let _933 := 0x40
-// let _487 := mload(_933)
-// let _488 := mload(_1)
-// let abi_decode_value0_60_618
-// let abi_decode_value0_60 := abi_decode_value0_60_618
-// let abi_decode_value1_61_619
-// let abi_decode_value1_61 := abi_decode_value1_61_619
-// let abi_decode_value2_620
-// let abi_decode_value2 := abi_decode_value2_620
-// let abi_decode_value3_621
-// let abi_decode_value3 := abi_decode_value3_621
-// if slt(sub(_487, _488), 128)
+// let a, b, c, d := abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(mload(_1), mload(0x40))
+// sstore(a, b)
+// sstore(c, d)
+// sstore(_2, abi_encode_pos)
+// }
+// function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset_3, end_4) -> array_5
+// {
+// if iszero(slt(add(offset_3, 0x1f), end_4))
// {
-// revert(_2, _2)
+// revert(array_5, array_5)
// }
+// let length_6 := calldataload(offset_3)
+// let array_5_254 := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_6))
+// array_5 := array_5_254
+// let dst_7 := array_5_254
+// mstore(array_5_254, length_6)
+// let _36 := 0x20
+// let offset_3_256 := add(offset_3, _36)
+// dst_7 := add(array_5_254, _36)
+// let src_8 := offset_3_256
+// let _38 := 0x40
+// if gt(add(add(offset_3, mul(length_6, _38)), _36), end_4)
// {
-// abi_decode_value0_60 := calldataload(_488)
+// let _42 := 0
+// revert(_42, _42)
+// }
+// let i_9 := 0
+// for {
// }
+// lt(i_9, length_6)
// {
-// abi_decode_value1_61 := calldataload(add(_488, 32))
+// i_9 := add(i_9, 1)
// }
// {
-// let abi_decode_offset_64 := calldataload(add(_488, abi_encode_pos_590))
-// let _940 := 0xffffffffffffffff
-// if gt(abi_decode_offset_64, _940)
-// {
-// revert(_2, _2)
-// }
-// let _942 := add(_488, abi_decode_offset_64)
-// if iszero(slt(add(_942, 0x1f), _487))
-// {
-// revert(_2, _2)
-// }
-// let abi_decode_length_30_1046 := calldataload(_942)
-// if gt(abi_decode_length_30_1046, _940)
-// {
-// revert(_2, _2)
-// }
-// let abi_decode_array_allo__561 := mul(abi_decode_length_30_1046, _1)
-// let abi_decode_array_29_279_1047 := allocateMemory(add(abi_decode_array_allo__561, _1))
-// let abi_decode_dst_31_1048 := abi_decode_array_29_279_1047
-// mstore(abi_decode_array_29_279_1047, abi_decode_length_30_1046)
-// let abi_decode_offset_27_281_1049 := add(_942, _1)
-// abi_decode_dst_31_1048 := add(abi_decode_array_29_279_1047, _1)
-// let abi_decode_src_32_1050 := abi_decode_offset_27_281_1049
-// if gt(add(add(_942, abi_decode_array_allo__561), _1), _487)
-// {
-// revert(_2, _2)
-// }
-// for {
-// let abi_decode_i_33_1052 := _2
-// }
-// lt(abi_decode_i_33_1052, abi_decode_length_30_1046)
-// {
-// abi_decode_i_33_1052 := add(abi_decode_i_33_1052, 1)
-// }
-// {
-// mstore(abi_decode_dst_31_1048, calldataload(abi_decode_src_32_1050))
-// abi_decode_dst_31_1048 := add(abi_decode_dst_31_1048, _1)
-// abi_decode_src_32_1050 := add(abi_decode_src_32_1050, _1)
-// }
-// abi_decode_value2 := abi_decode_array_29_279_1047
+// mstore(dst_7, abi_decode_t_array$_t_uint256_$2_memory(src_8, end_4))
+// dst_7 := add(dst_7, _36)
+// src_8 := add(src_8, _38)
// }
+// }
+// function abi_decode_t_array$_t_uint256_$2_memory(offset_11, end_12) -> array_13
+// {
+// if iszero(slt(add(offset_11, 0x1f), end_12))
// {
-// let abi_decode_offset_65 := calldataload(add(_488, 96))
-// let _945 := 0xffffffffffffffff
-// if gt(abi_decode_offset_65, _945)
-// {
-// revert(_2, _2)
-// }
-// let _947 := add(_488, abi_decode_offset_65)
-// let abi_decode__489_1056 := 0x1f
-// if iszero(slt(add(_947, abi_decode__489_1056), _487))
-// {
-// revert(_2, _2)
-// }
-// let abi_decode_length_6_1058 := calldataload(_947)
-// if gt(abi_decode_length_6_1058, _945)
-// {
-// revert(_2, _2)
-// }
-// let abi_decode_array_5_254_1061 := allocateMemory(add(mul(abi_decode_length_6_1058, _1), _1))
-// let abi_decode_dst_7_1062 := abi_decode_array_5_254_1061
-// mstore(abi_decode_array_5_254_1061, abi_decode_length_6_1058)
-// let abi_decode_offset_3_256_1063 := add(_947, _1)
-// abi_decode_dst_7_1062 := add(abi_decode_array_5_254_1061, _1)
-// let abi_decode_src_8_1064 := abi_decode_offset_3_256_1063
-// if gt(add(add(_947, mul(abi_decode_length_6_1058, _933)), _1), _487)
-// {
-// revert(_2, _2)
-// }
-// for {
-// let abi_decode_i_9_1068 := _2
-// }
-// lt(abi_decode_i_9_1068, abi_decode_length_6_1058)
+// revert(array_13, array_13)
+// }
+// let length_14 := 0x2
+// let array_allo__559 := 0x20
+// let array_allo_size_95_605 := 64
+// let array_13_263 := allocateMemory(array_allo_size_95_605)
+// array_13 := array_13_263
+// let dst_15 := array_13_263
+// let src_16 := offset_11
+// if gt(add(offset_11, array_allo_size_95_605), end_12)
+// {
+// let _59 := 0
+// revert(_59, _59)
+// }
+// let i_17 := 0
+// for {
+// }
+// lt(i_17, length_14)
+// {
+// i_17 := add(i_17, 1)
+// }
+// {
+// mstore(dst_15, calldataload(src_16))
+// dst_15 := add(dst_15, array_allo__559)
+// src_16 := add(src_16, array_allo__559)
+// }
+// }
+// function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset_27, end_28) -> array_29
+// {
+// if iszero(slt(add(offset_27, 0x1f), end_28))
+// {
+// revert(array_29, array_29)
+// }
+// let length_30 := calldataload(offset_27)
+// let array_29_279 := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_30))
+// array_29 := array_29_279
+// let dst_31 := array_29_279
+// mstore(array_29_279, length_30)
+// let _91 := 0x20
+// let offset_27_281 := add(offset_27, _91)
+// dst_31 := add(array_29_279, _91)
+// let src_32 := offset_27_281
+// if gt(add(add(offset_27, mul(length_30, _91)), _91), end_28)
+// {
+// let _97 := 0
+// revert(_97, _97)
+// }
+// let i_33 := 0
+// for {
+// }
+// lt(i_33, length_30)
+// {
+// i_33 := add(i_33, 1)
+// }
+// {
+// mstore(dst_31, calldataload(src_32))
+// dst_31 := add(dst_31, _91)
+// src_32 := add(src_32, _91)
+// }
+// }
+// function abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(headStart_58, dataEnd_59) -> value0_60, value1_61, value2, value3
+// {
+// if slt(sub(dataEnd_59, headStart_58), 128)
+// {
+// revert(value2, value2)
+// }
+// {
+// value0_60 := calldataload(add(headStart_58, value2))
+// }
+// {
+// value1_61 := calldataload(add(headStart_58, 32))
+// }
+// {
+// let offset_64 := calldataload(add(headStart_58, 64))
+// if gt(offset_64, 0xffffffffffffffff)
// {
-// abi_decode_i_9_1068 := add(abi_decode_i_9_1068, 1)
+// revert(value2, value2)
// }
+// value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(headStart_58, offset_64), dataEnd_59)
+// }
+// {
+// let offset_65 := calldataload(add(headStart_58, 96))
+// if gt(offset_65, 0xffffffffffffffff)
// {
-// if iszero(slt(add(abi_decode_src_8_1064, abi_decode__489_1056), _487))
-// {
-// revert(_2, _2)
-// }
-// let abi_decode_abi_decode_length_14_1069 := 0x2
-// if _2
-// {
-// revert(_2, _2)
-// }
-// let allocateMe_memPtr_315 := mload(abi_encode_pos_590)
-// let allocateMe_newFreePtr := add(allocateMe_memPtr_315, abi_encode_pos_590)
-// if or(gt(allocateMe_newFreePtr, _945), lt(allocateMe_newFreePtr, allocateMe_memPtr_315))
-// {
-// revert(_2, _2)
-// }
-// mstore(abi_encode_pos_590, allocateMe_newFreePtr)
-// let abi_decode_abi_decode_dst_15_1071 := allocateMe_memPtr_315
-// let abi_decode_abi_decode_src_16_1072 := abi_decode_src_8_1064
-// if gt(add(abi_decode_src_8_1064, abi_encode_pos_590), _487)
-// {
-// revert(_2, _2)
-// }
-// for {
-// let abi_decode_abi_decode_i_17_1073 := _2
-// }
-// lt(abi_decode_abi_decode_i_17_1073, abi_decode_abi_decode_length_14_1069)
-// {
-// abi_decode_abi_decode_i_17_1073 := add(abi_decode_abi_decode_i_17_1073, 1)
-// }
-// {
-// mstore(abi_decode_abi_decode_dst_15_1071, calldataload(abi_decode_abi_decode_src_16_1072))
-// abi_decode_abi_decode_dst_15_1071 := add(abi_decode_abi_decode_dst_15_1071, _1)
-// abi_decode_abi_decode_src_16_1072 := add(abi_decode_abi_decode_src_16_1072, _1)
-// }
-// mstore(abi_decode_dst_7_1062, allocateMe_memPtr_315)
-// abi_decode_dst_7_1062 := add(abi_decode_dst_7_1062, _1)
-// abi_decode_src_8_1064 := add(abi_decode_src_8_1064, _933)
+// revert(value3, value3)
// }
-// abi_decode_value3 := abi_decode_array_5_254_1061
+// value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart_58, offset_65), dataEnd_59)
// }
-// sstore(abi_decode_value0_60, abi_decode_value1_61)
-// sstore(abi_decode_value2, abi_decode_value3)
-// sstore(_2, abi_encode_pos)
// }
// function allocateMemory(size) -> memPtr
// {
@@ -651,4 +639,22 @@
// }
// mstore(_199, newFreePtr)
// }
+// function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_92) -> size_93
+// {
+// if gt(length_92, 0xffffffffffffffff)
+// {
+// revert(size_93, size_93)
+// }
+// let _217 := 0x20
+// size_93 := add(mul(length_92, _217), _217)
+// }
+// function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_98) -> size_99
+// {
+// if gt(length_98, 0xffffffffffffffff)
+// {
+// revert(size_99, size_99)
+// }
+// let _234 := 0x20
+// size_99 := add(mul(length_98, _234), _234)
+// }
// }
diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul
index deb02068..fbe243d4 100644
--- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul
+++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul
@@ -9,16 +9,23 @@
pop(allocate(0x20))
let x := allocate(0x40)
mstore(array_index_access(x, 3), 2)
+ if 0 {
+ mstore(0x40, 0x20)
+ }
+ if sub(2,1) {
+ for { switch mul(1,2) case 2 { mstore(0x40, 0x20) } } sub(1,1) {} { mstore(0x80, 0x40) }
+ }
}
// ----
// fullSuite
// {
// {
-// let _18 := 0x20
-// let allocate__7 := 0x40
-// 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)
+// let _1 := 0x20
+// let allocate__19 := 0x40
+// mstore(allocate__19, add(mload(allocate__19), _1))
+// let allocate_p_24_41 := mload(allocate__19)
+// mstore(allocate__19, add(allocate_p_24_41, allocate__19))
+// mstore(add(allocate_p_24_41, 96), 2)
+// mstore(allocate__19, _1)
// }
// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul
new file mode 100644
index 00000000..ee1975e7
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul
@@ -0,0 +1,7 @@
+{ let a := mload(0) if a {} }
+// ----
+// structuralSimplifier
+// {
+// let a := mload(0)
+// pop(a)
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul
new file mode 100644
index 00000000..5977297b
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul
@@ -0,0 +1,6 @@
+{ if mload(0) {} }
+// ----
+// structuralSimplifier
+// {
+// pop(mload(0))
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol b/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol
new file mode 100644
index 00000000..b881a0a3
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol
@@ -0,0 +1,10 @@
+{
+ for { let a := 42 } 0 { a := a } {
+ let b := a
+ }
+}
+// ----
+// structuralSimplifier
+// {
+// let a := 42
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul
new file mode 100644
index 00000000..0895b1bb
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul
@@ -0,0 +1,5 @@
+{ if 0 { mstore(0, 0) } }
+// ----
+// structuralSimplifier
+// {
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul
new file mode 100644
index 00000000..0ece5dbd
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul
@@ -0,0 +1,10 @@
+{
+ let x, y
+ if x { mstore(0, 0) }
+ if y { mstore(0, 0) }
+}
+// ----
+// structuralSimplifier
+// {
+// let x, y
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul
new file mode 100644
index 00000000..ca9cba06
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul
@@ -0,0 +1,6 @@
+{ if 1 { mstore(0, 0) } }
+// ----
+// structuralSimplifier
+// {
+// mstore(0, 0)
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul
new file mode 100644
index 00000000..a327a882
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul
@@ -0,0 +1,9 @@
+{
+ let x
+ if x { mstore(0, 0) }
+}
+// ----
+// structuralSimplifier
+// {
+// let x
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul
new file mode 100644
index 00000000..169a84d1
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul
@@ -0,0 +1,6 @@
+{ if 1 { if 1 { for { mstore(0, 0) } 0 {} { mstore(2, 3) } if 0 { mstore(1, 2) } } } }
+// ----
+// structuralSimplifier
+// {
+// mstore(0, 0)
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul
new file mode 100644
index 00000000..7ca815a7
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul
@@ -0,0 +1,11 @@
+{
+ switch mload(0) default { mstore(1, 2) }
+}
+// ----
+// structuralSimplifier
+// {
+// pop(mload(0))
+// {
+// mstore(1, 2)
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul
new file mode 100644
index 00000000..a741ac2f
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul
@@ -0,0 +1,11 @@
+{
+ switch 1 case 2 { mstore(0, 0) }
+}
+// ----
+// structuralSimplifier
+// {
+// if eq(2, 1)
+// {
+// mstore(0, 0)
+// }
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul
new file mode 100644
index 00000000..5e2d60c2
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul
@@ -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()
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul
new file mode 100644
index 00000000..16428d7e
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul
@@ -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
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul
new file mode 100644
index 00000000..02d731af
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul
@@ -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
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul
new file mode 100644
index 00000000..2e14fe70
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul
@@ -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
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul
new file mode 100644
index 00000000..2a9bbe42
--- /dev/null
+++ b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul
@@ -0,0 +1,8 @@
+{
+ let a
+}
+// ----
+// varDeclInitializer
+// {
+// let a := 0
+// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul
deleted file mode 100644
index 54fea2fb..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- let a := 4
- let x
- if a {
- x := 2
- }
-}
-// ----
-// varDeclPropagator
-// {
-// let a := 4
-// let x
-// if a
-// {
-// x := 2
-// }
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul
deleted file mode 100644
index ed8d33b4..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul
+++ /dev/null
@@ -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()
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul
deleted file mode 100644
index ca921500..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- let a
- a := 4
- a := 5
-}
-// ----
-// varDeclPropagator
-// {
-// let a := 4
-// a := 5
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul
deleted file mode 100644
index 3affcac6..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- let a, b
- a := mload(0)
-}
-// ----
-// varDeclPropagator
-// {
-// let b
-// let a := mload(0)
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul
deleted file mode 100644
index d8959040..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- let f
- f := mload(0)
-}
-// ----
-// varDeclPropagator
-// {
-// let f := mload(0)
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul
deleted file mode 100644
index e8c91e10..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- let a, b
- a := mload(0)
- b := mload(1)
-}
-// ----
-// varDeclPropagator
-// {
-// let a := mload(0)
-// let b := mload(1)
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul
deleted file mode 100644
index 5312112a..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- let b
- let a := b
- b := 1
-}
-// ----
-// varDeclPropagator
-// {
-// let b
-// let a := b
-// b := 1
-// }
diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul
deleted file mode 100644
index e27785dd..00000000
--- a/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- function f(x) {}
- let a
- f(a)
- a := 4
-}
-// ----
-// varDeclPropagator
-// {
-// function f(x)
-// {
-// }
-// let a
-// f(a)
-// a := 4
-// }