diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f7adf16a9..efdc3e7bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -137,6 +137,8 @@ set(libyul_sources libyul/YulInterpreterTest.h libyul/YulOptimizerTest.cpp libyul/YulOptimizerTest.h + libyul/YulOptimizerTestCommon.cpp + libyul/YulOptimizerTestCommon.h ) detect_stray_source_files("${libyul_sources}" "libyul/") diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9a8a32836..027f6a0a8 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -17,76 +17,21 @@ // SPDX-License-Identifier: GPL-3.0 #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include - -#include -#include - #include -#include using namespace solidity; using namespace solidity::util; @@ -128,312 +73,10 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line soltestAssert(m_dialect, "Dialect not set."); - updateContext(); + m_object->analysisInfo = m_analysisInfo; + YulOptimizerTestCommon tester(m_object, *m_dialect, m_optimizerStep); - if (m_optimizerStep == "disambiguator") - disambiguate(); - else if (m_optimizerStep == "nameDisplacer") - { - disambiguate(); - NameDisplacer{ - *m_nameDispenser, - {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} - }(*m_object->code); - } - else if (m_optimizerStep == "blockFlattener") - { - disambiguate(); - BlockFlattener::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "constantOptimiser") - { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); - ConstantOptimiser{dynamic_cast(*m_dialect), meter}(*m_object->code); - } - else if (m_optimizerStep == "varDeclInitializer") - VarDeclInitializer::run(*m_context, *m_object->code); - else if (m_optimizerStep == "varNameCleaner") - { - disambiguate(); - FunctionGrouper::run(*m_context, *m_object->code); - VarNameCleaner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "forLoopConditionIntoBody") - { - disambiguate(); - ForLoopConditionIntoBody::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "forLoopInitRewriter") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "commonSubexpressionEliminator") - { - disambiguate(); - CommonSubexpressionEliminator::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "conditionalUnsimplifier") - { - disambiguate(); - ConditionalUnsimplifier::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "conditionalSimplifier") - { - disambiguate(); - ConditionalSimplifier::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "expressionSplitter") - ExpressionSplitter::run(*m_context, *m_object->code); - else if (m_optimizerStep == "expressionJoiner") - { - disambiguate(); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "splitJoin") - { - disambiguate(); - ExpressionSplitter::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "functionGrouper") - { - disambiguate(); - FunctionGrouper::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "functionHoister") - { - disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "expressionInliner") - { - disambiguate(); - ExpressionInliner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "fullInliner") - { - disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - FunctionGrouper::run(*m_context, *m_object->code); - ExpressionSplitter::run(*m_context, *m_object->code); - FullInliner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "mainFunction") - { - disambiguate(); - FunctionGrouper::run(*m_context, *m_object->code); - MainFunction::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "rematerialiser") - { - disambiguate(); - Rematerialiser::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "expressionSimplifier") - { - disambiguate(); - ExpressionSplitter::run(*m_context, *m_object->code); - CommonSubexpressionEliminator::run(*m_context, *m_object->code); - ExpressionSimplifier::run(*m_context, *m_object->code); - ExpressionSimplifier::run(*m_context, *m_object->code); - ExpressionSimplifier::run(*m_context, *m_object->code); - UnusedPruner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "fullSimplify") - { - disambiguate(); - ExpressionSplitter::run(*m_context, *m_object->code); - ForLoopInitRewriter::run(*m_context, *m_object->code); - CommonSubexpressionEliminator::run(*m_context, *m_object->code); - ExpressionSimplifier::run(*m_context, *m_object->code); - UnusedPruner::run(*m_context, *m_object->code); - CircularReferencesPruner::run(*m_context, *m_object->code); - DeadCodeEliminator::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "unusedFunctionParameterPruner") - { - disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - LiteralRematerialiser::run(*m_context, *m_object->code); - UnusedFunctionParameterPruner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "unusedPruner") - { - disambiguate(); - UnusedPruner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "circularReferencesPruner") - { - disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - CircularReferencesPruner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "deadCodeEliminator") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - DeadCodeEliminator::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "ssaTransform") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - SSATransform::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "redundantAssignEliminator") - { - disambiguate(); - RedundantAssignEliminator::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "ssaPlusCleanup") - { - disambiguate(); - SSATransform::run(*m_context, *m_object->code); - RedundantAssignEliminator::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "loadResolver") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - ExpressionSplitter::run(*m_context, *m_object->code); - CommonSubexpressionEliminator::run(*m_context, *m_object->code); - ExpressionSimplifier::run(*m_context, *m_object->code); - - LoadResolver::run(*m_context, *m_object->code); - - UnusedPruner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - ExpressionJoiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "loopInvariantCodeMotion") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - LoopInvariantCodeMotion::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "controlFlowSimplifier") - { - disambiguate(); - ControlFlowSimplifier::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "structuralSimplifier") - { - disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_object->code); - LiteralRematerialiser::run(*m_context, *m_object->code); - StructuralSimplifier::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "reasoningBasedSimplifier") - { - disambiguate(); - ReasoningBasedSimplifier::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "equivalentFunctionCombiner") - { - disambiguate(); - EquivalentFunctionCombiner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "ssaReverser") - { - disambiguate(); - SSAReverser::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "ssaAndBack") - { - disambiguate(); - // apply SSA - SSATransform::run(*m_context, *m_object->code); - RedundantAssignEliminator::run(*m_context, *m_object->code); - // reverse SSA - SSAReverser::run(*m_context, *m_object->code); - CommonSubexpressionEliminator::run(*m_context, *m_object->code); - UnusedPruner::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "stackCompressor") - { - disambiguate(); - FunctionGrouper::run(*m_context, *m_object->code); - size_t maxIterations = 16; - Object obj; - obj.code = m_object->code; - StackCompressor::run(*m_dialect, obj, true, maxIterations); - m_object->code = obj.code; - BlockFlattener::run(*m_context, *m_object->code); - } - else if (m_optimizerStep == "wordSizeTransform") - { - disambiguate(); - ExpressionSplitter::run(*m_context, *m_object->code); - WordSizeTransform::run(*m_dialect, *m_dialect, *m_object->code, *m_nameDispenser); - } - else if (m_optimizerStep == "fullSuite") - { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); - yul::Object obj; - obj.code = m_object->code; - obj.analysisInfo = m_analysisInfo; - OptimiserSuite::run(*m_dialect, &meter, obj, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); - } - else if (m_optimizerStep == "stackLimitEvader") - { - yul::Object obj; - obj.code = m_object->code; - obj.analysisInfo = m_analysisInfo; - disambiguate(); - StackLimitEvader::run(*m_context, obj, CompilabilityChecker{ - *m_dialect, - obj, - true - }.unreachableVariables); - } - else if (m_optimizerStep == "fakeStackLimitEvader") - { - yul::Object obj; - obj.code = m_object->code; - obj.analysisInfo = m_analysisInfo; - disambiguate(); - // Mark all variables with a name starting with "$" for escalation to memory. - struct FakeUnreachableGenerator: ASTWalker - { - map> fakeUnreachables; - using ASTWalker::operator(); - void operator()(FunctionDefinition const& _function) override - { - YulString originalFunctionName = m_currentFunction; - m_currentFunction = _function.name; - ASTWalker::operator()(_function); - m_currentFunction = originalFunctionName; - } - void visitVariableName(YulString _var) - { - if (!_var.empty() && _var.str().front() == '$') - fakeUnreachables[m_currentFunction].insert(_var); - } - void operator()(VariableDeclaration const& _varDecl) override - { - for (auto const& var: _varDecl.variables) - visitVariableName(var.name); - ASTWalker::operator()(_varDecl); - } - void operator()(Identifier const& _identifier) override - { - visitVariableName(_identifier.name); - ASTWalker::operator()(_identifier); - } - YulString m_currentFunction = YulString{}; - }; - FakeUnreachableGenerator fakeUnreachableGenerator; - fakeUnreachableGenerator(*obj.code); - StackLimitEvader::run(*m_context, obj, fakeUnreachableGenerator.fakeUnreachables); - } - else + if (!tester.runStep()) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; return TestResult::FatalError; @@ -477,23 +120,6 @@ std::pair, std::shared_ptr> YulOptimize return {std::move(object), std::move(analysisInfo)}; } -void YulOptimizerTest::disambiguate() -{ - *m_object->code = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(*m_object->code)); - m_analysisInfo.reset(); - updateContext(); -} - -void YulOptimizerTest::updateContext() -{ - m_nameDispenser = make_unique(*m_dialect, *m_object->code, m_reservedIdentifiers); - m_context = make_unique(OptimiserStepContext{ - *m_dialect, - *m_nameDispenser, - m_reservedIdentifiers - }); -} - void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors) { SourceReferenceFormatter formatter(_stream, true, false); diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 6baeca728..b4ba4ca7a 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -20,17 +20,8 @@ #include -#include -#include - -#include - -#include -#include - namespace solidity::langutil { -class Scanner; class Error; using ErrorList = std::vector>; } @@ -56,22 +47,15 @@ public: explicit YulOptimizerTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; - private: std::pair, std::shared_ptr> parse( std::ostream& _stream, std::string const& _linePrefix, bool const _formatted, std::string const& _source ); - void disambiguate(); - void updateContext(); - static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors); std::string m_optimizerStep; Dialect const* m_dialect = nullptr; - std::set m_reservedIdentifiers; - std::unique_ptr m_nameDispenser; - std::unique_ptr m_context; std::shared_ptr m_object; std::shared_ptr m_analysisInfo; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp new file mode 100644 index 000000000..1f3bfd2eb --- /dev/null +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -0,0 +1,434 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace solidity; +using namespace solidity::util; +using namespace solidity::langutil; +using namespace solidity::yul; +using namespace solidity::yul::test; +using namespace solidity::frontend; +using namespace std; + +YulOptimizerTestCommon::YulOptimizerTestCommon( + shared_ptr _obj, + Dialect const& _dialect, + string const& _optimizerStep +) +{ + m_object = _obj; + m_ast = m_object->code; + m_analysisInfo = m_object->analysisInfo; + m_dialect = &_dialect; + m_optimizerStep = _optimizerStep; +} + +bool YulOptimizerTestCommon::runStep() +{ + yulAssert(m_dialect, "Dialect not set."); + + updateContext(); + + if (m_optimizerStep == "disambiguator") + disambiguate(); + else if (m_optimizerStep == "nameDisplacer") + { + disambiguate(); + NameDisplacer{ + *m_nameDispenser, + {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} + }(*m_ast); + } + else if (m_optimizerStep == "blockFlattener") + { + disambiguate(); + BlockFlattener::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "constantOptimiser") + { + GasMeter meter(dynamic_cast(*m_dialect), false, 200); + ConstantOptimiser{dynamic_cast(*m_dialect), meter}(*m_ast); + } + else if (m_optimizerStep == "varDeclInitializer") + VarDeclInitializer::run(*m_context, *m_ast); + else if (m_optimizerStep == "varNameCleaner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, *m_ast); + VarNameCleaner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "forLoopConditionIntoBody") + { + disambiguate(); + ForLoopConditionIntoBody::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "forLoopInitRewriter") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "commonSubexpressionEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "conditionalUnsimplifier") + { + disambiguate(); + ConditionalUnsimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "conditionalSimplifier") + { + disambiguate(); + ConditionalSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionSplitter") + ExpressionSplitter::run(*m_context, *m_ast); + else if (m_optimizerStep == "expressionJoiner") + { + disambiguate(); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "splitJoin") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "functionGrouper") + { + disambiguate(); + FunctionGrouper::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "functionHoister") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionInliner") + { + disambiguate(); + ExpressionInliner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "fullInliner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, *m_ast); + ExpressionSplitter::run(*m_context, *m_ast); + FullInliner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "mainFunction") + { + disambiguate(); + FunctionGrouper::run(*m_context, *m_ast); + MainFunction::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "rematerialiser") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + Rematerialiser::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "expressionSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + ExpressionSplitter::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "fullSimplify") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, *m_ast); + CircularReferencesPruner::run(*m_context, *m_ast); + DeadCodeEliminator::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "unusedFunctionParameterPruner") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_object->code); + LiteralRematerialiser::run(*m_context, *m_object->code); + UnusedFunctionParameterPruner::run(*m_context, *m_object->code); + } + else if (m_optimizerStep == "unusedPruner") + { + disambiguate(); + UnusedPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "circularReferencesPruner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_ast); + CircularReferencesPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "deadCodeEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + DeadCodeEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaTransform") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + SSATransform::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "redundantAssignEliminator") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaPlusCleanup") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + SSATransform::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "loadResolver") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + ExpressionSplitter::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + ExpressionSimplifier::run(*m_context, *m_ast); + + LoadResolver::run(*m_context, *m_ast); + + UnusedPruner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + ExpressionJoiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "loopInvariantCodeMotion") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + LoopInvariantCodeMotion::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "controlFlowSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + ControlFlowSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "structuralSimplifier") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + LiteralRematerialiser::run(*m_context, *m_ast); + StructuralSimplifier::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "reasoningBasedSimplifier") + { + disambiguate(); + ReasoningBasedSimplifier::run(*m_context, *m_object->code); + } + else if (m_optimizerStep == "equivalentFunctionCombiner") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + EquivalentFunctionCombiner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaReverser") + { + disambiguate(); + SSAReverser::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "ssaAndBack") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + // apply SSA + SSATransform::run(*m_context, *m_ast); + RedundantAssignEliminator::run(*m_context, *m_ast); + // reverse SSA + SSAReverser::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + CommonSubexpressionEliminator::run(*m_context, *m_ast); + UnusedPruner::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "stackCompressor") + { + disambiguate(); + ForLoopInitRewriter::run(*m_context, *m_ast); + FunctionHoister::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, *m_ast); + size_t maxIterations = 16; + StackCompressor::run(*m_dialect, *m_object, true, maxIterations); + BlockFlattener::run(*m_context, *m_ast); + } + else if (m_optimizerStep == "wordSizeTransform") + { + disambiguate(); + ExpressionSplitter::run(*m_context, *m_ast); + WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser); + } + else if (m_optimizerStep == "fullSuite") + { + GasMeter meter(dynamic_cast(*m_dialect), false, 200); + OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); + } + else if (m_optimizerStep == "stackLimitEvader") + { + disambiguate(); + StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ + *m_dialect, + *m_object, + true + }.unreachableVariables); + } + else if (m_optimizerStep == "fakeStackLimitEvader") + { + disambiguate(); + // Mark all variables with a name starting with "$" for escalation to memory. + struct FakeUnreachableGenerator: ASTWalker + { + map> fakeUnreachables; + using ASTWalker::operator(); + void operator()(FunctionDefinition const& _function) override + { + YulString originalFunctionName = m_currentFunction; + m_currentFunction = _function.name; + ASTWalker::operator()(_function); + m_currentFunction = originalFunctionName; + } + void visitVariableName(YulString _var) + { + if (!_var.empty() && _var.str().front() == '$') + fakeUnreachables[m_currentFunction].insert(_var); + } + void operator()(VariableDeclaration const& _varDecl) override + { + for (auto const& var: _varDecl.variables) + visitVariableName(var.name); + ASTWalker::operator()(_varDecl); + } + void operator()(Identifier const& _identifier) override + { + visitVariableName(_identifier.name); + ASTWalker::operator()(_identifier); + } + YulString m_currentFunction = YulString{}; + }; + FakeUnreachableGenerator fakeUnreachableGenerator; + fakeUnreachableGenerator(*m_ast); + StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); + } + else + return false; + + return true; +} + +shared_ptr YulOptimizerTestCommon::run() +{ + return runStep() ? m_ast : nullptr; +} + +void YulOptimizerTestCommon::disambiguate() +{ + *m_object->code = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(*m_object->code)); + m_analysisInfo.reset(); + updateContext(); +} + +void YulOptimizerTestCommon::updateContext() +{ + m_nameDispenser = make_unique(*m_dialect, *m_object->code, m_reservedIdentifiers); + m_context = make_unique(OptimiserStepContext{ + *m_dialect, + *m_nameDispenser, + m_reservedIdentifiers + }); +} diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h new file mode 100644 index 000000000..cb24e1a64 --- /dev/null +++ b/test/libyul/YulOptimizerTestCommon.h @@ -0,0 +1,68 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include + +#include + +#include +#include + +namespace solidity::yul +{ + struct AsmAnalysisInfo; + struct Object; + struct Dialect; +} + +namespace solidity::yul::test +{ +class YulOptimizerTestCommon +{ +public: + explicit YulOptimizerTestCommon( + std::shared_ptr _obj, + Dialect const& _dialect, + std::string const& _optimizerStep + ); + /// Runs chosen optimiser step returning pointer + /// to yul AST Block post optimisation. + std::shared_ptr run(); + /// Runs chosen optimiser step returning true if + /// successful, false otherwise. + bool runStep(); +private: + void disambiguate(); + void updateContext(); + + std::string m_optimizerStep; + + Dialect const* m_dialect = nullptr; + std::set m_reservedIdentifiers; + std::unique_ptr m_nameDispenser; + std::unique_ptr m_context; + + std::shared_ptr m_object; + std::shared_ptr m_ast; + std::shared_ptr m_analysisInfo; +}; + +} diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul index 1fd8f84f1..2fd765afc 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/function_scopes.yul @@ -27,6 +27,15 @@ // step: commonSubexpressionEliminator // // { +// 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) // function allocate(size) -> p // { // let _1 := 0x40 @@ -41,13 +50,4 @@ // 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/movable_functions.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul index ac0fa0f52..d6041eb5e 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul @@ -11,6 +11,11 @@ // step: commonSubexpressionEliminator // // { +// let i := mload(3) +// let a := double(i) +// let b := a +// let c := double_with_se(i) +// let d := double_with_se(i) // function double(x) -> y // { y := add(x, x) } // function double_with_se(x_1) -> y_2 @@ -18,9 +23,4 @@ // y_2 := add(x_1, x_1) // mstore(40, 4) // } -// let i := mload(3) -// let a := double(i) -// let b := a -// let c := double_with_se(i) -// let d := double_with_se(i) // } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul index 46bf80eb7..bdb54d955 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul @@ -13,12 +13,12 @@ // step: commonSubexpressionEliminator // // { +// let a +// let b := a +// sstore(a, a) // function f() -> x // { // let y := x // mstore(x, 7) // } -// let a -// let b := a -// sstore(a, a) // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul index 595b9c792..b73742ced 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul @@ -8,8 +8,8 @@ // step: expressionSimplifier // // { -// function f() -> x, z -// { } // let c, d := f() // sstore(add(add(d, c), 7), 20) +// function f() -> x, z +// { } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul index a035494b8..8ebb9e51d 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/including_function_calls.yul @@ -7,7 +7,7 @@ // step: expressionSimplifier // // { +// sstore(0, f()) // function f() -> a // { } -// sstore(0, f()) // } 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 index ccb490892..eca9021ea 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -7,9 +7,9 @@ // step: expressionSimplifier // // { -// function f(a) -> b -// { } // let _2 := f(1) // let _3 := 0 // sstore(_3, sub(f(_3), _2)) +// function f(a) -> b +// { } // } 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 index 7f44c2208..ed439b62f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul @@ -8,9 +8,9 @@ // step: expressionSimplifier // // { +// sstore(0, sub(f1(), f2())) // function f1() -> a // { } // function f2() -> b // { } -// sstore(0, 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 index 6ed704aea..2de7b4a67 100644 --- 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 @@ -8,7 +8,7 @@ // step: expressionSimplifier // // { +// sstore(sub(f(), f()), 8) // function f() -> a // { mstore(a, 1) } -// sstore(sub(f(), f()), 8) // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul index 0d9513ec2..002d8f28e 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/pop_byte_shr_func.yul @@ -8,8 +8,8 @@ // step: expressionSimplifier // // { -// function f() -> x -// { mstore(x, 1337) } // pop(f()) // mstore(0, 0) +// function f() -> x +// { mstore(x, 1337) } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul index 9b0087dd7..de740fc22 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul @@ -10,7 +10,7 @@ // step: expressionSimplifier // // { +// let t, v := f() // function f() -> c, d // { sstore(d, 7) } -// let t, v := f() // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul index 73bd6c363..090b3cde6 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/including_function_calls.yul @@ -7,7 +7,7 @@ // step: fullSimplify // // { +// mstore(f(), 0) // function f() -> a // { } -// mstore(f(), 0) // } 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 index 8dd271d9f..517bbe442 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul @@ -6,9 +6,9 @@ // step: fullSimplify // // { -// function f(a) -> b -// { } // let _2 := f(1) // let _3 := 0 // mstore(_3, sub(f(_3), _2)) +// function f(a) -> b +// { } // } 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 index 0b17b1e4a..7f8fddf2e 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_names.yul @@ -8,9 +8,9 @@ // step: fullSimplify // // { +// mstore(0, sub(f1(), f2())) // 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 index 3133c69ca..52030fe88 100644 --- 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 @@ -8,7 +8,7 @@ // step: fullSimplify // // { +// mstore(0, sub(f(), f())) // function f() -> a // { mstore(1, 2) } -// mstore(0, sub(f(), f())) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul index 5e5c06553..a8d9e2af0 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul @@ -10,20 +10,20 @@ // step: loadResolver // // { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// foo(42) +// sstore(_2, mload(_2)) // function foo(x) // { // for { } // x // { -// let _1 := 0 -// x := mload(_1) -// mstore(_1, _1) +// let _7 := 0 +// x := mload(_7) +// mstore(_7, _7) // } // { } // } -// let _4 := 1337 -// let _5 := 0 -// mstore(_5, _4) -// foo(42) -// sstore(_5, mload(_5)) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul index da910bace..6fcf7a6aa 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul @@ -15,6 +15,11 @@ // step: loadResolver // // { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// funcWithLoop(42) +// sstore(_2, mload(_2)) // function userNot(x) -> y // { y := iszero(x) } // function funcWithLoop(x_1) @@ -22,14 +27,9 @@ // for { } // userNot(x_1) // { -// let _1 := 0 -// mstore(_1, _1) +// let _7 := 0 +// mstore(_7, _7) // } // { } // } -// let _3 := 1337 -// let _4 := 0 -// mstore(_4, _3) -// funcWithLoop(42) -// sstore(_4, mload(_4)) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul index efef507dc..4794237d6 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul @@ -15,18 +15,18 @@ // step: loadResolver // // { +// let _1 := 1337 +// let _2 := 0 +// mstore(_2, _1) +// funcWithLoop(42) +// sstore(_2, mload(_2)) // function userNot(x) -> y // { y := iszero(x) } // function funcWithLoop(x_1) // { -// let _1 := 0 -// mstore(_1, _1) +// let _7 := 0 +// mstore(_7, _7) // for { } userNot(x_1) { } // { } // } -// let _3 := 1337 -// let _4 := 0 -// mstore(_4, _3) -// funcWithLoop(42) -// sstore(_4, mload(_4)) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul index ec9eec6c9..684e6b94f 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul @@ -12,17 +12,17 @@ // step: loadResolver // // { +// let _1 := 9 +// let _2 := 2 +// mstore(_2, _1) +// reads() +// let _4 := _1 +// let _5 := 0 +// sstore(_5, _4) +// stores() +// sstore(_5, mload(_2)) // function stores() // { mstore(0, 1) } // function reads() // { sstore(9, mload(7)) } -// let _6 := 9 -// let _7 := 2 -// mstore(_7, _6) -// reads() -// let _9 := _6 -// let _10 := 0 -// sstore(_10, _9) -// stores() -// sstore(_10, mload(_7)) // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul index f48cb78f1..412895037 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/create_sload.yul @@ -15,10 +15,6 @@ // step: loopInvariantCodeMotion // // { -// function g() -> x -// { x := create(100, 0, 32) } -// function f() -> x_1 -// { x_1 := mload(0) } // let b := 1 // let a := 1 // let z := f() @@ -27,4 +23,8 @@ // let q := sload(5) // let r := g() // } +// function g() -> x +// { x := create(100, 0, 32) } +// function f() -> x_1 +// { x_1 := mload(0) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_memory_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_memory_function.yul index a4506a8e5..f8c18f5f4 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_memory_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_memory_function.yul @@ -12,8 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function g() -> x -// { x := add(sload(mload(x)), 1) } // let b := 1 // let a := 1 // let t := mload(g()) @@ -21,4 +19,6 @@ // let q := g() // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { } +// function g() -> x +// { x := add(sload(mload(x)), 1) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul index a5117cb61..1d1a14915 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_state_function.yul @@ -12,14 +12,14 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := mload(g()) } -// function g() -> x_1 -// { x_1 := add(sload(x_1), 1) } // let b := 1 // let a := 1 // let t := extcodesize(f()) // let q := g() // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { } +// function f() -> x +// { x := mload(g()) } +// function g() -> x_1 +// { x_1 := add(sload(x_1), 1) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_storage_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_storage_function.yul index 7790c0e6a..230e13d14 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_storage_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/move_storage_function.yul @@ -12,14 +12,14 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { x_1 := add(x_1, 1) } // let b := 1 // let a := 1 // let t := sload(f()) // let q := g() // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { x_1 := add(x_1, 1) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul index b08899613..8881fdc84 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_immovables.yul @@ -14,10 +14,6 @@ // // { // let a := 1 -// function f() -> x -// { invalid() } -// function g() -> y -// { return(0, 0) } // let i := 1 // for { } iszero(eq(i, 10)) { a := add(i, 1) } // { @@ -26,4 +22,8 @@ // let d := g() // let e := sload(g()) // } +// function f() -> x +// { invalid() } +// function g() -> y +// { return(0, 0) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_loop.yul index 19e681d6b..8632e3764 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_loop.yul @@ -12,13 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { -// for { } 1 { } -// { } -// } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -26,4 +19,11 @@ // let t := f() // let q := g() // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { +// for { } 1 { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_loop.yul index 1ebef6f9c..c55762461 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_loop.yul @@ -12,13 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { -// for { } 1 { } -// { } -// } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -26,4 +19,11 @@ // let t := mload(f()) // let q := g() // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { +// for { } 1 { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_recursive_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_recursive_function.yul index 2bb86008e..27193a138 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_recursive_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_recursive_function.yul @@ -12,10 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { x_1 := g() } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -23,4 +19,8 @@ // let t := f() // let q := g() // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { x_1 := g() } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul index ab5be62d9..d3dce8d78 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_function.yul @@ -15,13 +15,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { -// x_1 := add(x_1, 1) -// sstore(0x00, 0x00) -// } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -29,4 +22,11 @@ // let t := extcodesize(f()) // let q := sload(g()) // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { +// x_1 := add(x_1, 1) +// sstore(0x00, 0x00) +// } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul index d7e16ed68..8de9147d8 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_loop.yul @@ -12,13 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { -// for { } 1 { } -// { } -// } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -26,4 +19,11 @@ // let t := extcodesize(f()) // let q := g() // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { +// for { } 1 { } +// { } +// } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul index 431453941..1eb0ccd6d 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state_recursive_function.yul @@ -12,10 +12,6 @@ // step: loopInvariantCodeMotion // // { -// function f() -> x -// { x := g() } -// function g() -> x_1 -// { x_1 := g() } // let b := 1 // let a := 1 // for { } iszero(eq(a, 10)) { a := add(a, 1) } @@ -23,4 +19,8 @@ // let t := extcodesize(f()) // let q := sload(g()) // } +// function f() -> x +// { x := g() } +// function g() -> x_1 +// { x_1 := g() } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_function.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_function.yul index f1a2d6283..210f21f5c 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_function.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_function.yul @@ -14,6 +14,10 @@ // step: loopInvariantCodeMotion // // { +// let b := 1 +// let a := 1 +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { let q := sload(g()) } // function f() -> x // { x := g() } // function g() -> x_1 @@ -21,8 +25,4 @@ // x_1 := add(x_1, 1) // sstore(0x00, 0x00) // } -// let b := 1 -// let a := 1 -// for { } iszero(eq(a, 10)) { a := add(a, 1) } -// { let q := sload(g()) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_loop.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_loop.yul index d799fa6ae..0dc110873 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_loop.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage_loop.yul @@ -11,6 +11,10 @@ // step: loopInvariantCodeMotion // // { +// let b := 1 +// let a := 1 +// for { } iszero(eq(a, 10)) { a := add(a, 1) } +// { let t := sload(f()) } // function f() -> x // { x := g() } // function g() -> x_1 @@ -18,8 +22,4 @@ // for { } 1 { } // { } // } -// let b := 1 -// let a := 1 -// for { } iszero(eq(a, 10)) { a := add(a, 1) } -// { let t := sload(f()) } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/not_first.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/not_first.yul index 2840d3445..a1a2bd645 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/not_first.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/not_first.yul @@ -11,11 +11,11 @@ // step: loopInvariantCodeMotion // // { -// function g() -> x -// { x := add(mload(x), 1) } // let b := 1 // let a := 1 // let q := keccak256(g(), 32) // for { } iszero(eq(a, 10)) { a := add(a, 1) } // { sstore(0, a) } +// function g() -> x +// { x := add(mload(x), 1) } // } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul index 4cffa6a02..0d2d8fdf1 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/non_movable_function.yul @@ -9,10 +9,10 @@ // step: rematerialiser // // { -// function f(x) -> y -// { } // let a := 1 // let b := f(1) // let c := 1 // mstore(add(1, b), 1) +// function f(x) -> y +// { } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul index da8d797b8..56f0278ce 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/ssaReverse.yul @@ -24,6 +24,8 @@ // step: ssaAndBack // // { +// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) +// mstore(a, b) // function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 // { // if iszero(slt(add(offset_12, 0x1f), end_13)) @@ -38,6 +40,4 @@ // arrayPos_14 := add(offset_12, 0x20) // if gt(add(add(offset_12, length_15), 0x20), end_13) { revert(0, 0) } // } -// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) -// mstore(a, b) // } diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index dc0d58bce..edd4eb686 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable(isoltest ../libyul/ObjectCompilerTest.cpp ../libyul/SyntaxTest.cpp ../libyul/YulOptimizerTest.cpp + ../libyul/YulOptimizerTestCommon.cpp ../libyul/YulInterpreterTest.cpp ) target_link_libraries(isoltest PRIVATE evmc libsolc solidity yulInterpreter evmasm Boost::boost Boost::program_options Boost::unit_test_framework)