mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #5355 from ethereum/yul-forloop-pre-rewrite
[Yul] Implements a pass to rewrite for-loop's pre block into the parent's Block
This commit is contained in:
		
						commit
						8e98885c53
					
				
							
								
								
									
										43
									
								
								libyul/optimiser/ForLoopInitRewriter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libyul/optimiser/ForLoopInitRewriter.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
/*
 | 
			
		||||
	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 <libyul/optimiser/ForLoopInitRewriter.h>
 | 
			
		||||
#include <libsolidity/inlineasm/AsmData.h>
 | 
			
		||||
#include <libdevcore/CommonData.h>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace dev;
 | 
			
		||||
using namespace dev::yul;
 | 
			
		||||
 | 
			
		||||
void ForLoopInitRewriter::operator()(Block& _block)
 | 
			
		||||
{
 | 
			
		||||
	iterateReplacing(
 | 
			
		||||
		_block.statements,
 | 
			
		||||
		[](Statement& _stmt) -> boost::optional<vector<Statement>>
 | 
			
		||||
		{
 | 
			
		||||
			if (_stmt.type() == typeid(ForLoop))
 | 
			
		||||
			{
 | 
			
		||||
				auto& forLoop = boost::get<ForLoop>(_stmt);
 | 
			
		||||
				vector<Statement> rewrite;
 | 
			
		||||
				swap(rewrite, forLoop.pre.statements);
 | 
			
		||||
				rewrite.emplace_back(move(forLoop));
 | 
			
		||||
				return rewrite;
 | 
			
		||||
			}
 | 
			
		||||
			return {};
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								libyul/optimiser/ForLoopInitRewriter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								libyul/optimiser/ForLoopInitRewriter.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
	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 <libyul/optimiser/ASTWalker.h>
 | 
			
		||||
 | 
			
		||||
namespace dev
 | 
			
		||||
{
 | 
			
		||||
namespace yul
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Rewrites ForLoop by moving the pre statement block in front of the ForLoop.
 | 
			
		||||
 * Requirements:
 | 
			
		||||
 * - The Disambiguator must be run upfront.
 | 
			
		||||
 */
 | 
			
		||||
class ForLoopInitRewriter: public ASTModifier
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	using ASTModifier::operator();
 | 
			
		||||
	void operator()(Block& _block) override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@ -27,6 +27,7 @@
 | 
			
		||||
#include <libyul/optimiser/ExpressionJoiner.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionInliner.h>
 | 
			
		||||
#include <libyul/optimiser/FullInliner.h>
 | 
			
		||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
 | 
			
		||||
#include <libyul/optimiser/Rematerialiser.h>
 | 
			
		||||
#include <libyul/optimiser/UnusedPruner.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionSimplifier.h>
 | 
			
		||||
@ -58,6 +59,7 @@ void OptimiserSuite::run(
 | 
			
		||||
 | 
			
		||||
	(FunctionHoister{})(ast);
 | 
			
		||||
	(FunctionGrouper{})(ast);
 | 
			
		||||
	(ForLoopInitRewriter{})(ast);
 | 
			
		||||
 | 
			
		||||
	NameDispenser dispenser{ast};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@
 | 
			
		||||
#include <libyul/optimiser/FunctionHoister.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionInliner.h>
 | 
			
		||||
#include <libyul/optimiser/FullInliner.h>
 | 
			
		||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
 | 
			
		||||
#include <libyul/optimiser/MainFunction.h>
 | 
			
		||||
#include <libyul/optimiser/Rematerialiser.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionSimplifier.h>
 | 
			
		||||
@ -108,6 +109,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
 | 
			
		||||
		disambiguate();
 | 
			
		||||
		VarDeclPropagator{}(*m_ast);
 | 
			
		||||
	}
 | 
			
		||||
	else if (m_optimizerStep == "forLoopInitRewriter")
 | 
			
		||||
	{
 | 
			
		||||
		disambiguate();
 | 
			
		||||
		ForLoopInitRewriter{}(*m_ast);
 | 
			
		||||
	}
 | 
			
		||||
	else if (m_optimizerStep == "commonSubexpressionEliminator")
 | 
			
		||||
	{
 | 
			
		||||
		disambiguate();
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
{
 | 
			
		||||
  let random := 42
 | 
			
		||||
  for { let a := 1
 | 
			
		||||
	    let b := 1 } iszero(eq(a, 10)) { a := add(a, b) } {
 | 
			
		||||
    a := add(a, 1)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
// ----
 | 
			
		||||
// forLoopInitRewriter
 | 
			
		||||
// {
 | 
			
		||||
//     let random := 42
 | 
			
		||||
//     let a := 1
 | 
			
		||||
//     let b := 1
 | 
			
		||||
//     for {
 | 
			
		||||
//     }
 | 
			
		||||
//     iszero(eq(a, 10))
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, b)
 | 
			
		||||
//     }
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, 1)
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  let a := 1
 | 
			
		||||
  for {} iszero(eq(a, 10)) { a := add(a, 1) } {
 | 
			
		||||
    a := add(a, 1)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
// ----
 | 
			
		||||
// forLoopInitRewriter
 | 
			
		||||
// {
 | 
			
		||||
//     let a := 1
 | 
			
		||||
//     for {
 | 
			
		||||
//     }
 | 
			
		||||
//     iszero(eq(a, 10))
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, 1)
 | 
			
		||||
//     }
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, 1)
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
							
								
								
									
										21
									
								
								test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
{
 | 
			
		||||
  let random := 42
 | 
			
		||||
  for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } {
 | 
			
		||||
    a := add(a, 1)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
// ----
 | 
			
		||||
// forLoopInitRewriter
 | 
			
		||||
// {
 | 
			
		||||
//     let random := 42
 | 
			
		||||
//     let a := 1
 | 
			
		||||
//     for {
 | 
			
		||||
//     }
 | 
			
		||||
//     iszero(eq(a, 10))
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, 1)
 | 
			
		||||
//     }
 | 
			
		||||
//     {
 | 
			
		||||
//         a := add(a, 1)
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
@ -38,6 +38,7 @@
 | 
			
		||||
#include <libyul/optimiser/FunctionHoister.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionInliner.h>
 | 
			
		||||
#include <libyul/optimiser/FullInliner.h>
 | 
			
		||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
 | 
			
		||||
#include <libyul/optimiser/MainFunction.h>
 | 
			
		||||
#include <libyul/optimiser/Rematerialiser.h>
 | 
			
		||||
#include <libyul/optimiser/ExpressionSimplifier.h>
 | 
			
		||||
@ -123,7 +124,7 @@ public:
 | 
			
		||||
			}
 | 
			
		||||
			cout << "(q)quit/(f)flatten/(c)se/propagate var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl;
 | 
			
		||||
			cout << "  (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl;
 | 
			
		||||
			cout << "  (r)edundant assign elim./re(m)aterializer? ";
 | 
			
		||||
			cout << "  (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter? ";
 | 
			
		||||
			cout.flush();
 | 
			
		||||
			int option = readStandardInputChar();
 | 
			
		||||
			cout << ' ' << char(option) << endl;
 | 
			
		||||
@ -134,6 +135,9 @@ public:
 | 
			
		||||
			case 'f':
 | 
			
		||||
				BlockFlattener{}(*m_ast);
 | 
			
		||||
				break;
 | 
			
		||||
			case 'o':
 | 
			
		||||
				ForLoopInitRewriter{}(*m_ast);
 | 
			
		||||
				break;
 | 
			
		||||
			case 'c':
 | 
			
		||||
				(CommonSubexpressionEliminator{})(*m_ast);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user