diff options
Diffstat (limited to 'test/libyul')
193 files changed, 4996 insertions, 0 deletions
diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp new file mode 100644 index 00000000..d224bdcd --- /dev/null +++ b/test/libyul/Common.cpp @@ -0,0 +1,95 @@ +/* + 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/>. +*/ +/** + * @date 2017 + * Common functions the Yul tests. + */ + +#include <test/libyul/Common.h> + +#include <test/Options.h> + +#include <libyul/optimiser/Disambiguator.h> + +#include <libsolidity/parsing/Scanner.h> + +#include <libsolidity/inlineasm/AsmParser.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmPrinter.h> + +#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <libsolidity/interface/ErrorReporter.h> + +#include <boost/test/unit_test.hpp> + +using namespace std; +using namespace dev::yul; +using namespace dev::solidity; + +void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) +{ + SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; }); + + for (auto const& error: _errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); +} + + +pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::parse(string const& _source, bool _yul) +{ + auto flavour = _yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + ErrorList errors; + ErrorReporter errorReporter(errors); + auto scanner = make_shared<Scanner>(CharStream(_source), ""); + auto parserResult = assembly::Parser(errorReporter, flavour).parse(scanner, false); + if (parserResult) + { + BOOST_REQUIRE(errorReporter.errors().empty()); + auto analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); + assembly::AsmAnalyzer analyzer( + *analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + boost::none, + flavour + ); + if (analyzer.analyze(*parserResult)) + { + BOOST_REQUIRE(errorReporter.errors().empty()); + return make_pair(parserResult, analysisInfo); + } + } + printErrors(errors, *scanner); + BOOST_FAIL("Invalid source."); + + // Unreachable. + return {}; +} + +assembly::Block dev::yul::test::disambiguate(string const& _source, bool _yul) +{ + auto result = parse(_source, _yul); + return boost::get<Block>(Disambiguator(*result.second, {})(*result.first)); +} + +string dev::yul::test::format(string const& _source, bool _yul) +{ + return assembly::AsmPrinter(_yul)(*parse(_source, _yul).first); +} diff --git a/test/libyul/Common.h b/test/libyul/Common.h new file mode 100644 index 00000000..ee191494 --- /dev/null +++ b/test/libyul/Common.h @@ -0,0 +1,55 @@ +/* + 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/>. +*/ +/** + * @date 2017 + * Common functions the Yul tests. + */ + +#pragma once + +#include <libsolidity/inlineasm/AsmData.h> + +#include <string> +#include <vector> +#include <memory> + +namespace dev +{ +namespace solidity +{ +class Scanner; +class Error; +using ErrorList = std::vector<std::shared_ptr<Error const>>; +namespace assembly +{ +struct AsmAnalysisInfo; +} +} +namespace yul +{ +namespace test +{ + +void printErrors(solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); +std::pair<std::shared_ptr<solidity::assembly::Block>, std::shared_ptr<solidity::assembly::AsmAnalysisInfo>> +parse(std::string const& _source, bool _yul = true); +solidity::assembly::Block disambiguate(std::string const& _source, bool _yul = true); +std::string format(std::string const& _source, bool _yul = true); + +} +} +} diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp new file mode 100644 index 00000000..66810298 --- /dev/null +++ b/test/libyul/Inliner.cpp @@ -0,0 +1,111 @@ +/* + 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/>. +*/ +/** + * @date 2017 + * Unit tests for the Yul function inliner. + */ + +#include <test/libyul/Common.h> + +#include <libyul/optimiser/ExpressionInliner.h> +#include <libyul/optimiser/InlinableExpressionFunctionFinder.h> +#include <libyul/optimiser/FullInliner.h> +#include <libyul/optimiser/FunctionHoister.h> +#include <libyul/optimiser/FunctionGrouper.h> + +#include <libsolidity/inlineasm/AsmPrinter.h> + +#include <boost/test/unit_test.hpp> + +#include <boost/range/adaptors.hpp> +#include <boost/algorithm/string/join.hpp> + +using namespace std; +using namespace dev; +using namespace dev::yul; +using namespace dev::yul::test; +using namespace dev::solidity; + +namespace +{ +string inlinableFunctions(string const& _source) +{ + auto ast = disambiguate(_source); + + InlinableExpressionFunctionFinder funFinder; + funFinder(ast); + + vector<string> functionNames; + for (auto const& f: funFinder.inlinableFunctions()) + functionNames.emplace_back(f.first.str()); + return boost::algorithm::join(functionNames, ","); +} + +} + + +BOOST_AUTO_TEST_SUITE(YulInlinableFunctionFilter) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ }"), ""); +} + +BOOST_AUTO_TEST_CASE(simple) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 } }"), "f"); + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "function g(a:u256) -> b:u256 { b := a }" + "function f() -> x:u256 { x := g(2:u256) }" + "}"), "g,f"); +} + +BOOST_AUTO_TEST_CASE(simple_inside_structures) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "switch 2:u256 " + "case 2:u256 {" + "function g(a:u256) -> b:u256 { b := a }" + "function f() -> x:u256 { x := g(2:u256) }" + "}" + "}"), "g,f"); + BOOST_CHECK_EQUAL(inlinableFunctions("{" + "for {" + "function g(a:u256) -> b:u256 { b := a }" + "} 1:u256 {" + "function f() -> x:u256 { x := g(2:u256) }" + "}" + "{" + "function h() -> y:u256 { y := 2:u256 }" + "}" + "}"), "h,g,f"); +} + +BOOST_AUTO_TEST_CASE(negative) +{ + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := 2:u256 {} } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := f() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256 { x := x } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f() -> x:u256, y:u256 { x := 2:u256 } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions( + "{ function g() -> x:u256, y:u256 {} function f(y:u256) -> x:u256 { x,y := g() } }"), ""); + BOOST_CHECK_EQUAL(inlinableFunctions("{ function f(y:u256) -> x:u256 { y := 2:u256 } }"), ""); +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp new file mode 100644 index 00000000..3f329d28 --- /dev/null +++ b/test/libyul/Parser.cpp @@ -0,0 +1,306 @@ +/* + 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/>. +*/ +/** + * @date 2017 + * Unit tests for parsing Yul. + */ + +#include <test/Options.h> + +#include <test/libsolidity/ErrorCheck.h> + +#include <libsolidity/inlineasm/AsmParser.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/inlineasm/AsmAnalysisInfo.h> +#include <libsolidity/parsing/Scanner.h> +#include <libsolidity/interface/ErrorReporter.h> + +#include <boost/optional.hpp> +#include <boost/algorithm/string/replace.hpp> + +#include <string> +#include <memory> + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +namespace +{ + +bool parse(string const& _source, ErrorReporter& errorReporter) +{ + try + { + auto scanner = make_shared<Scanner>(CharStream(_source)); + auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Yul).parse(scanner, false); + if (parserResult) + { + assembly::AsmAnalysisInfo analysisInfo; + return (assembly::AsmAnalyzer( + analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + boost::none, + assembly::AsmFlavour::Yul + )).analyze(*parserResult); + } + } + catch (FatalError const&) + { + BOOST_FAIL("Fatal error leaked."); + } + return false; +} + +boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true) +{ + ErrorList errors; + ErrorReporter errorReporter(errors); + if (!parse(_source, errorReporter)) + { + BOOST_REQUIRE_EQUAL(errors.size(), 1); + return *errors.front(); + } + else + { + // If success is true, there might still be an error in the assembly stage. + if (_allowWarnings && Error::containsOnlyWarnings(errors)) + return {}; + else if (!errors.empty()) + { + if (!_allowWarnings) + BOOST_CHECK_EQUAL(errors.size(), 1); + return *errors.front(); + } + } + return {}; +} + +bool successParse(std::string const& _source, bool _allowWarnings = true) +{ + return !parseAndReturnFirstError(_source, _allowWarnings); +} + +Error expectError(std::string const& _source, bool _allowWarnings = false) +{ + + auto error = parseAndReturnFirstError(_source, _allowWarnings); + BOOST_REQUIRE(error); + return *error; +} + +} + +#define CHECK_ERROR(text, typ, substring) \ +do \ +{ \ + Error err = expectError((text), false); \ + BOOST_CHECK(err.type() == (Error::Type::typ)); \ + BOOST_CHECK(searchErrorMessage(err, (substring))); \ +} while(0) + +BOOST_AUTO_TEST_SUITE(YulParser) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + BOOST_CHECK(successParse("{ }")); +} + +BOOST_AUTO_TEST_CASE(vardecl) +{ + BOOST_CHECK(successParse("{ let x:u256 := 7:u256 }")); +} + +BOOST_AUTO_TEST_CASE(vardecl_bool) +{ + BOOST_CHECK(successParse("{ let x:bool := true:bool }")); + BOOST_CHECK(successParse("{ let x:bool := false:bool }")); +} + +BOOST_AUTO_TEST_CASE(vardecl_empty) +{ + BOOST_CHECK(successParse("{ let x:u256 }")); +} + +BOOST_AUTO_TEST_CASE(assignment) +{ + BOOST_CHECK(successParse("{ let x:u256 := 2:u256 let y:u256 := x }")); +} + +BOOST_AUTO_TEST_CASE(vardecl_complex) +{ + BOOST_CHECK(successParse("{ function add(a:u256, b:u256) -> c:u256 {} let y:u256 := 2:u256 let x:u256 := add(7:u256, add(6:u256, y)) }")); +} + +BOOST_AUTO_TEST_CASE(blocks) +{ + BOOST_CHECK(successParse("{ let x:u256 := 7:u256 { let y:u256 := 3:u256 } { let z:u256 := 2:u256 } }")); +} + +BOOST_AUTO_TEST_CASE(function_definitions) +{ + BOOST_CHECK(successParse("{ function f() { } function g(a:u256) -> x:u256 { } }")); +} + +BOOST_AUTO_TEST_CASE(function_definitions_multiple_args) +{ + BOOST_CHECK(successParse("{ function f(a:u256, d:u256) { } function g(a:u256, d:u256) -> x:u256, y:u256 { } }")); +} + +BOOST_AUTO_TEST_CASE(function_calls) +{ + BOOST_CHECK(successParse("{ function f(a:u256) -> b:u256 {} function g(a:u256, b:u256, c:u256) {} function x() { g(1:u256, 2:u256, f(3:u256)) x() } }")); +} + +BOOST_AUTO_TEST_CASE(tuple_assignment) +{ + BOOST_CHECK(successParse("{ function f() -> a:u256, b:u256, c:u256 {} let x:u256, y:u256, z:u256 := f() }")); +} + +BOOST_AUTO_TEST_CASE(label) +{ + CHECK_ERROR("{ label: }", ParserError, "Labels are not supported."); +} + +BOOST_AUTO_TEST_CASE(instructions) +{ + CHECK_ERROR("{ pop }", ParserError, "Call or assignment expected."); +} + +BOOST_AUTO_TEST_CASE(push) +{ + CHECK_ERROR("{ 0x42:u256 }", ParserError, "Call or assignment expected."); +} + +BOOST_AUTO_TEST_CASE(assign_from_stack) +{ + CHECK_ERROR("{ =: x:u256 }", ParserError, "Literal or identifier expected."); +} + +BOOST_AUTO_TEST_CASE(empty_call) +{ + CHECK_ERROR("{ () }", ParserError, "Literal or identifier expected."); +} + +BOOST_AUTO_TEST_CASE(tokens_as_identifers) +{ + BOOST_CHECK(successParse("{ let return:u256 := 1:u256 }")); + BOOST_CHECK(successParse("{ let byte:u256 := 1:u256 }")); + BOOST_CHECK(successParse("{ let address:u256 := 1:u256 }")); + BOOST_CHECK(successParse("{ let bool:u256 := 1:u256 }")); +} + +BOOST_AUTO_TEST_CASE(lacking_types) +{ + CHECK_ERROR("{ let x := 1:u256 }", ParserError, "Expected identifier but got '='"); + CHECK_ERROR("{ let x:u256 := 1 }", ParserError, "Expected ':' but got '}'"); + CHECK_ERROR("{ function f(a) {} }", ParserError, "Expected ':' but got ')'"); + CHECK_ERROR("{ function f(a:u256) -> b {} }", ParserError, "Expected ':' but got '{'"); +} + +BOOST_AUTO_TEST_CASE(invalid_types) +{ + /// testing invalid literal + /// NOTE: these will need to change when types are compared + CHECK_ERROR("{ let x:bool := 1:invalid }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported)."); + /// testing invalid variable declaration + CHECK_ERROR("{ let x:invalid := 1:bool }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported)."); + CHECK_ERROR("{ function f(a:invalid) {} }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported)."); +} + +BOOST_AUTO_TEST_CASE(number_literals) +{ + BOOST_CHECK(successParse("{ let x:u256 := 1:u256 }")); + CHECK_ERROR("{ let x:u256 := .1:u256 }", ParserError, "Invalid number literal."); + CHECK_ERROR("{ let x:u256 := 1e5:u256 }", ParserError, "Invalid number literal."); + CHECK_ERROR("{ let x:u256 := 67.235:u256 }", ParserError, "Invalid number literal."); + CHECK_ERROR("{ let x:u256 := 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:u256 }", TypeError, "Number literal too large (> 256 bits)"); +} + +BOOST_AUTO_TEST_CASE(builtin_types) +{ + BOOST_CHECK(successParse("{ let x:bool := true:bool }")); + BOOST_CHECK(successParse("{ let x:u8 := 1:u8 }")); + BOOST_CHECK(successParse("{ let x:s8 := 1:u8 }")); + BOOST_CHECK(successParse("{ let x:u32 := 1:u32 }")); + BOOST_CHECK(successParse("{ let x:s32 := 1:s32 }")); + BOOST_CHECK(successParse("{ let x:u64 := 1:u64 }")); + BOOST_CHECK(successParse("{ let x:s64 := 1:s64 }")); + BOOST_CHECK(successParse("{ let x:u128 := 1:u128 }")); + BOOST_CHECK(successParse("{ let x:s128 := 1:s128 }")); + BOOST_CHECK(successParse("{ let x:u256 := 1:u256 }")); + BOOST_CHECK(successParse("{ let x:s256 := 1:s256 }")); +} + +BOOST_AUTO_TEST_CASE(recursion_depth) +{ + string input; + for (size_t i = 0; i < 20000; i++) + input += "{"; + input += "let x:u256 := 0:u256"; + for (size_t i = 0; i < 20000; i++) + input += "}"; + + CHECK_ERROR(input, ParserError, "recursion"); +} + +BOOST_AUTO_TEST_CASE(multiple_assignment) +{ + CHECK_ERROR("{ let x:u256 function f() -> a:u256, b:u256 {} 123:u256, x := f() }", ParserError, "Label name / variable name must precede \",\" (multiple assignment)."); + CHECK_ERROR("{ let x:u256 function f() -> a:u256, b:u256 {} x, 123:u256 := f() }", ParserError, "Variable name expected in multiple assignment."); + + /// NOTE: Travis hiccups if not having a variable + char const* text = R"( + { + function f(a:u256) -> r1:u256, r2:u256 { + r1 := a + r2 := 7:u256 + } + let x:u256 := 9:u256 + let y:u256 := 2:u256 + x, y := f(x) + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(if_statement) +{ + BOOST_CHECK(successParse("{ if true:bool {} }")); + BOOST_CHECK(successParse("{ if false:bool { let x:u256 := 3:u256 } }")); + BOOST_CHECK(successParse("{ function f() -> x:bool {} if f() { let b:bool := f() } }")); +} + +BOOST_AUTO_TEST_CASE(if_statement_invalid) +{ + CHECK_ERROR("{ if let x:u256 {} }", ParserError, "Literal or identifier expected."); + CHECK_ERROR("{ if true:bool let x:u256 := 3:u256 }", ParserError, "Expected '{' but got reserved keyword 'let'"); + // TODO change this to an error once we check types. + BOOST_CHECK(successParse("{ if 42:u256 { } }")); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp new file mode 100644 index 00000000..03cd6446 --- /dev/null +++ b/test/libyul/YulOptimizerTest.cpp @@ -0,0 +1,295 @@ +/* + 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/YulOptimizerTest.h> + +#include <test/libsolidity/FormattedScope.h> + +#include <test/Options.h> + +#include <libyul/optimiser/BlockFlattener.h> +#include <libyul/optimiser/VarDeclPropagator.h> +#include <libyul/optimiser/Disambiguator.h> +#include <libyul/optimiser/CommonSubexpressionEliminator.h> +#include <libyul/optimiser/NameCollector.h> +#include <libyul/optimiser/ExpressionSplitter.h> +#include <libyul/optimiser/FunctionGrouper.h> +#include <libyul/optimiser/FunctionHoister.h> +#include <libyul/optimiser/ExpressionInliner.h> +#include <libyul/optimiser/FullInliner.h> +#include <libyul/optimiser/MainFunction.h> +#include <libyul/optimiser/Rematerialiser.h> +#include <libyul/optimiser/ExpressionSimplifier.h> +#include <libyul/optimiser/UnusedPruner.h> +#include <libyul/optimiser/ExpressionJoiner.h> +#include <libyul/optimiser/SSATransform.h> +#include <libyul/optimiser/RedundantAssignEliminator.h> +#include <libyul/optimiser/Suite.h> + +#include <libsolidity/parsing/Scanner.h> +#include <libsolidity/inlineasm/AsmPrinter.h> +#include <libsolidity/inlineasm/AsmParser.h> +#include <libsolidity/inlineasm/AsmAnalysis.h> +#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <libsolidity/interface/ErrorReporter.h> + +#include <boost/test/unit_test.hpp> +#include <boost/algorithm/string.hpp> + +#include <fstream> + +using namespace dev; +using namespace dev::yul; +using namespace dev::yul::test; +using namespace dev::solidity; +using namespace dev::solidity::test; +using namespace std; + +YulOptimizerTest::YulOptimizerTest(string const& _filename) +{ + boost::filesystem::path path(_filename); + + if (path.empty() || std::next(path.begin()) == path.end() || std::next(std::next(path.begin())) == path.end()) + BOOST_THROW_EXCEPTION(runtime_error("Filename path has to contain a directory: \"" + _filename + "\".")); + m_optimizerStep = std::prev(std::prev(path.end()))->string(); + + 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, "// yul")) + m_yul = true; + m_source += line + "\n"; + } + while (getline(file, line)) + if (boost::algorithm::starts_with(line, "// ")) + m_expectation += line.substr(3) + "\n"; + else + m_expectation += line + "\n"; +} + +bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmPrinter printer{m_yul}; + shared_ptr<Block> ast; + shared_ptr<assembly::AsmAnalysisInfo> analysisInfo; + if (!parse(_stream, _linePrefix, _formatted)) + return false; + + if (m_optimizerStep == "disambiguator") + disambiguate(); + else if (m_optimizerStep == "blockFlattener") + { + disambiguate(); + BlockFlattener{}(*m_ast); + } + else if (m_optimizerStep == "varDeclPropagator") + { + disambiguate(); + VarDeclPropagator{}(*m_ast); + } + else if (m_optimizerStep == "commonSubexpressionEliminator") + { + disambiguate(); + (CommonSubexpressionEliminator{})(*m_ast); + } + else if (m_optimizerStep == "expressionSplitter") + { + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + } + else if (m_optimizerStep == "expressionJoiner") + { + disambiguate(); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "splitJoin") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + ExpressionJoiner::run(*m_ast); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "functionGrouper") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + } + else if (m_optimizerStep == "functionHoister") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + } + else if (m_optimizerStep == "expressionInliner") + { + disambiguate(); + ExpressionInliner(*m_ast).run(); + } + else if (m_optimizerStep == "fullInliner") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + (FunctionGrouper{})(*m_ast); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + FullInliner(*m_ast, nameDispenser).run(); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "mainFunction") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + (MainFunction{})(*m_ast); + } + else if (m_optimizerStep == "rematerialiser") + { + disambiguate(); + (Rematerialiser{})(*m_ast); + } + else if (m_optimizerStep == "expressionSimplifier") + { + disambiguate(); + ExpressionSimplifier::run(*m_ast); + } + else if (m_optimizerStep == "fullSimplify") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + ExpressionSplitter{nameDispenser}(*m_ast); + CommonSubexpressionEliminator{}(*m_ast); + ExpressionSimplifier::run(*m_ast); + UnusedPruner::runUntilStabilised(*m_ast); + ExpressionJoiner::run(*m_ast); + ExpressionJoiner::run(*m_ast); + } + else if (m_optimizerStep == "unusedPruner") + { + disambiguate(); + UnusedPruner::runUntilStabilised(*m_ast); + } + else if (m_optimizerStep == "ssaTransform") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + SSATransform::run(*m_ast, nameDispenser); + } + else if (m_optimizerStep == "redundantAssignEliminator") + { + disambiguate(); + RedundantAssignEliminator::run(*m_ast); + } + else if (m_optimizerStep == "ssaPlusCleanup") + { + disambiguate(); + NameDispenser nameDispenser(*m_ast); + SSATransform::run(*m_ast, nameDispenser); + RedundantAssignEliminator::run(*m_ast); + } + else if (m_optimizerStep == "fullSuite") + OptimiserSuite::run(*m_ast, *m_analysisInfo); + else + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; + return false; + } + + m_obtainedResult = m_optimizerStep + "\n" + printer(*m_ast) + "\n"; + + if (m_expectation != m_obtainedResult) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl; + // TODO could compute a simple diff with highlighted lines + 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 YulOptimizerTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + printIndented(_stream, m_source, _linePrefix); +} + +void YulOptimizerTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +{ + printIndented(_stream, m_obtainedResult, _linePrefix); +} + +void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const +{ + stringstream output(_output); + string line; + while (getline(output, line)) + _stream << _linePrefix << line << endl; +} + +bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + assembly::AsmFlavour flavour = m_yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + ErrorList errors; + ErrorReporter errorReporter(errors); + shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source), ""); + m_ast = assembly::Parser(errorReporter, flavour).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); + return false; + } + m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); + assembly::AsmAnalyzer analyzer( + *m_analysisInfo, + errorReporter, + dev::test::Options::get().evmVersion(), + boost::none, + flavour + ); + 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); + return false; + } + return true; +} + +void YulOptimizerTest::disambiguate() +{ + *m_ast = boost::get<Block>(Disambiguator(*m_analysisInfo)(*m_ast)); + m_analysisInfo.reset(); +} + +void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors, Scanner const& _scanner) +{ + SourceReferenceFormatter formatter(_stream, [&](string const&) -> Scanner const& { return _scanner; }); + + for (auto const& error: _errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); +} diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h new file mode 100644 index 00000000..7db17ceb --- /dev/null +++ b/test/libyul/YulOptimizerTest.h @@ -0,0 +1,75 @@ +/* + 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/libsolidity/TestCase.h> + + +namespace dev +{ +namespace solidity +{ +class Scanner; +class Error; +using ErrorList = std::vector<std::shared_ptr<Error const>>; +namespace assembly +{ +struct AsmAnalysisInfo; +struct Block; +} +} +namespace yul +{ +namespace test +{ + +class YulOptimizerTest: public solidity::test::TestCase +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { + return std::unique_ptr<TestCase>(new YulOptimizerTest(_filename)); + } + + explicit YulOptimizerTest(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, solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); + + std::string m_source; + bool m_yul = false; + std::string m_optimizerStep; + std::string m_expectation; + + std::shared_ptr<solidity::assembly::Block> m_ast; + std::shared_ptr<solidity::assembly::AsmAnalysisInfo> m_analysisInfo; + std::string m_obtainedResult; +}; + +} +} +} diff --git a/test/libyul/yulOptimizerTests/blockFlattener/basic.yul b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul new file mode 100644 index 00000000..adcaedd0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/basic.yul @@ -0,0 +1,20 @@ +{ + 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) +} +// ---- +// blockFlattener +// { +// 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/blockFlattener/for_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul new file mode 100644 index 00000000..07bd5c18 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/for_stmt.yul @@ -0,0 +1,19 @@ +{ + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + a := add(a, 1) + } +} +// ---- +// blockFlattener +// { +// for { +// let a := 1 +// } +// iszero(eq(a, 10)) +// { +// a := add(a, 1) +// } +// { +// a := add(a, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul new file mode 100644 index 00000000..4d6ccf0e --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/if_stmt.yul @@ -0,0 +1,20 @@ +{ + if add(mload(7), sload(mload(3))) + { + let y := add(mload(3), 3) + { + y := add(y, 7) + } + } + let t := add(3, 9) +} +// ---- +// blockFlattener +// { +// 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/blockFlattener/many_nested_blocks.yul b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul new file mode 100644 index 00000000..ae2a066b --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/many_nested_blocks.yul @@ -0,0 +1,28 @@ +{ + 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) + } +} +// ---- +// blockFlattener +// { +// 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/blockFlattener/switch_stmt.yul b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul new file mode 100644 index 00000000..2df4f9d0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockFlattener/switch_stmt.yul @@ -0,0 +1,22 @@ +{ + let a := 1 + switch calldataload(0) + case 0 { { { mstore(0, 1) } } a := 8 } + default { a := 3 { a := 4 } } + a := 5 +} +// ---- +// blockFlattener +// { +// let a := 1 +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// a := 8 +// } +// default { +// a := 3 +// a := 4 +// } +// a := 5 +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul new file mode 100644 index 00000000..c59bced7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -0,0 +1,24 @@ +{ + let a := 1 let b := codesize() + for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { + mstore(1, codesize()) + } + mstore(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := 1 +// let b := codesize() +// for { +// } +// lt(1, b) +// { +// mstore(1, b) +// a := add(a, b) +// } +// { +// mstore(1, b) +// } +// mstore(1, b) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul new file mode 100644 index 00000000..5b8200d9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul @@ -0,0 +1,15 @@ +{ + let b := 1 + if b { b := 1 } + let c := 1 +} +// ---- +// commonSubexpressionEliminator +// { +// let b := 1 +// if b +// { +// b := b +// } +// let c := 1 +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul new file mode 100644 index 00000000..fd8b4bc8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/case2.yul @@ -0,0 +1,52 @@ +{ + let _13 := 0x20 + let _14 := allocate(_13) + pop(_14) + let _15 := 2 + let _16 := 3 + let _17 := 0x40 + let _18 := allocate(_17) + let _19 := array_index_access(_18, _16) + mstore(_19, _15) + function allocate(size) -> p + { + let _1 := 0x40 + let p_2 := mload(_1) + p := p_2 + let _20 := add(p_2, size) + mstore(_1, _20) + } + function array_index_access(array, index) -> p_1 + { + let _21 := 0x20 + let _22 := mul(index, _21) + p_1 := add(array, _22) + } +} +// ---- +// commonSubexpressionEliminator +// { +// let _13 := 0x20 +// let _14 := allocate(_13) +// pop(_14) +// let _15 := 2 +// let _16 := 3 +// let _17 := 0x40 +// let _18 := allocate(_17) +// let _19 := array_index_access(_18, _16) +// mstore(_19, _15) +// function allocate(size) -> p +// { +// let _1 := 0x40 +// let p_2 := mload(_1) +// p := p_2 +// let _20 := add(p_2, size) +// mstore(_1, _20) +// } +// function array_index_access(array, index) -> p_1 +// { +// let _21 := 0x20 +// let _22 := mul(index, _21) +// p_1 := add(array, _22) +// } +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul new file mode 100644 index 00000000..28e840cf --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul @@ -0,0 +1,52 @@ +{ + function allocate(size) -> p + { + let _1 := 0x40 + p := mload(_1) + let _2 := add(p, size) + let _3 := 0x40 + mstore(_3, _2) + } + function array_index_access(array, index) -> p_1 + { + let _4 := 0x20 + let _5 := mul(index, _4) + p_1 := add(array, _5) + } + let _6 := 0x20 + let _7 := allocate(_6) + pop(_7) + let _8 := 0x40 + let x := allocate(_8) + let _9 := 2 + let _10 := 3 + let _11 := array_index_access(x, _10) + mstore(_11, _9) +} +// ---- +// commonSubexpressionEliminator +// { +// function allocate(size) -> p +// { +// let _1 := 0x40 +// p := mload(_1) +// let _2 := add(p, size) +// let _3 := _1 +// mstore(_1, _2) +// } +// function array_index_access(array, index) -> p_1 +// { +// let _4 := 0x20 +// let _5 := mul(index, _4) +// p_1 := add(array, _5) +// } +// let _6 := 0x20 +// let _7 := allocate(_6) +// pop(_7) +// let _8 := 0x40 +// let x := allocate(_8) +// let _9 := 2 +// let _10 := 3 +// let _11 := array_index_access(x, _10) +// mstore(_11, _9) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul new file mode 100644 index 00000000..cb0ca38d --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul @@ -0,0 +1,10 @@ +{ + let a := mload(1) + let b := mload(1) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mload(1) +// let b := mload(1) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul new file mode 100644 index 00000000..ebc17446 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul @@ -0,0 +1,10 @@ +{ + let a := gas() + let b := gas() +} +// ---- +// commonSubexpressionEliminator +// { +// let a := gas() +// let b := gas() +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul new file mode 100644 index 00000000..49b4c916 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/scopes.yul @@ -0,0 +1,25 @@ +{ + let a := 10 + let x := 20 + { + let b := calldataload(0) + let d := calldataload(1) + x := d + } + // We had a bug where "calldataload(0)" was incorrectly replaced by "b" + mstore(0, calldataload(0)) + mstore(0, x) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := 10 +// let x := 20 +// { +// let b := calldataload(0) +// let d := calldataload(1) +// x := d +// } +// mstore(0, calldataload(0)) +// mstore(0, x) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul new file mode 100644 index 00000000..b9457229 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// commonSubexpressionEliminator +// { +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul new file mode 100644 index 00000000..684272f5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := mul(1, codesize()) + let b := mul(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mul(1, codesize()) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul new file mode 100644 index 00000000..ab94afc2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/variable_for_variable.yul @@ -0,0 +1,27 @@ +{ + + let a := mload(0) + let b := add(a, 7) + let c := a + let d := c + let x := add(a, b) + // CSE has to recognize equality with x here. + let y := add(d, add(c, 7)) + // some reassignments + b := mload(a) + a := b + mstore(2, a) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mload(0) +// let b := add(a, 7) +// let c := a +// let d := a +// let x := add(a, b) +// let y := x +// b := mload(a) +// a := b +// mstore(2, b) +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul new file mode 100644 index 00000000..6875abec --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul @@ -0,0 +1,28 @@ +// yul +{ + { let a:u256, b:u256 } + { + for { let a:u256 } a { a := a } { + let b:u256 := a + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256 +// } +// { +// for { +// let a_1:u256 +// } +// a_1 +// { +// a_1 := a_1 +// } +// { +// let b_2:u256 := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul new file mode 100644 index 00000000..df49b92a --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256, d:u256, f:u256 } + { + function f(a:u256) -> c:u256, d:u256 { + let b:u256, c_1:u256 := f(a) + } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256, d:u256, f:u256 +// } +// { +// function f_1(a_2:u256) -> c_3:u256, d_4:u256 +// { +// let b_5:u256, c_1:u256 := f_1(a_2) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul new file mode 100644 index 00000000..bc3aa30f --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul @@ -0,0 +1,22 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:bool + if a { let b:bool := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:bool +// if a_1 +// { +// let b_2:bool := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/long_names.yul b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul new file mode 100644 index 00000000..933e1e8f --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/long_names.yul @@ -0,0 +1,12 @@ +// yul +{ { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } { let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 } } +// ---- +// disambiguator +// { +// { +// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh:u256 +// } +// { +// let aanteuhdaoneudbrgkjiuaothduiathudaoeuh_1:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke.yul new file mode 100644 index 00000000..d6cd8a61 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul b/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul new file mode 100644 index 00000000..e55f4cd3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/smoke_yul.yul @@ -0,0 +1,6 @@ +// yul +{ } +// ---- +// disambiguator +// { +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul new file mode 100644 index 00000000..e62e957f --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul @@ -0,0 +1,27 @@ +// yul +{ + { let a:u256, b:u256, c:u256 } + { + let a:u256 + switch a + case 0:u256 { let b:u256 := a } + default { let c:u256 := a } + } +} +// ---- +// disambiguator +// { +// { +// let a:u256, b:u256, c:u256 +// } +// { +// let a_1:u256 +// switch a_1 +// case 0:u256 { +// let b_2:u256 := a_1 +// } +// default { +// let c_3:u256 := a_1 +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables.yul b/test/libyul/yulOptimizerTests/disambiguator/variables.yul new file mode 100644 index 00000000..65bd4c8f --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables.yul @@ -0,0 +1,12 @@ +// yul +{ { let a:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// } +// { +// let a_1:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul new file mode 100644 index 00000000..e462442a --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_clash.yul @@ -0,0 +1,13 @@ +// yul +{ { let a:u256 let a_1:u256 } { let a:u256 } } +// ---- +// disambiguator +// { +// { +// let a:u256 +// let a_1:u256 +// } +// { +// let a_2:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul new file mode 100644 index 00000000..839692bc --- /dev/null +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -0,0 +1,24 @@ +// yul +{ + { let c:u256 let b:u256 } + function f(a:u256, c:u256) -> b:u256 { let x:u256 } + { + let a:u256 let x:u256 + } +} +// ---- +// disambiguator +// { +// { +// let c:u256 +// let b:u256 +// } +// function f(a:u256, c_1:u256) -> b_2:u256 +// { +// let x:u256 +// } +// { +// let a_3:u256 +// let x_4:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul b/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul new file mode 100644 index 00000000..519a2af8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/complex_with_evm.yul @@ -0,0 +1,13 @@ +{ + function f(a) -> x { x := add(a, a) } + let y := f(calldatasize()) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// let y := add(calldatasize(), calldatasize()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul b/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul new file mode 100644 index 00000000..e1da8e07 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/double_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// y := mul(mload(c), add(b, b)) +// } +// let y_1 := mul(mload(7), add(calldatasize(), calldatasize())) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul b/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul new file mode 100644 index 00000000..082cb53f --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/double_recursive_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a, r) -> x { x := g(a, g(r, r)) } + function g(b, s) -> y { y := f(b, f(s, s)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a, r) -> x +// { +// x := g(a, f(r, f(r, r))) +// } +// function g(b, s) -> y +// { +// y := f(b, g(s, f(s, f(s, s)))) +// } +// let y_1 := f(calldatasize(), g(7, f(7, f(7, 7)))) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul b/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul new file mode 100644 index 00000000..0fb43a9d --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/no_inline_mload.yul @@ -0,0 +1,14 @@ +// Does not inline because mload could be moved out of sequence +{ + function f(a) -> x { x := a } + let y := f(mload(2)) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := a +// } +// let y := f(mload(2)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul b/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul new file mode 100644 index 00000000..7fdad6c4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul @@ -0,0 +1,27 @@ +// The calls to g and h cannot be moved because g and h are not movable. Therefore, the call +// to f is not inlined. +{ + function f(a, b) -> x { x := add(b, a) } + function g() -> y { y := mload(0) mstore(0, 4) } + function h() -> z { mstore(0, 4) z := mload(0) } + let r := f(g(), h()) +} +// ---- +// expressionInliner +// { +// function f(a, b) -> x +// { +// x := add(b, a) +// } +// function g() -> y +// { +// y := mload(0) +// mstore(0, 4) +// } +// function h() -> z +// { +// mstore(0, 4) +// z := mload(0) +// } +// let r := f(g(), h()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/simple.yul b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul new file mode 100644 index 00000000..c186eafd --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/simple.yul @@ -0,0 +1,14 @@ +// yul +{ + function f() -> x:u256 { x := 2:u256 } + let y:u256 := f() +} +// ---- +// expressionInliner +// { +// function f() -> x:u256 +// { +// x := 2:u256 +// } +// let y:u256 := 2:u256 +// } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul new file mode 100644 index 00000000..b5f4d515 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionInliner/with_args.yul @@ -0,0 +1,14 @@ +// yul +{ + function f(a:u256) -> x:u256 { x := a } + let y:u256 := f(7:u256) +} +// ---- +// expressionInliner +// { +// function f(a:u256) -> x:u256 +// { +// x := a +// } +// let y:u256 := 7:u256 +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul new file mode 100644 index 00000000..a1349511 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/if_condition.yul @@ -0,0 +1,21 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(c, b) + if d { + let x := mload(3) + let y := add(x, 3) + } + let z := 3 + let t := add(z, 9) +} +// ---- +// expressionJoiner +// { +// if add(mload(7), sload(mload(3))) +// { +// let y := add(mload(3), 3) +// } +// let t := add(3, 9) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul new file mode 100644 index 00000000..0d407c7c --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/muli_wrong_order3.yul @@ -0,0 +1,13 @@ +{ + let a := mload(3) + let b := mload(6) + let x := mul(add(b, a), mload(2)) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(3) +// let b := mload(6) +// sstore(mul(add(b, a), mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul new file mode 100644 index 00000000..fd53ca51 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi.yul @@ -0,0 +1,11 @@ +{ + let a := mload(2) + let b := mload(6) + let x := mul(add(b, a), 2) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(mul(add(mload(6), mload(2)), 2), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul new file mode 100644 index 00000000..078a12a5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_reference.yul @@ -0,0 +1,11 @@ +{ + // This is not joined because a is referenced multiple times + let a := mload(2) + let b := add(a, a) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// let b := add(a, a) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul new file mode 100644 index 00000000..965e07e9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order.yul @@ -0,0 +1,15 @@ +{ + // We have an interleaved "add" here, so we cannot inline "a" + // (note that this component does not analyze whether + // functions are pure or not) + let a := mload(2) + let b := mload(6) + let x := mul(a, add(2, b)) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// sstore(mul(a, add(2, mload(6))), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul new file mode 100644 index 00000000..c577e182 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/multi_wrong_order2.yul @@ -0,0 +1,12 @@ +{ + let a := mload(2) + let b := mload(6) + let x := mul(add(a, b), 2) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// sstore(mul(add(a, mload(6)), 2), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul new file mode 100644 index 00000000..a781bb2a --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_across_blocks.yul @@ -0,0 +1,19 @@ +{ + // The component will remove the empty block after + // it has handled the outer block. + // The idea behind this test is that the component + // does not perform replacements across blocks because + // they usually have contents, but adding contents + // will reduce the scope of the test. + let a := mload(2) + let x := calldataload(a) + { + } + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// let x := calldataload(mload(2)) +// sstore(x, 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul new file mode 100644 index 00000000..75218a5c --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition1.yul @@ -0,0 +1,15 @@ +{ + for { let b := mload(1) } b {} {} +} +// ---- +// expressionJoiner +// { +// for { +// let b := mload(1) +// } +// b +// { +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul new file mode 100644 index 00000000..d5f7d8fa --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/no_replacement_in_loop_condition2.yul @@ -0,0 +1,16 @@ +{ + let a := mload(0) + for { } a {} {} +} +// ---- +// expressionJoiner +// { +// let a := mload(0) +// for { +// } +// a +// { +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul new file mode 100644 index 00000000..c7411211 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/only_assignment.yul @@ -0,0 +1,16 @@ +{ + // This is not joined because a is referenced multiple times + function f(a) -> x { + a := mload(2) + x := add(a, 3) + } +} +// ---- +// expressionJoiner +// { +// function f(a) -> x +// { +// a := mload(2) +// x := add(a, 3) +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul new file mode 100644 index 00000000..1e502353 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/reassignment.yul @@ -0,0 +1,13 @@ +{ + // This is not joined because a is referenced multiple times + let a := mload(2) + let b := mload(a) + a := 4 +} +// ---- +// expressionJoiner +// { +// let a := mload(2) +// let b := mload(a) +// a := 4 +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul new file mode 100644 index 00000000..b03bcf45 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/simple.yul @@ -0,0 +1,10 @@ +{ + let a := mload(2) + let x := calldataload(a) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(calldataload(mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul new file mode 100644 index 00000000..3b433f78 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/single_wrong_order.yul @@ -0,0 +1,13 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(b, c) + sstore(d, 0) +} +// ---- +// expressionJoiner +// { +// let b := sload(mload(3)) +// sstore(add(b, mload(7)), 0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul new file mode 100644 index 00000000..c0e2c6f2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionJoiner +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul new file mode 100644 index 00000000..0e4e540e --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/switch_expression.yul @@ -0,0 +1,28 @@ +{ + let a := mload(3) + let b := sload(a) + let c := mload(7) + let d := add(c, b) + switch d + case 3 { + let x := mload(3) + let y := add(x, 3) + } + default { + sstore(1, 0) + } + let z := 3 + let t := add(z, 9) +} +// ---- +// expressionJoiner +// { +// switch add(mload(7), sload(mload(3))) +// case 3 { +// let y := add(mload(3), 3) +// } +// default { +// sstore(1, 0) +// } +// let t := add(3, 9) +// } diff --git a/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul new file mode 100644 index 00000000..7b722be1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionJoiner/triple.yul @@ -0,0 +1,12 @@ +{ + let a := mload(2) + let b := mload(6) + let c := mload(7) + let x := mul(add(c, b), a) + sstore(x, 3) +} +// ---- +// expressionJoiner +// { +// sstore(mul(add(mload(7), mload(6)), mload(2)), 3) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul new file mode 100644 index 00000000..0b55adc5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constant_propagation.yul @@ -0,0 +1,6 @@ +{ let a := add(7, sub(mload(0), 7)) } +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul new file mode 100644 index 00000000..bd1a5a53 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/constants.yul @@ -0,0 +1,6 @@ +{ let a := add(1, mul(3, 4)) } +// ---- +// expressionSimplifier +// { +// let a := 13 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul new file mode 100644 index 00000000..f6190622 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(0), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := 0 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul new file mode 100644 index 00000000..e91403cd --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(1), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := sub(calldataload(1), calldataload(0)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul new file mode 100644 index 00000000..d35686cd --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul @@ -0,0 +1,10 @@ +{ + let a := mload(0) + let b := sub(a, a) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := 0 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul new file mode 100644 index 00000000..c2ca504a --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul @@ -0,0 +1,12 @@ +{ + function f() -> a {} + let b := add(7, sub(f(), 7)) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := f() +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul new file mode 100644 index 00000000..42c37826 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul @@ -0,0 +1,16 @@ +{ + for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} +} +// ---- +// expressionSimplifier +// { +// for { +// let a := 10 +// } +// iszero(iszero(a)) +// { +// a := add(a, 1) +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul new file mode 100644 index 00000000..e6d84552 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/invariant.yul @@ -0,0 +1,10 @@ +{ + let a := mload(sub(7, 7)) + let b := sub(a, 0) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul new file mode 100644 index 00000000..88714ce0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 8))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 255)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul new file mode 100644 index 00000000..4d52abe8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 255))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul new file mode 100644 index 00000000..53270b72 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -0,0 +1,12 @@ +{ + function f(a) -> b { } + let c := sub(f(0), f(1)) +} +// ---- +// expressionSimplifier +// { +// function f(a) -> b +// { +// } +// let c := sub(f(0), f(1)) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul new file mode 100644 index 00000000..6ab65d29 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul @@ -0,0 +1,16 @@ +{ + function f1() -> a { } + function f2() -> b { } + let c := sub(f1(), f2()) +} +// ---- +// expressionSimplifier +// { +// function f1() -> a +// { +// } +// function f2() -> b +// { +// } +// let c := sub(f1(), f2()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul new file mode 100644 index 00000000..ab1bd128 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul @@ -0,0 +1,13 @@ +// Even if the functions pass the equality check, they are not movable. +{ + function f() -> a { } + let b := sub(f(), f()) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := sub(f(), f()) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul new file mode 100644 index 00000000..fc61c3df --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul @@ -0,0 +1,10 @@ +// The first argument of div is not constant. +// keccak256 is not movable. +{ + let a := div(keccak256(0, 0), 0) +} +// ---- +// expressionSimplifier +// { +// let a := div(keccak256(0, 0), 0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul new file mode 100644 index 00000000..6353cda9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/reversed.yul @@ -0,0 +1,8 @@ +{ + let a := add(0, mload(0)) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul new file mode 100644 index 00000000..88420e92 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSimplifier +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul new file mode 100644 index 00000000..d021129f --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul @@ -0,0 +1,40 @@ +{ + let x := calldataload(0) + if mul(add(x, 2), 3) { + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, 2), 4) + sstore(b, mul(b, 2)) + } + } +} +// ---- +// expressionSplitter +// { +// let _1 := 0 +// let x := calldataload(_1) +// let _2 := 3 +// let _3 := 2 +// let _4 := add(x, _3) +// let _5 := mul(_4, _2) +// if _5 +// { +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// let _6 := 2 +// let _7 := mul(a, _6) +// a := add(a, _7) +// } +// { +// let _8 := 4 +// let _9 := 2 +// let _10 := add(a, _9) +// let b := mul(_10, _8) +// let _11 := 2 +// let _12 := mul(b, _11) +// sstore(b, _12) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul b/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul new file mode 100644 index 00000000..53bbcea7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/inside_function.yul @@ -0,0 +1,29 @@ +{ + let x := mul(f(0, mload(7)), 3) + function f(a, b) -> c { + c := mul(a, mload(add(b, c))) + } + sstore(x, f(mload(2), mload(2))) +} +// ---- +// expressionSplitter +// { +// let _1 := 3 +// let _2 := 7 +// let _3 := mload(_2) +// let _4 := 0 +// let _5 := f(_4, _3) +// let x := mul(_5, _1) +// function f(a, b) -> c +// { +// let _6 := add(b, c) +// let _7 := mload(_6) +// c := mul(a, _7) +// } +// let _8 := 2 +// let _9 := mload(_8) +// let _10 := 2 +// let _11 := mload(_10) +// let _12 := f(_11, _9) +// sstore(x, _12) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul b/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul new file mode 100644 index 00000000..f69f60b6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSplitter +// { +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul b/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul new file mode 100644 index 00000000..aee7976f --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/switch.yul @@ -0,0 +1,33 @@ +{ + let x := 8 + switch add(2, calldataload(0)) + case 0 { sstore(0, mload(2)) } + default { mstore(0, mload(3)) } + x := add(mload(3), 4) +} +// ---- +// expressionSplitter +// { +// let x := 8 +// let _1 := 0 +// let _2 := calldataload(_1) +// let _3 := 2 +// let _4 := add(_3, _2) +// switch _4 +// case 0 { +// let _5 := 2 +// let _6 := mload(_5) +// let _7 := 0 +// sstore(_7, _6) +// } +// default { +// let _8 := 3 +// let _9 := mload(_8) +// let _10 := 0 +// mstore(_10, _9) +// } +// let _11 := 4 +// let _12 := 3 +// let _13 := mload(_12) +// x := add(_13, _11) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul b/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul new file mode 100644 index 00000000..bff70cd8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSplitter/trivial.yul @@ -0,0 +1,14 @@ +{ + mstore(add(calldataload(2), mload(3)), 8) +} +// ---- +// expressionSplitter +// { +// let _1 := 8 +// let _2 := 3 +// let _3 := mload(_2) +// let _4 := 2 +// let _5 := calldataload(_4) +// let _6 := add(_5, _3) +// mstore(_6, _1) +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul new file mode 100644 index 00000000..ee7f5bf5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul @@ -0,0 +1,30 @@ +{ + function f(a) -> b, c { let x := mload(a) b := sload(x) c := 3 } + let a1 := calldataload(0) + let b3, c3 := f(a1) + let b4, c4 := f(c3) +} +// ---- +// fullInliner +// { +// { +// let f_a := calldataload(0) +// let f_b +// let f_c +// 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 +// f_b_3 := sload(mload(f_a_2)) +// f_c_4 := 3 +// let b4 := f_b_3 +// let c4 := f_c_4 +// } +// function f(a) -> b, c +// { +// b := sload(mload(a)) +// c := 3 +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul new file mode 100644 index 00000000..00bb6577 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul @@ -0,0 +1,30 @@ +// This tests that splitting the expression inside the condition works properly. +{ + if gt(f(mload(1)), mload(0)) { + sstore(0, 2) + } + function f(a) -> r { + a := mload(a) + r := add(a, calldatasize()) + } +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(0) +// let f_a := mload(1) +// let f_r +// f_a := mload(f_a) +// f_r := add(f_a, calldatasize()) +// if gt(f_r, _2) +// { +// sstore(0, 2) +// } +// } +// function f(a) -> r +// { +// a := mload(a) +// r := add(a, calldatasize()) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul new file mode 100644 index 00000000..0972ac56 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul @@ -0,0 +1,43 @@ +{ + 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) + } + let a := mload(2) + let a2 := 2 + // This should not be inlined because it is not a constant + let r := f(a) + // This should be inlined because it is a constant + let t := f(a2) +} +// ---- +// fullInliner +// { +// { +// let a_1 := mload(2) +// let a2 := 2 +// let r := f(a_1) +// let f_a := a2 +// let f_b +// 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 +// } +// 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 new file mode 100644 index 00000000..3302a35c --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul @@ -0,0 +1,36 @@ +{ + 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) + } + // Single-use functions are always inlined. + let r := f(mload(1)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(1) +// let f_b +// 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 r := f_b +// } +// 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/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul new file mode 100644 index 00000000..644e9126 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul @@ -0,0 +1,25 @@ +{ + function verylongfunctionname(verylongvariablename) -> verylongvariablename2 { + verylongvariablename2 := add(verylongvariablename, verylongvariablename) + } + // same long name + let verylongvariablename2 := 3 + mstore(0, verylongfunctionname(verylongvariablename2)) + mstore(1, verylongvariablename2) +} +// ---- +// fullInliner +// { +// { +// let verylongvariablename2_1 := 3 +// let verylongfu_verylongvariablename := verylongvariablename2_1 +// let verylongfu_verylongvariablename2 +// verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename) +// mstore(0, verylongfu_verylongvariablename2) +// mstore(1, verylongvariablename2_1) +// } +// function verylongfunctionname(verylongvariablename) -> verylongvariablename2 +// { +// verylongvariablename2 := add(verylongvariablename, verylongvariablename) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul new file mode 100644 index 00000000..f3d0b286 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul @@ -0,0 +1,29 @@ +{ + function f(a, b, c) -> x { + x := add(a, b) + x := mul(x, c) + } + let y := add(mload(1), add(f(mload(2), mload(3), mload(4)), mload(5))) +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(5) +// let _4 := mload(4) +// let _6 := mload(3) +// let f_a := mload(2) +// let f_b := _6 +// let f_c := _4 +// let f_x +// f_x := add(f_a, f_b) +// f_x := mul(f_x, f_c) +// let _10 := add(f_x, _2) +// let y := add(mload(1), _10) +// } +// function f(a, b, c) -> x +// { +// x := add(a, b) +// x := mul(x, c) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul new file mode 100644 index 00000000..8bc6ec58 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul @@ -0,0 +1,31 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(f(3), 7) +} +// ---- +// fullInliner +// { +// { +// let _1 := 7 +// let f_a := 3 +// let f_x +// f_x := add(f_a, f_a) +// let g_b := f_x +// let g_c := _1 +// let g_y +// g_y := mul(mload(g_c), f(g_b)) +// let y_1 := g_y +// } +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// let f_a_6 := b +// let f_x_7 +// 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 new file mode 100644 index 00000000..19ac945e --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul @@ -0,0 +1,63 @@ +{ + // This is a test for an older version where + // inlining was performed on a function + // just being called. This is a problem + // because the statemenst of the original + // function might be in an invalid state. + + function f(x) { + mstore(0, x) + mstore(7, h()) + g(10) + mstore(1, x) + } + function g(x) { + f(1) + } + function h() -> t { + t := 2 + + } + { + f(100) + } +} +// ---- +// fullInliner +// { +// { +// { +// let f_x := 100 +// mstore(0, f_x) +// mstore(7, h()) +// g(10) +// mstore(1, f_x) +// } +// } +// function f(x) +// { +// mstore(0, x) +// let h_t +// h_t := 2 +// mstore(7, h_t) +// let g_x_1 := 10 +// let g_f_x_8 := 1 +// mstore(0, g_f_x_8) +// mstore(7, h()) +// g(10) +// mstore(1, g_f_x_8) +// mstore(1, x) +// } +// function g(x_1) +// { +// let f_x_8 := 1 +// mstore(0, f_x_8) +// mstore(7, h()) +// g(10) +// mstore(1, f_x_8) +// } +// function h() -> t +// { +// t := 2 +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul new file mode 100644 index 00000000..eebdec38 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul @@ -0,0 +1,26 @@ +{ + function f(a) -> x, y { + x := mul(a, a) + y := add(a, x) + } + let r, s := f(mload(0)) + mstore(r, s) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// let f_x +// let f_y +// f_x := mul(f_a, f_a) +// f_y := add(f_a, f_x) +// let r := f_x +// mstore(r, f_y) +// } +// function f(a) -> x, y +// { +// x := mul(a, a) +// y := add(a, x) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_return.yul b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul new file mode 100644 index 00000000..3708c557 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul @@ -0,0 +1,18 @@ +{ + function f(a) { + sstore(a, a) + } + f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// sstore(f_a, f_a) +// } +// function f(a) +// { +// sstore(a, a) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul new file mode 100644 index 00000000..9644e6c1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul @@ -0,0 +1,43 @@ +{ + for { let x := f(0) } f(x) { x := f(x) } + { + let t := f(x) + } + function f(a) -> r { + sstore(a, 0) + r := a + } +} +// ---- +// fullInliner +// { +// { +// for { +// let f_a := 0 +// let f_r +// sstore(f_a, 0) +// f_r := f_a +// let x := f_r +// } +// f(x) +// { +// let f_a_3 := x +// let f_r_4 +// sstore(f_a_3, 0) +// f_r_4 := f_a_3 +// x := f_r_4 +// } +// { +// let f_a_6 := x +// let f_r_7 +// sstore(f_a_6, 0) +// f_r_7 := f_a_6 +// let t := f_r_7 +// } +// } +// function f(a) -> r +// { +// sstore(a, 0) +// r := a +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul new file mode 100644 index 00000000..cd9e2746 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul @@ -0,0 +1,27 @@ +// An earlier version of the inliner produced +// pop(...) statements and explicitly removed them. +// This used to test that they are removed. +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + pop(add(f(7), 2)) +} +// ---- +// fullInliner +// { +// { +// let _1 := 2 +// let f_a := 7 +// let f_x +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// pop(add(f_x, _1)) +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/recursion.yul b/test/libyul/yulOptimizerTests/fullInliner/recursion.yul new file mode 100644 index 00000000..3e9a8021 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/recursion.yul @@ -0,0 +1,18 @@ +{ + function f(a) { + f(1) + } + f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// f(1) +// } +// function f(a) +// { +// f(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/simple.yul b/test/libyul/yulOptimizerTests/fullInliner/simple.yul new file mode 100644 index 00000000..fcdf453b --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/simple.yul @@ -0,0 +1,24 @@ +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + let y := add(f(sload(mload(2))), mload(7)) +} +// ---- +// fullInliner +// { +// { +// let _2 := mload(7) +// let f_a := sload(mload(2)) +// let f_x +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// let y := add(f_x, _2) +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul new file mode 100644 index 00000000..90a3e16d --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul @@ -0,0 +1,10 @@ +{ + let a := add(7, sub(mload(0), 7)) + mstore(a, 0) +} +// ---- +// fullSimplify +// { +// let _2 := 0 +// mstore(mload(_2), _2) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constants.yul b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul new file mode 100644 index 00000000..b9c7c1fc --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/constants.yul @@ -0,0 +1,9 @@ +{ + let a := add(1, mul(3, 4)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// mstore(0, 13) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul new file mode 100644 index 00000000..4b17d7ea --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_complex.yul @@ -0,0 +1,9 @@ +{ + let a := sub(calldataload(0), calldataload(0)) + mstore(a, 0) +} +// ---- +// fullSimplify +// { +// mstore(0, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul new file mode 100644 index 00000000..a1737efa --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_negative.yul @@ -0,0 +1,10 @@ +{ + let a := sub(calldataload(1), calldataload(0)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// mstore(_1, sub(calldataload(1), calldataload(_1))) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul new file mode 100644 index 00000000..22a358fd --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/identity_rules_simple.yul @@ -0,0 +1,11 @@ +{ + let a := mload(0) + mstore(0, sub(a, a)) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// pop(mload(_1)) +// mstore(_1, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul new file mode 100644 index 00000000..fa3ff07c --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul @@ -0,0 +1,13 @@ +{ + function f() -> a {} + let b := add(7, sub(f(), 7)) + mstore(b, 0) +} +// ---- +// fullSimplify +// { +// function f() -> a +// { +// } +// mstore(f(), 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul new file mode 100644 index 00000000..f1b40301 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul @@ -0,0 +1,17 @@ +{ + let x := calldataload(3) + for { let a := 10 } iszero(eq(a, sub(x, calldataload(3)))) { a := add(a, 1) } {} +} +// ---- +// fullSimplify +// { +// for { +// let a := 10 +// } +// iszero(iszero(a)) +// { +// a := add(a, 1) +// } +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul new file mode 100644 index 00000000..a8eedef1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul @@ -0,0 +1,17 @@ +{ + let a := calldataload(sub(7, 7)) + let b := sub(a, 0) + // Below, `b` is not eliminated, because + // we run CSE and then Simplify. + // Elimination of `b` would require another + // run of CSE afterwards. + mstore(b, eq(calldataload(0), a)) +} +// ---- +// fullSimplify +// { +// let a := calldataload(0) +// let _4 := 0 +// let b := a +// mstore(b, eq(calldataload(_4), a)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul new file mode 100644 index 00000000..bba16a94 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul @@ -0,0 +1,9 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 8))) +} +// ---- +// fullSimplify +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 255)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul new file mode 100644 index 00000000..4a6eaa52 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul @@ -0,0 +1,9 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 255))) +} +// ---- +// fullSimplify +// { +// let _4 := 0 +// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul new file mode 100644 index 00000000..0c5e3ed9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul @@ -0,0 +1,14 @@ +{ + function f(a) -> b { } + mstore(0, sub(f(0), f(1))) +} +// ---- +// fullSimplify +// { +// function f(a) -> b +// { +// } +// let _2 := f(1) +// let _3 := 0 +// mstore(_3, sub(f(_3), _2)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul new file mode 100644 index 00000000..90e89fe1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul @@ -0,0 +1,17 @@ +{ + function f1() -> a { } + function f2() -> b { } + let c := sub(f1(), f2()) + mstore(0, c) +} +// ---- +// fullSimplify +// { +// function f1() -> a +// { +// } +// function f2() -> b +// { +// } +// mstore(0, sub(f1(), f2())) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul new file mode 100644 index 00000000..92e50ebe --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_equality_not_movable.yul @@ -0,0 +1,14 @@ +// Even if the functions pass the equality check, they are not movable. +{ + function f() -> a { } + let b := sub(f(), f()) + mstore(0, b) +} +// ---- +// fullSimplify +// { +// function f() -> a +// { +// } +// mstore(0, sub(f(), f())) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul new file mode 100644 index 00000000..7dcdc280 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_removes_non_constant_and_not_movable.yul @@ -0,0 +1,12 @@ +// div is eliminated, but keccak256 has side-effects. +{ + let a := div(keccak256(0, 0), 0) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// pop(keccak256(_1, _1)) +// mstore(_1, 0) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/operations.yul b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul new file mode 100644 index 00000000..25467b62 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/operations.yul @@ -0,0 +1,44 @@ +{ + let x := mload(0) + mstore(1, mul(x, 0)) + mstore(2, div(x, 0)) + mstore(3, div(0, x)) + mstore(4, sdiv(x, 0)) + mstore(5, sdiv(0, x)) + mstore(6, and(0, x)) + mstore(7, and(x, 0)) + mstore(8, mod(0, x)) + mstore(9, mod(x, 0)) + mstore(10, lt(x, x)) + mstore(11, gt(x, x)) + mstore(12, slt(x, x)) + mstore(13, sgt(x, x)) + mstore(14, mod(x, x)) + mstore(15, and(x, not(x))) + mstore(16, and(not(x), x)) + mstore(17, or(x, not(x))) + mstore(18, or(not(x), x)) +} +// ---- +// fullSimplify +// { +// pop(mload(0)) +// mstore(1, 0) +// mstore(2, 0) +// mstore(3, 0) +// mstore(4, 0) +// mstore(5, 0) +// mstore(6, 0) +// mstore(7, 0) +// mstore(8, 0) +// mstore(9, 0) +// mstore(10, 0) +// mstore(11, 0) +// mstore(12, 0) +// mstore(13, 0) +// mstore(14, 0) +// mstore(15, 0) +// mstore(16, 0) +// mstore(17, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// mstore(18, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul new file mode 100644 index 00000000..fb916e6a --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/reversed.yul @@ -0,0 +1,10 @@ +{ + let a := add(0, mload(0)) + mstore(0, a) +} +// ---- +// fullSimplify +// { +// let _1 := 0 +// mstore(_1, mload(_1)) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul new file mode 100644 index 00000000..714eb860 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/signextend.yul @@ -0,0 +1,12 @@ +{ + let x := 7 + mstore(0, signextend(50, x)) + let y := 255 + mstore(1, signextend(0, y)) +} +// ---- +// fullSimplify +// { +// mstore(0, 7) +// mstore(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul new file mode 100644 index 00000000..a4fbb899 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSimplify/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// fullSimplify +// { +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul new file mode 100644 index 00000000..a34da198 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -0,0 +1,654 @@ +{ + let x := abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(mload(0), 0x20) + 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(0x20), mload(0x40)) + sstore(a, b) + sstore(c, d) + sstore(0, x) + + function abi_decode_t_address(offset, end) -> value + { + value := cleanup_revert_t_address(calldataload(offset)) + } + function abi_decode_t_array$_t_address_$dyn_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_address(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x40)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_array$_t_uint256_$2_memory(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x40) + } + } + function abi_decode_t_array$_t_uint256_$2_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := 0x2 + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(length)) + let dst := array + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_uint256_$dyn_memory(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset, end) -> array + { + if iszero(slt(add(offset, 0x1f), end)) + { + revert(0, 0) + } + let length := calldataload(offset) + array := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length)) + let dst := array + mstore(array, length) + offset := add(offset, 0x20) + dst := add(dst, 0x20) + let src := offset + if gt(add(src, mul(length, 0x20)), end) + { + revert(0, 0) + } + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + let elementPos := src + mstore(dst, abi_decode_t_uint256(elementPos, end)) + dst := add(dst, 0x20) + src := add(src, 0x20) + } + } + function abi_decode_t_contract$_C_$55(offset, end) -> value + { + value := cleanup_revert_t_contract$_C_$55(calldataload(offset)) + } + function abi_decode_t_struct$_S_$11_memory_ptr(headStart, end) -> value + { + if slt(sub(end, headStart), 0x60) + { + revert(0, 0) + } + value := allocateMemory(0x60) + { + let offset := 0 + mstore(add(value, 0x0), abi_decode_t_uint256(add(headStart, offset), end)) + } + { + let offset := calldataload(add(headStart, 32)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + mstore(add(value, 0x20), abi_decode_t_array$_t_uint256_$dyn_memory(add(headStart, offset), end)) + } + { + let offset := calldataload(add(headStart, 64)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + mstore(add(value, 0x40), abi_decode_t_array$_t_address_$dyn_memory(add(headStart, offset), end)) + } + } + function abi_decode_t_uint256(offset, end) -> value + { + value := cleanup_revert_t_uint256(calldataload(offset)) + } + function abi_decode_t_uint8(offset, end) -> value + { + value := cleanup_revert_t_uint8(calldataload(offset)) + } + function abi_decode_tuple_t_contract$_C_$55t_uint8(headStart, dataEnd) -> value0, value1 + { + if slt(sub(dataEnd, headStart), 64) + { + revert(0, 0) + } + { + let offset := 0 + value0 := abi_decode_t_contract$_C_$55(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint8(add(headStart, offset), dataEnd) + } + } + function abi_decode_tuple_t_struct$_S_$11_memory_ptrt_uint256(headStart, dataEnd) -> value0, value1 + { + if slt(sub(dataEnd, headStart), 64) + { + revert(0, 0) + } + { + let offset := calldataload(add(headStart, 0)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value0 := abi_decode_t_struct$_S_$11_memory_ptr(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + } + function abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(headStart, dataEnd) -> value0, value1, value2, value3 + { + if slt(sub(dataEnd, headStart), 128) + { + revert(0, 0) + } + { + let offset := 0 + value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value1 := abi_decode_t_uint256(add(headStart, offset), dataEnd) + } + { + let offset := calldataload(add(headStart, 64)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(headStart, offset), dataEnd) + } + { + let offset := calldataload(add(headStart, 96)) + if gt(offset, 0xffffffffffffffff) + { + revert(0, 0) + } + value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart, offset), dataEnd) + } + } + function abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(value, pos) -> end + { + let length := array_length_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) + mstore(pos, length) + pos := add(pos, 0x20) + let srcPtr := array_dataslot_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(mload(srcPtr), pos) + srcPtr := array_nextElement_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(srcPtr) + pos := add(pos, 0x60) + } + end := pos + } + function abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(value, pos) + { + let length := array_length_t_array$_t_contract$_C_$55_$3_memory(value) + let srcPtr := array_dataslot_t_array$_t_contract$_C_$55_$3_memory(value) + for { + let i := 0 + } + lt(i, length) + { + i := add(i, 1) + } + { + abi_encode_t_contract$_C_$55_to_t_address(mload(srcPtr), pos) + srcPtr := array_nextElement_t_array$_t_contract$_C_$55_$3_memory(srcPtr) + pos := add(pos, 0x20) + } + } + function abi_encode_t_bool_to_t_bool(value, pos) + { + mstore(pos, cleanup_assert_t_bool(value)) + } + function abi_encode_t_contract$_C_$55_to_t_address(value, pos) + { + mstore(pos, convert_t_contract$_C_$55_to_t_address(value)) + } + function abi_encode_t_uint16_to_t_uint16(value, pos) + { + mstore(pos, cleanup_assert_t_uint16(value)) + } + function abi_encode_t_uint24_to_t_uint24(value, pos) + { + mstore(pos, cleanup_assert_t_uint24(value)) + } + function abi_encode_tuple_t_bool__to_t_bool_(headStart, value0) -> tail + { + tail := add(headStart, 32) + abi_encode_t_bool_to_t_bool(value0, add(headStart, 0)) + } + function abi_encode_tuple_t_uint16_t_uint24_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr__to_t_uint16_t_uint24_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr_(headStart, value2, value1, value0) -> tail + { + tail := add(headStart, 96) + abi_encode_t_uint16_to_t_uint16(value0, add(headStart, 0)) + abi_encode_t_uint24_to_t_uint24(value1, add(headStart, 32)) + mstore(add(headStart, 64), sub(tail, headStart)) + tail := abi_encode_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr_to_t_array$_t_array$_t_address_$3_memory_$dyn_memory_ptr(value2, tail) + } + function allocateMemory(size) -> memPtr + { + memPtr := mload(64) + let newFreePtr := add(memPtr, size) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) + { + revert(0, 0) + } + mstore(64, newFreePtr) + } + function array_allocation_size_t_array$_t_address_$dyn_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$2_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$dyn_memory(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length) -> size + { + if gt(length, 0xffffffffffffffff) + { + revert(0, 0) + } + size := mul(length, 0x20) + size := add(size, 0x20) + } + function array_dataslot_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(memPtr) -> dataPtr + { + dataPtr := add(memPtr, 0x20) + } + function array_dataslot_t_array$_t_contract$_C_$55_$3_memory(memPtr) -> dataPtr + { + dataPtr := memPtr + } + function array_length_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(value) -> length + { + length := mload(value) + } + function array_length_t_array$_t_contract$_C_$55_$3_memory(value) -> length + { + length := 0x3 + } + function array_nextElement_t_array$_t_array$_t_contract$_C_$55_$3_memory_$dyn_memory_ptr(memPtr) -> nextPtr + { + nextPtr := add(memPtr, 0x20) + } + function array_nextElement_t_array$_t_contract$_C_$55_$3_memory(memPtr) -> nextPtr + { + nextPtr := add(memPtr, 0x20) + } + function cleanup_assert_t_address(value) -> cleaned + { + cleaned := cleanup_assert_t_uint160(value) + } + function cleanup_assert_t_bool(value) -> cleaned + { + cleaned := iszero(iszero(value)) + } + function cleanup_assert_t_uint16(value) -> cleaned + { + cleaned := and(value, 0xFFFF) + } + function cleanup_assert_t_uint160(value) -> cleaned + { + cleaned := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + } + function cleanup_assert_t_uint24(value) -> cleaned + { + cleaned := and(value, 0xFFFFFF) + } + function cleanup_revert_t_address(value) -> cleaned + { + cleaned := cleanup_assert_t_uint160(value) + } + function cleanup_revert_t_contract$_C_$55(value) -> cleaned + { + cleaned := cleanup_assert_t_address(value) + } + function cleanup_revert_t_uint256(value) -> cleaned + { + cleaned := value + } + function cleanup_revert_t_uint8(value) -> cleaned + { + cleaned := and(value, 0xFF) + } + function convert_t_contract$_C_$55_to_t_address(value) -> converted + { + converted := convert_t_contract$_C_$55_to_t_uint160(value) + } + function convert_t_contract$_C_$55_to_t_uint160(value) -> converted + { + converted := cleanup_assert_t_uint160(value) + } +} +// ---- +// fullSuite +// { +// { +// let _1 := 0x20 +// let _2 := 0 +// let _485 := mload(_2) +// 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 +// let abi_encode_srcPtr := add(_485, _1) +// 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 +// for { +// let abi_encode_i_74_1040 := _2 +// } +// lt(abi_encode_i_74_1040, abi_encode_length_72_1038) +// { +// abi_encode_i_74_1040 := add(abi_encode_i_74_1040, 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) +// } +// 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) +// { +// revert(_2, _2) +// } +// { +// abi_decode_value0_60 := calldataload(_488) +// } +// { +// abi_decode_value1_61 := calldataload(add(_488, 32)) +// } +// { +// 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 +// } +// { +// 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) +// { +// abi_decode_i_9_1068 := add(abi_decode_i_9_1068, 1) +// } +// { +// 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) +// } +// abi_decode_value3 := abi_decode_array_5_254_1061 +// } +// 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 +// { +// let _199 := 64 +// let memPtr_315 := mload(_199) +// memPtr := memPtr_315 +// let newFreePtr := add(memPtr_315, size) +// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr_315)) +// { +// let _204 := 0 +// revert(_204, _204) +// } +// mstore(_199, newFreePtr) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul new file mode 100644 index 00000000..deb02068 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -0,0 +1,24 @@ +{ + function allocate(size) -> p { + p := mload(0x40) + mstore(0x40, add(p, size)) + } + function array_index_access(array, index) -> p { + p := add(array, mul(index, 0x20)) + } + pop(allocate(0x20)) + let x := allocate(0x40) + mstore(array_index_access(x, 3), 2) +} +// ---- +// 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) +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul new file mode 100644 index 00000000..f0d49d7b --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/empty_block.yul @@ -0,0 +1,24 @@ +// yul +{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } } +// ---- +// functionGrouper +// { +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul new file mode 100644 index 00000000..c830d5da --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul @@ -0,0 +1,24 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 function g() { let d:u256 } + let e:u256 +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul new file mode 100644 index 00000000..4a8be86a --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/nested_fun.yul @@ -0,0 +1,27 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { + let c:u256 + } + let d:u256 + } +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul new file mode 100644 index 00000000..149a44eb --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/single_fun.yul @@ -0,0 +1,14 @@ +// yul +{ + let a:u256 function f() {} +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul b/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul new file mode 100644 index 00000000..650a163e --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionGrouper/smoke.yul @@ -0,0 +1,7 @@ +{ } +// ---- +// functionGrouper +// { +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul new file mode 100644 index 00000000..6ea9f59d --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/empty_block.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + { } + for {} f() {} {} + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul new file mode 100644 index 00000000..1e3bc5a1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/multi_mixed.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// functionHoister +// { +// let a:u256 +// let c:u256 +// let e:u256 +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/nested.yul b/test/libyul/yulOptimizerTests/functionHoister/nested.yul new file mode 100644 index 00000000..20f094f1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/nested.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256 } + let d:u256 + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function g() +// { +// let c:u256 +// } +// function f() +// { +// let b:u256 +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/single.yul b/test/libyul/yulOptimizerTests/functionHoister/single.yul new file mode 100644 index 00000000..ba922612 --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/single.yul @@ -0,0 +1,13 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/functionHoister/smoke.yul b/test/libyul/yulOptimizerTests/functionHoister/smoke.yul new file mode 100644 index 00000000..35c1ce5f --- /dev/null +++ b/test/libyul/yulOptimizerTests/functionHoister/smoke.yul @@ -0,0 +1,6 @@ +{ +} +// ---- +// functionHoister +// { +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul b/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul new file mode 100644 index 00000000..bae6bd48 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/empty_block.yul @@ -0,0 +1,33 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + {} + for {} f() {} {} + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul b/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul new file mode 100644 index 00000000..dd5caaec --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/multi_fun_mixed.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul b/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul new file mode 100644 index 00000000..309b97cc --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/nested_fun.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256} + let d:u256 + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul b/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul new file mode 100644 index 00000000..fa9a8f41 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/sigle_fun.yul @@ -0,0 +1,16 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/mainFunction/smoke.yul b/test/libyul/yulOptimizerTests/mainFunction/smoke.yul new file mode 100644 index 00000000..7be14746 --- /dev/null +++ b/test/libyul/yulOptimizerTests/mainFunction/smoke.yul @@ -0,0 +1,9 @@ +// yul +{} +// ---- +// mainFunction +// { +// function main() +// { +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul new file mode 100644 index 00000000..d9bbd86d --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul @@ -0,0 +1,26 @@ +{ + for { + let a := 2 + // Should not be removed, even though you might think + // it goes out of scope + a := 3 + } a { a := add(a, 1) } + { + a := 7 + } +} +// ---- +// redundantAssignEliminator +// { +// for { +// let a := 2 +// a := 3 +// } +// a +// { +// a := add(a, 1) +// } +// { +// a := 7 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul new file mode 100644 index 00000000..7f5e97ce --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_branch.yul @@ -0,0 +1,31 @@ +{ + let x + let y + // Cannot be removed, because we might skip the loop + x := 1 + for { } calldataload(0) { } + { + // Cannot be removed + x := 2 + // Can be removed + y := 3 + } + y := 8 + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// let y +// x := 1 +// for { +// } +// calldataload(0) +// { +// } +// { +// x := 2 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul new file mode 100644 index 00000000..65eb2838 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for_rerun.yul @@ -0,0 +1,27 @@ +{ + let x + // Cannot be removed, because we might run the loop only once + x := 1 + for { } calldataload(0) { } + { + mstore(x, 2) + // Cannot be removed because of the line above + x := 2 + } + x := 3 +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// for { +// } +// calldataload(0) +// { +// } +// { +// mstore(x, 2) +// x := 2 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul new file mode 100644 index 00000000..5bb920ec --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/function.yul @@ -0,0 +1,23 @@ +{ + let r + r := 1 + function f(x, y) -> a, b { + // Can be removed, is param + x := 1 + y := 2 + // Cannot be removed, is return param + a := 3 + b := 4 + } + r := 2 +} +// ---- +// redundantAssignEliminator +// { +// let r +// function f(x, y) -> a, b +// { +// a := 3 +// b := 4 +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul new file mode 100644 index 00000000..958bfc66 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if.yul @@ -0,0 +1,24 @@ +{ + let c + let d + c := calldataload(0) + d := 1 + if c { + d := 2 + } + // This enforces that none of the assignments above can be removed. + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// d := 1 +// if c +// { +// d := 2 +// } +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul new file mode 100644 index 00000000..e47c31d1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_overwrite_all_branches.yul @@ -0,0 +1,24 @@ +{ + let c + let d + c := calldataload(0) + // This assignment will be overwritten in all branches and thus can be removed. + d := 1 + if c { + d := 2 + } + d := 3 + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// if c +// { +// } +// d := 3 +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul new file mode 100644 index 00000000..00065ed2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/if_used_in_one_branch.yul @@ -0,0 +1,25 @@ +{ + let c + let d + c := calldataload(0) + d := 1 + if c { + // Uses the assignment above + d := d + } + d := 3 + mstore(0, d) +} +// ---- +// redundantAssignEliminator +// { +// let c +// let d +// c := calldataload(0) +// d := 1 +// if c +// { +// } +// d := 3 +// mstore(0, d) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul new file mode 100644 index 00000000..26bcfc72 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multi_assign.yul @@ -0,0 +1,19 @@ +{ + function f() -> a, b {} + let x, y + x := 1 + x := 2 + // Will not be used, but is a multi-assign, so not removed. + x, y := f() + x := 3 + y := 4 +} +// ---- +// redundantAssignEliminator +// { +// function f() -> a, b +// { +// } +// let x, y +// x, y := f() +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul new file mode 100644 index 00000000..cf646126 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/multivar.yul @@ -0,0 +1,15 @@ +{ + let a := 2 + a := 7 + let b := 8 + b := a + a := b +} +// ---- +// redundantAssignEliminator +// { +// let a := 2 +// a := 7 +// let b := 8 +// b := a +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul new file mode 100644 index 00000000..ae3e5226 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/non_movable.yul @@ -0,0 +1,11 @@ +{ + let a + a := 0 + a := mload(0) +} +// ---- +// redundantAssignEliminator +// { +// let a +// a := mload(0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul new file mode 100644 index 00000000..702f854d --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/scopes.yul @@ -0,0 +1,16 @@ +{ + let a + { + let b + b := 2 + a := 2 + } +} +// ---- +// redundantAssignEliminator +// { +// let a +// { +// let b +// } +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul new file mode 100644 index 00000000..913a7694 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/simple.yul @@ -0,0 +1,10 @@ +{ + let a + a := 1 + a := 2 +} +// ---- +// redundantAssignEliminator +// { +// let a +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul new file mode 100644 index 00000000..96265576 --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_all.yul @@ -0,0 +1,22 @@ +{ + let x + // Will be overwritten in all branches + x := 1 + switch calldataload(0) + case 0 { x := 2 } + default { x := 3 } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// default { +// x := 3 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul new file mode 100644 index 00000000..cbe859ed --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_in_one.yul @@ -0,0 +1,19 @@ +{ + let x + // Will NOT be overwritten in all branches + x := 1 + switch calldataload(0) + case 0 { x := 2 } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul new file mode 100644 index 00000000..1a3b26eb --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_overwrite_use_combination.yul @@ -0,0 +1,23 @@ +{ + let x + // Will be used in some and overwritten in others + x := 1 + switch calldataload(0) + case 0 { x := 2 } + default { mstore(x, 1) } + mstore(x, 0) +} +// ---- +// redundantAssignEliminator +// { +// let x +// x := 1 +// switch calldataload(0) +// case 0 { +// x := 2 +// } +// default { +// mstore(x, 1) +// } +// mstore(x, 0) +// } diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul new file mode 100644 index 00000000..cc78b74d --- /dev/null +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/switch_unused.yul @@ -0,0 +1,16 @@ +{ + let x + // Not referenced anywhere. + x := 1 + switch calldataload(0) + case 0 { mstore(0, 1) } +} +// ---- +// redundantAssignEliminator +// { +// let x +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul new file mode 100644 index 00000000..dbd1ee63 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul @@ -0,0 +1,21 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + pop(a) + } +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// pop(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul new file mode 100644 index 00000000..6a52e045 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul @@ -0,0 +1,25 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + a := 7 + let c := a + } + let x := a +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// a +// { +// pop(7) +// } +// { +// a := 7 +// let c := 7 +// } +// let x := a +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul new file mode 100644 index 00000000..fc816419 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul @@ -0,0 +1,23 @@ +{ + let b := 0 + for { let a := 1 pop(a) } a { pop(a) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// b := 1 +// pop(1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul new file mode 100644 index 00000000..3d916890 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul @@ -0,0 +1,24 @@ +{ + let b := 0 + for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// lt(a, 0) +// { +// pop(a) +// a := add(a, 3) +// } +// { +// b := 1 +// pop(a) +// } +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul new file mode 100644 index 00000000..c148c2f2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_if.yul @@ -0,0 +1,18 @@ +{ + let a := 1 + let b := 2 + if b { pop(b) b := a } + let c := b +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// if 2 +// { +// pop(2) +// b := 1 +// } +// let c := b +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul new file mode 100644 index 00000000..8f70a79d --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_switch.yul @@ -0,0 +1,24 @@ +{ + let a := 1 + let b := 2 + switch number() + case 1 { b := a } + default { let x := a let y := b b := a } + pop(add(a, b)) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// switch number() +// case 1 { +// b := 1 +// } +// default { +// let x := 1 +// let y := b +// b := 1 +// } +// pop(add(1, b)) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul new file mode 100644 index 00000000..891a5043 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul @@ -0,0 +1,19 @@ +// Cannot replace `let b := x` by `let b := a` since a is out of scope. +{ + let x + { + let a := sload(0) + x := a + } + let b := x +} +// ---- +// rematerialiser +// { +// let x +// { +// let a := sload(0) +// x := a +// } +// let b := x +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul new file mode 100644 index 00000000..016fa0d7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) +// let b := x +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul new file mode 100644 index 00000000..d95dc1fc --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// let b := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/expression.yul b/test/libyul/yulOptimizerTests/rematerialiser/expression.yul new file mode 100644 index 00000000..a801677d --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/expression.yul @@ -0,0 +1,10 @@ +{ + let a := add(mul(calldatasize(), 2), number()) + let b := add(a, a) +} +// ---- +// rematerialiser +// { +// let a := add(mul(calldatasize(), 2), number()) +// let b := add(add(mul(calldatasize(), 2), number()), add(mul(calldatasize(), 2), number())) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul new file mode 100644 index 00000000..9a041dfc --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul @@ -0,0 +1,18 @@ +{ + function f(x) -> y {} + let a := 1 + let b := f(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// function f(x) -> y +// { +// } +// let a := 1 +// let b := f(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul new file mode 100644 index 00000000..8767abc9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_instruction.yul @@ -0,0 +1,14 @@ +{ + let a := 1 + let b := mload(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := mload(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul new file mode 100644 index 00000000..47124658 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassign.yul @@ -0,0 +1,21 @@ +{ + let a := extcodesize(0) + let b := a + let c := b + a := 2 + let d := add(b, c) + pop(a) pop(b) pop(c) pop(d) +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// let b := a +// let c := a +// a := 2 +// let d := add(b, c) +// pop(2) +// pop(b) +// pop(c) +// pop(add(b, c)) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul b/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul new file mode 100644 index 00000000..13238780 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/reassignment.yul @@ -0,0 +1,19 @@ +{ + let a := 1 + pop(a) + if a { a := 2 } + let b := mload(a) + pop(b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// pop(1) +// if 1 +// { +// a := 2 +// } +// let b := mload(a) +// pop(b) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul b/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul new file mode 100644 index 00000000..2423db32 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/smoke.yul @@ -0,0 +1,5 @@ +{} +// ---- +// rematerialiser +// { +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul b/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul new file mode 100644 index 00000000..d29ea98a --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/trivial.yul @@ -0,0 +1,12 @@ +{ + let a := 1 + let b := a + mstore(0, b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 1 +// mstore(0, 1) +// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul new file mode 100644 index 00000000..7d35fee0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/rematerialiser/update_asignment_remat.yul @@ -0,0 +1,13 @@ +// We cannot substitute `a` in `let b := a` +{ + let a := extcodesize(0) + a := mul(a, 2) + let b := a +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// a := mul(a, 2) +// let b := a +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul new file mode 100644 index 00000000..ad609c74 --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/control_flow.yul @@ -0,0 +1,26 @@ +{ + if mul(add(calldataload(0), 2), 3) { + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, 2), 4) + sstore(b, mul(b, 2)) + } + } +} +// ---- +// splitJoin +// { +// if mul(add(calldataload(0), 2), 3) +// { +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// a := add(a, mul(a, 2)) +// } +// { +// let b := mul(add(a, 2), 4) +// sstore(b, mul(b, 2)) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/functions.yul b/test/libyul/yulOptimizerTests/splitJoin/functions.yul new file mode 100644 index 00000000..549fc550 --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/functions.yul @@ -0,0 +1,30 @@ +{ + let x := f(0) + function f(y) -> r { + r := mload(mul(6, add(y, 0x20))) + } + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, f(a)), 4) + sstore(b, mul(b, 2)) + } +} +// ---- +// splitJoin +// { +// let x := f(0) +// function f(y) -> r +// { +// r := mload(mul(6, add(y, 0x20))) +// } +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// a := add(a, mul(a, 2)) +// } +// { +// let b := mul(add(a, f(a)), 4) +// sstore(b, mul(b, 2)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/splitJoin/smoke.yul b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul new file mode 100644 index 00000000..4b133029 --- /dev/null +++ b/test/libyul/yulOptimizerTests/splitJoin/smoke.yul @@ -0,0 +1,5 @@ +{} +// ---- +// splitJoin +// { +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul new file mode 100644 index 00000000..d2408343 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul @@ -0,0 +1,35 @@ +{ + function copy(from, to) -> length { + length := mload(from) + mstore(to, length) + from := add(from, 0x20) + to := add(to, 0x20) + for { let x := 1 } lt(x, length) { x := add(x, 0x20) } { + mstore(add(to, x), mload(add(from, x))) + } + } +} +// ---- +// ssaPlusCleanup +// { +// function copy(from, to) -> length +// { +// let length_1 := mload(from) +// length := length_1 +// mstore(to, length_1) +// let from_2 := add(from, 0x20) +// let to_3 := add(to, 0x20) +// for { +// let x_4 := 1 +// let x := x_4 +// } +// lt(x, length_1) +// { +// let x_5 := add(x, 0x20) +// x := x_5 +// } +// { +// mstore(add(to_3, x), mload(add(from_2, x))) +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul new file mode 100644 index 00000000..ddb33aa0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign.yul @@ -0,0 +1,17 @@ +{ + let a := 1 + a := 2 + a := 3 + a := 4 + mstore(0, a) +} +// ---- +// ssaPlusCleanup +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// let a_3 := 3 +// let a_4 := 4 +// mstore(0, a_4) +// } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul new file mode 100644 index 00000000..67a6c5d3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/multi_reassign_with_use.yul @@ -0,0 +1,17 @@ +{ + let a := 1 + a := add(a, 2) + a := add(a, 3) + a := mload(add(a, 4)) + mstore(0, a) +} +// ---- +// ssaPlusCleanup +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := add(a_1, 2) +// let a_3 := add(a_2, 3) +// let a_4 := mload(add(a_3, 4)) +// mstore(0, a_4) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/branches.yul b/test/libyul/yulOptimizerTests/ssaTransform/branches.yul new file mode 100644 index 00000000..c089fe70 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/branches.yul @@ -0,0 +1,25 @@ +{ + let a := 1 + a := add(a, 1) + if a { + a := add(a, 1) + } + a := add(a, 1) + mstore(a, 1) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := add(a_1, 1) +// a := a_2 +// if a_2 +// { +// let a_3 := add(a_2, 1) +// a := a_3 +// } +// let a_4 := add(a, 1) +// a := a_4 +// mstore(a_4, 1) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul new file mode 100644 index 00000000..41640346 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_body.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { mstore(0, a) } a { mstore(0, a) } + { + a := add(a, 3) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// mstore(0, a_1) +// } +// a +// { +// mstore(0, a) +// } +// { +// let a_2 := add(a, 3) +// a := a_2 +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul new file mode 100644 index 00000000..821a5b2a --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_init.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { a := add(a, 3) } a { mstore(0, a) } + { + mstore(0, a) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// let a_2 := add(a_1, 3) +// a := a_2 +// } +// a +// { +// mstore(0, a) +// } +// { +// mstore(0, a) +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul new file mode 100644 index 00000000..1fc075bc --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_reassign_post.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + for { mstore(0, a) } a { a := add(a, 3) } + { + mstore(0, a) + } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// for { +// mstore(0, a_1) +// } +// a +// { +// let a_2 := add(a, 3) +// a := a_2 +// } +// { +// mstore(0, a) +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul new file mode 100644 index 00000000..273d3811 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_simple.yul @@ -0,0 +1,47 @@ +{ + let a := mload(0) + a := add(a, 1) + if a { + a := add(a, 2) + } + { + a := add(a, 4) + } + for { a := add(a, 3) } a { a := add(a, 6) } + { + a := add(a, 12) + } + a := add(a, 8) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// let a_2 := add(a_1, 1) +// a := a_2 +// if a_2 +// { +// let a_3 := add(a_2, 2) +// a := a_3 +// } +// { +// let a_4 := add(a, 4) +// a := a_4 +// } +// for { +// let a_5 := add(a, 3) +// a := a_5 +// } +// a +// { +// let a_7 := add(a, 6) +// a := a_7 +// } +// { +// let a_6 := add(a, 12) +// a := a_6 +// } +// let a_8 := add(a, 8) +// a := a_8 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/function.yul b/test/libyul/yulOptimizerTests/ssaTransform/function.yul new file mode 100644 index 00000000..995d16cc --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/function.yul @@ -0,0 +1,23 @@ +{ + function f(a, b) -> c, d { + b := add(b, a) + c := add(c, b) + d := add(d, c) + a := add(a, d) + } +} +// ---- +// ssaTransform +// { +// function f(a, b) -> c, d +// { +// let b_1 := add(b, a) +// b := b_1 +// let c_2 := add(c, b_1) +// c := c_2 +// let d_3 := add(d, c_2) +// d := d_3 +// let a_4 := add(a, d_3) +// a := a_4 +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/nested.yul b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul new file mode 100644 index 00000000..49a76953 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul @@ -0,0 +1,32 @@ +{ + let a := 1 + a := 2 + let b := 3 + b := 4 + { + // b is not reassigned here + a := 3 + a := 4 + } + a := add(b, a) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// a := a_2 +// let b_3 := 3 +// let b := b_3 +// let b_4 := 4 +// b := b_4 +// { +// let a_5 := 3 +// a := a_5 +// let a_6 := 4 +// a := a_6 +// } +// let a_7 := add(b_4, a) +// a := a_7 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul b/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul new file mode 100644 index 00000000..297905c6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/notransform.yul @@ -0,0 +1,19 @@ +{ + let a := 1 + // this should not be transformed + let b := add(a, 2) + let c + mstore(c, 0) + c := add(a, b) +} +// ---- +// ssaTransform +// { +// let a := 1 +// let b := add(a, 2) +// let c_1 +// let c := c_1 +// mstore(c_1, 0) +// let c_2 := add(a, b) +// c := c_2 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/simple.yul b/test/libyul/yulOptimizerTests/ssaTransform/simple.yul new file mode 100644 index 00000000..6dbce729 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/simple.yul @@ -0,0 +1,18 @@ +{ + let a := 1 + a := 2 + a := 3 + a := 4 +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// let a_2 := 2 +// a := a_2 +// let a_3 := 3 +// a := a_3 +// let a_4 := 4 +// a := a_4 +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/switch.yul b/test/libyul/yulOptimizerTests/ssaTransform/switch.yul new file mode 100644 index 00000000..bc9b55bb --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/switch.yul @@ -0,0 +1,26 @@ +{ + let a := mload(0) + // This could be more efficient: + // all cases could use the value of the variable from just before + // the switch and not just the first + switch a + case 0 { a := add(a, 4) } + default { a := add(a, 8) } + mstore(0, a) +} +// ---- +// ssaTransform +// { +// let a_1 := mload(0) +// let a := a_1 +// switch a_1 +// case 0 { +// let a_2 := add(a_1, 4) +// a := a_2 +// } +// default { +// let a_3 := add(a, 8) +// a := a_3 +// } +// mstore(0, a) +// } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/used.yul b/test/libyul/yulOptimizerTests/ssaTransform/used.yul new file mode 100644 index 00000000..ad686ca1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaTransform/used.yul @@ -0,0 +1,39 @@ +{ + let a := 1 + mstore(a, 0) + a := 2 + mstore(a, 0) + { + mstore(a, 0) + a := 3 + mstore(a, 0) + a := 4 + mstore(a, 0) + } + mstore(a, 0) + a := 4 + mstore(a, 0) +} +// ---- +// ssaTransform +// { +// let a_1 := 1 +// let a := a_1 +// mstore(a_1, 0) +// let a_2 := 2 +// a := a_2 +// mstore(a_2, 0) +// { +// mstore(a_2, 0) +// let a_3 := 3 +// a := a_3 +// mstore(a_3, 0) +// let a_4 := 4 +// a := a_4 +// mstore(a_4, 0) +// } +// mstore(a, 0) +// let a_5 := 4 +// a := a_5 +// mstore(a_5, 0) +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/functions.yul b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul new file mode 100644 index 00000000..ec9cdda8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/functions.yul @@ -0,0 +1,8 @@ +{ + function f() { let a := 1 } + function g() { f() } +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul new file mode 100644 index 00000000..4ed6dd2c --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_assignment.yul @@ -0,0 +1,11 @@ +{ + let a := 1 + a := 4 + let b := 1 +} +// ---- +// unusedPruner +// { +// let a := 1 +// a := 4 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul new file mode 100644 index 00000000..94d101e9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul @@ -0,0 +1,16 @@ +{ + let a, b + function f() -> x { } + a := f() + b := 1 +} +// ---- +// unusedPruner +// { +// let a, b +// function f() -> x +// { +// } +// a := f() +// b := 1 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul new file mode 100644 index 00000000..a14dc28c --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assign.yul @@ -0,0 +1,16 @@ +{ + let a + let b + function f() -> x, y { } + a, b := f() +} +// ---- +// unusedPruner +// { +// let a +// let b +// function f() -> x, y +// { +// } +// a, b := f() +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul new file mode 100644 index 00000000..fe94edb8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_assignments.yul @@ -0,0 +1,12 @@ +{ + let x, y + x := 1 + y := 2 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// y := 2 +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul new file mode 100644 index 00000000..3cf35007 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declarations.yul @@ -0,0 +1,7 @@ +{ + let x, y +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul new file mode 100644 index 00000000..adabac87 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_declare.yul @@ -0,0 +1,12 @@ +{ + function f() -> x, y { } + let a, b := f() +} +// ---- +// unusedPruner +// { +// function f() -> x, y +// { +// } +// let a, b := f() +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul new file mode 100644 index 00000000..5db0ade9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul @@ -0,0 +1,10 @@ +{ + let x, y + x := 1 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// } 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 +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul new file mode 100644 index 00000000..ca2ed942 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// unusedPruner +// { +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul new file mode 100644 index 00000000..9b4cf9fd --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := 1 + let b := 1 + mstore(0, 1) +} +// ---- +// unusedPruner +// { +// mstore(0, 1) +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul new file mode 100644 index 00000000..54fea2fb --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul @@ -0,0 +1,17 @@ +{ + 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 new file mode 100644 index 00000000..ed8d33b4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul @@ -0,0 +1,13 @@ +{ + 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 new file mode 100644 index 00000000..ca921500 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul @@ -0,0 +1,11 @@ +{ + 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 new file mode 100644 index 00000000..3affcac6 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul @@ -0,0 +1,10 @@ +{ + 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 new file mode 100644 index 00000000..d8959040 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul @@ -0,0 +1,9 @@ +{ + 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 new file mode 100644 index 00000000..e8c91e10 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul @@ -0,0 +1,11 @@ +{ + 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 new file mode 100644 index 00000000..5312112a --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul @@ -0,0 +1,12 @@ +{ + 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 new file mode 100644 index 00000000..e27785dd --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul @@ -0,0 +1,16 @@ +{ + function f(x) {} + let a + f(a) + a := 4 +} +// ---- +// varDeclPropagator +// { +// function f(x) +// { +// } +// let a +// f(a) +// a := 4 +// } |
