diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 346d8267f..ffd91bf92 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -132,13 +132,18 @@ void eliminateVariables(shared_ptr const& _dialect, ASTNode& _node, siz } -bool StackCompressor::run(shared_ptr const& _dialect, Block& _ast, bool _optimizeStackAllocation) +bool StackCompressor::run( + shared_ptr const& _dialect, + Block& _ast, + bool _optimizeStackAllocation, + size_t _maxIterations +) { yulAssert( _ast.statements.size() > 0 && _ast.statements.at(0).type() == typeid(Block), "Need to run the function grouper before the stack compressor." ); - for (size_t iterations = 0; iterations < 6; iterations++) + for (size_t iterations = 0; iterations < _maxIterations; iterations++) { map stackSurplus = CompilabilityChecker::run(_dialect, _ast, _optimizeStackAllocation); if (stackSurplus.empty()) diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index a6f20b8b4..45240fc6d 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -41,7 +41,12 @@ class StackCompressor public: /// Try to remove local variables until the AST is compilable. /// @returns true if it was successful. - static bool run(std::shared_ptr const& _dialect, Block& _ast, bool _optimizeStackAllocation); + static bool run( + std::shared_ptr const& _dialect, + Block& _ast, + bool _optimizeStackAllocation, + size_t _maxIterations + ); }; } diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index c30987ed5..91ac3f3a7 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -185,8 +185,12 @@ void OptimiserSuite::run( Rematerialiser::run(*_dialect, ast); UnusedPruner::runUntilStabilised(*_dialect, ast, reservedIdentifiers); + // This is a tuning parameter, but actually just prevents infinite loops. + size_t stackCompressorMaxIterations = 16; FunctionGrouper{}(ast); - solAssert(StackCompressor::run(_dialect, ast, _optimizeStackAllocation), ""); + // We ignore the return value because we will get a much better error + // message once we perform code generation. + StackCompressor::run(_dialect, ast, _optimizeStackAllocation, stackCompressorMaxIterations); BlockFlattener{}(ast); VarNameCleaner{ast, *_dialect, reservedIdentifiers}(ast); diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index c0c873699..7d05ea9f5 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -247,7 +247,8 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con { disambiguate(); (FunctionGrouper{})(*m_ast); - StackCompressor::run(m_dialect, *m_ast, true); + size_t maxIterations = 16; + StackCompressor::run(m_dialect, *m_ast, true, maxIterations); (BlockFlattener{})(*m_ast); } else if (m_optimizerStep == "fullSuite") diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 80de0fac7..14ac0e950 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -198,7 +198,7 @@ public: SSAReverser::run(*m_ast); break; case 'p': - StackCompressor::run(m_dialect, *m_ast, true); + StackCompressor::run(m_dialect, *m_ast, true, 16); break; default: cout << "Unknown option." << endl;