diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index fa9aac9ce..c10aa83aa 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -40,6 +40,17 @@ void ExpressionJoiner::run(OptimiserStepContext&, Block& _ast) ExpressionJoiner{_ast}(_ast); } +void ExpressionJoiner::runUntilStabilized(OptimiserStepContext&, Block& _ast) +{ + while (true) + { + ExpressionJoiner expressionJoiner{_ast}; + expressionJoiner(_ast); + if (!expressionJoiner.m_expressionWasJoined) + break; + } +} + void ExpressionJoiner::operator()(FunctionCall& _funCall) { @@ -74,6 +85,7 @@ void ExpressionJoiner::visit(Expression& _e) *latestStatement() = Block(); decrementLatestStatementPointer(); + m_expressionWasJoined = true; } } else diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index db3217de0..014ab011f 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -74,6 +74,7 @@ class ExpressionJoiner: public ASTModifier public: static constexpr char const* name{"ExpressionJoiner"}; static void run(OptimiserStepContext&, Block& _ast); + static void runUntilStabilized(OptimiserStepContext&, Block& _ast); private: explicit ExpressionJoiner(Block& _ast); @@ -92,9 +93,10 @@ private: bool isLatestStatementVarDeclJoinable(Identifier const& _identifier); private: - Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. + Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. size_t m_latestStatementInBlock = 0; ///< Offset to m_currentBlock's statements of the last visited statement. std::map m_references; ///< Holds reference counts to all variable declarations in current block. + bool m_expressionWasJoined = false; ///< True, if any expression was joined during the visit. }; }