mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #5620 from ethereum/rematOnlyOne
[Yul] Use rematerializer if variable is only referenced once or value is "cheap".
This commit is contained in:
		
						commit
						3631df5d88
					
				| @ -21,6 +21,9 @@ | |||||||
| #include <libyul/optimiser/Metrics.h> | #include <libyul/optimiser/Metrics.h> | ||||||
| 
 | 
 | ||||||
| #include <libyul/AsmData.h> | #include <libyul/AsmData.h> | ||||||
|  | #include <libyul/Exceptions.h> | ||||||
|  | 
 | ||||||
|  | #include <libevmasm/Instruction.h> | ||||||
| 
 | 
 | ||||||
| using namespace dev; | using namespace dev; | ||||||
| using namespace yul; | using namespace yul; | ||||||
| @ -60,3 +63,64 @@ void CodeSize::visit(Expression const& _expression) | |||||||
| 	++m_size; | 	++m_size; | ||||||
| 	ASTWalker::visit(_expression); | 	ASTWalker::visit(_expression); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | size_t CodeCost::codeCost(Expression const& _expr) | ||||||
|  | { | ||||||
|  | 	CodeCost cc; | ||||||
|  | 	cc.visit(_expr); | ||||||
|  | 	return cc.m_cost; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void CodeCost::operator()(FunctionCall const& _funCall) | ||||||
|  | { | ||||||
|  | 	yulAssert(m_cost >= 1, "Should assign cost one in visit(Expression)."); | ||||||
|  | 	m_cost += 49; | ||||||
|  | 	ASTWalker::operator()(_funCall); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CodeCost::operator()(FunctionalInstruction const& _instr) | ||||||
|  | { | ||||||
|  | 	using namespace dev::solidity; | ||||||
|  | 	yulAssert(m_cost >= 1, "Should assign cost one in visit(Expression)."); | ||||||
|  | 	Tier gasPriceTier = instructionInfo(_instr.instruction).gasPriceTier; | ||||||
|  | 	if (gasPriceTier < Tier::VeryLow) | ||||||
|  | 		m_cost -= 1; | ||||||
|  | 	else if (gasPriceTier < Tier::High) | ||||||
|  | 		m_cost += 1; | ||||||
|  | 	else | ||||||
|  | 		m_cost += 49; | ||||||
|  | 	ASTWalker::operator()(_instr); | ||||||
|  | } | ||||||
|  | void CodeCost::operator()(Literal const& _literal) | ||||||
|  | { | ||||||
|  | 	yulAssert(m_cost >= 1, "Should assign cost one in visit(Expression)."); | ||||||
|  | 	size_t cost = 0; | ||||||
|  | 	switch (_literal.kind) | ||||||
|  | 	{ | ||||||
|  | 	case LiteralKind::Boolean: | ||||||
|  | 		break; | ||||||
|  | 	case LiteralKind::Number: | ||||||
|  | 		for (u256 n = u256(_literal.value.str()); n >= 0x100; n >>= 8) | ||||||
|  | 			cost++; | ||||||
|  | 		break; | ||||||
|  | 	case LiteralKind::String: | ||||||
|  | 		cost = _literal.value.str().size(); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_cost += cost; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CodeCost::visit(Statement const& _statement) | ||||||
|  | { | ||||||
|  | 	++m_cost; | ||||||
|  | 	ASTWalker::visit(_statement); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CodeCost::visit(Expression const& _expression) | ||||||
|  | { | ||||||
|  | 	++m_cost; | ||||||
|  | 	ASTWalker::visit(_expression); | ||||||
|  | } | ||||||
|  | |||||||
| @ -46,4 +46,26 @@ private: | |||||||
| 	size_t m_size = 0; | 	size_t m_size = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Very rough cost that takes the size and execution cost of code into account. | ||||||
|  |  * The cost per AST element is one, except for literals where it is the byte size. | ||||||
|  |  * Function calls cost 50. Instructions cost 0 for 3 or less gas (same as DUP), | ||||||
|  |  * 2 for up to 10 and 50 otherwise. | ||||||
|  |  */ | ||||||
|  | class CodeCost: public ASTWalker | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	static size_t codeCost(Expression const& _expression); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	void operator()(FunctionCall const& _funCall) override; | ||||||
|  | 	void operator()(FunctionalInstruction const& _instr) override; | ||||||
|  | 	void operator()(Literal const& _literal) override; | ||||||
|  | 	void visit(Statement const& _statement) override; | ||||||
|  | 	void visit(Expression const& _expression) override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	size_t m_cost = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <libyul/optimiser/Metrics.h> | #include <libyul/optimiser/Metrics.h> | ||||||
| #include <libyul/optimiser/ASTCopier.h> | #include <libyul/optimiser/ASTCopier.h> | ||||||
|  | #include <libyul/optimiser/NameCollector.h> | ||||||
| #include <libyul/Exceptions.h> | #include <libyul/Exceptions.h> | ||||||
| #include <libyul/AsmData.h> | #include <libyul/AsmData.h> | ||||||
| 
 | 
 | ||||||
| @ -29,6 +30,16 @@ using namespace std; | |||||||
| using namespace dev; | using namespace dev; | ||||||
| using namespace yul; | using namespace yul; | ||||||
| 
 | 
 | ||||||
|  | void Rematerialiser::run(Block& _ast) | ||||||
|  | { | ||||||
|  | 	Rematerialiser{_ast}(_ast); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Rematerialiser::Rematerialiser(Block& _ast): | ||||||
|  | 	m_referenceCounts(ReferencesCounter::countReferences(_ast)) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Rematerialiser::visit(Expression& _e) | void Rematerialiser::visit(Expression& _e) | ||||||
| { | { | ||||||
| 	if (_e.type() == typeid(Identifier)) | 	if (_e.type() == typeid(Identifier)) | ||||||
| @ -37,12 +48,21 @@ void Rematerialiser::visit(Expression& _e) | |||||||
| 		if (m_value.count(identifier.name)) | 		if (m_value.count(identifier.name)) | ||||||
| 		{ | 		{ | ||||||
| 			YulString name = identifier.name; | 			YulString name = identifier.name; | ||||||
| 			for (auto const& ref: m_references[name]) |  | ||||||
| 				assertThrow(inScope(ref), OptimizerException, ""); |  | ||||||
| 			assertThrow(m_value.at(name), OptimizerException, ""); | 			assertThrow(m_value.at(name), OptimizerException, ""); | ||||||
| 			auto const& value = *m_value.at(name); | 			auto const& value = *m_value.at(name); | ||||||
| 			if (CodeSize::codeSize(value) <= 7) | 			size_t refs = m_referenceCounts[name]; | ||||||
|  | 			size_t cost = CodeCost::codeCost(value); | ||||||
|  | 			if (refs <= 1 || cost == 0 || (refs <= 5 && cost <= 1)) | ||||||
|  | 			{ | ||||||
|  | 				assertThrow(m_referenceCounts[name] > 0, OptimizerException, ""); | ||||||
|  | 				for (auto const& ref: m_references[name]) | ||||||
|  | 					assertThrow(inScope(ref), OptimizerException, ""); | ||||||
|  | 				// update reference counts
 | ||||||
|  | 				m_referenceCounts[name]--; | ||||||
|  | 				for (auto const& ref: ReferencesCounter::countReferences(value)) | ||||||
|  | 					m_referenceCounts[ref.first] += ref.second; | ||||||
| 				_e = (ASTCopier{}).translate(value); | 				_e = (ASTCopier{}).translate(value); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	DataFlowAnalyzer::visit(_e); | 	DataFlowAnalyzer::visit(_e); | ||||||
|  | |||||||
| @ -26,16 +26,27 @@ namespace yul | |||||||
| { | { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Optimisation stage that replaces variables by their most recently assigned expressions. |  * Optimisation stage that replaces variables by their most recently assigned expressions, | ||||||
|  |  * but only if the expression is movable and one of the following holds: | ||||||
|  |  *  - the variable is referenced exactly once | ||||||
|  |  *  - the value is extremely cheap ("cost" of zero like ``caller()``) | ||||||
|  |  *  - the variable is referenced at most 5 times and the value is rather cheap | ||||||
|  |  *    ("cost" of at most 1 like a constant up to 0xff) | ||||||
|  * |  * | ||||||
|  * Prerequisite: Disambiguator |  * Prerequisite: Disambiguator | ||||||
|  */ |  */ | ||||||
| class Rematerialiser: public DataFlowAnalyzer | class Rematerialiser: public DataFlowAnalyzer | ||||||
| { | { | ||||||
|  | public: | ||||||
|  | 	static void run(Block& _ast); | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
|  | 	Rematerialiser(Block& _ast); | ||||||
|  | 
 | ||||||
| 	using ASTModifier::visit; | 	using ASTModifier::visit; | ||||||
| 	void visit(Expression& _e) override; | 	void visit(Expression& _e) override; | ||||||
| 
 | 
 | ||||||
|  | 	std::map<YulString, size_t> m_referenceCounts; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -105,14 +105,17 @@ void OptimiserSuite::run( | |||||||
| 		RedundantAssignEliminator::run(ast); | 		RedundantAssignEliminator::run(ast); | ||||||
| 		RedundantAssignEliminator::run(ast); | 		RedundantAssignEliminator::run(ast); | ||||||
| 		UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); | 		UnusedPruner::runUntilStabilised(ast, reservedIdentifiers); | ||||||
|  | 		CommonSubexpressionEliminator{}(ast); | ||||||
| 	} | 	} | ||||||
| 	ExpressionJoiner::run(ast); | 	ExpressionJoiner::run(ast); | ||||||
|  | 	Rematerialiser::run(ast); | ||||||
| 	UnusedPruner::runUntilStabilised(ast); | 	UnusedPruner::runUntilStabilised(ast); | ||||||
| 	ExpressionJoiner::run(ast); | 	ExpressionJoiner::run(ast); | ||||||
| 	UnusedPruner::runUntilStabilised(ast); | 	UnusedPruner::runUntilStabilised(ast); | ||||||
| 	ExpressionJoiner::run(ast); | 	ExpressionJoiner::run(ast); | ||||||
| 	UnusedPruner::runUntilStabilised(ast); | 	UnusedPruner::runUntilStabilised(ast); | ||||||
| 	ExpressionJoiner::run(ast); | 	ExpressionJoiner::run(ast); | ||||||
|  | 	Rematerialiser::run(ast); | ||||||
| 	UnusedPruner::runUntilStabilised(ast); | 	UnusedPruner::runUntilStabilised(ast); | ||||||
| 
 | 
 | ||||||
| 	_ast = std::move(ast); | 	_ast = std::move(ast); | ||||||
|  | |||||||
| @ -171,7 +171,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con | |||||||
| 	else if (m_optimizerStep == "rematerialiser") | 	else if (m_optimizerStep == "rematerialiser") | ||||||
| 	{ | 	{ | ||||||
| 		disambiguate(); | 		disambiguate(); | ||||||
| 		(Rematerialiser{})(*m_ast); | 		Rematerialiser::run(*m_ast); | ||||||
| 	} | 	} | ||||||
| 	else if (m_optimizerStep == "expressionSimplifier") | 	else if (m_optimizerStep == "expressionSimplifier") | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
| @ -19,31 +19,21 @@ object "a" { | |||||||
| // Assembly: | // Assembly: | ||||||
| //     /* "source":60:61   */ | //     /* "source":60:61   */ | ||||||
| //   0x00 | //   0x00 | ||||||
| //     /* "source":137:138   */ | //   0x00 | ||||||
| //   dup1 |  | ||||||
| //     /* "source":60:61   */ |  | ||||||
| //   dup2 |  | ||||||
| //     /* "source":47:62   */ | //     /* "source":47:62   */ | ||||||
| //   calldataload | //   calldataload | ||||||
| //     /* "source":119:139   */ | //     /* "source":119:139   */ | ||||||
| //   sstore | //   sstore | ||||||
| //     /* "source":32:143   */ |  | ||||||
| //   pop |  | ||||||
| // stop | // stop | ||||||
| // | // | ||||||
| // sub_0: assembly { | // sub_0: assembly { | ||||||
| //         /* "source":200:201   */ | //         /* "source":200:201   */ | ||||||
| //       0x00 | //       0x00 | ||||||
| //         /* "source":283:284   */ | //       0x00 | ||||||
| //       dup1 |  | ||||||
| //         /* "source":200:201   */ |  | ||||||
| //       dup2 |  | ||||||
| //         /* "source":187:202   */ | //         /* "source":187:202   */ | ||||||
| //       calldataload | //       calldataload | ||||||
| //         /* "source":265:285   */ | //         /* "source":265:285   */ | ||||||
| //       sstore | //       sstore | ||||||
| //         /* "source":170:291   */ |  | ||||||
| //       pop |  | ||||||
| // } | // } | ||||||
| // Bytecode: 60008081355550fe | // Bytecode: 600060003555fe | ||||||
| // Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP INVALID | // Opcodes: PUSH1 0x0 PUSH1 0x0 CALLDATALOAD SSTORE INVALID | ||||||
|  | |||||||
| @ -9,15 +9,10 @@ | |||||||
| // Assembly: | // Assembly: | ||||||
| //     /* "source":38:39   */ | //     /* "source":38:39   */ | ||||||
| //   0x00 | //   0x00 | ||||||
| //     /* "source":109:110   */ | //   0x00 | ||||||
| //   dup1 |  | ||||||
| //     /* "source":38:39   */ |  | ||||||
| //   dup2 |  | ||||||
| //     /* "source":25:40   */ | //     /* "source":25:40   */ | ||||||
| //   calldataload | //   calldataload | ||||||
| //     /* "source":91:111   */ | //     /* "source":91:111   */ | ||||||
| //   sstore | //   sstore | ||||||
| //     /* "source":12:113   */ | // Bytecode: 600060003555 | ||||||
| //   pop | // Opcodes: PUSH1 0x0 PUSH1 0x0 CALLDATALOAD SSTORE | ||||||
| // Bytecode: 60008081355550 |  | ||||||
| // Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP |  | ||||||
|  | |||||||
| @ -460,14 +460,13 @@ | |||||||
| // { | // { | ||||||
| //     { | //     { | ||||||
| //         let _1 := 0x20 | //         let _1 := 0x20 | ||||||
| //         let _2 := 0 | //         let _485 := mload(0) | ||||||
| //         let _485 := mload(_2) |  | ||||||
| //         let abi_encode_pos := _1 | //         let abi_encode_pos := _1 | ||||||
| //         let abi_encode_length_68 := mload(_485) | //         let abi_encode_length_68 := mload(_485) | ||||||
| //         mstore(_1, abi_encode_length_68) | //         mstore(_1, abi_encode_length_68) | ||||||
| //         abi_encode_pos := 64 | //         abi_encode_pos := 64 | ||||||
| //         let abi_encode_srcPtr := add(_485, _1) | //         let abi_encode_srcPtr := add(_485, _1) | ||||||
| //         let abi_encode_i_69 := _2 | //         let abi_encode_i_69 := 0 | ||||||
| //         for { | //         for { | ||||||
| //         } | //         } | ||||||
| //         lt(abi_encode_i_69, abi_encode_length_68) | //         lt(abi_encode_i_69, abi_encode_length_68) | ||||||
| @ -477,12 +476,11 @@ | |||||||
| //         { | //         { | ||||||
| //             let _863 := mload(abi_encode_srcPtr) | //             let _863 := mload(abi_encode_srcPtr) | ||||||
| //             let abi_encode_pos_71_971 := abi_encode_pos | //             let abi_encode_pos_71_971 := abi_encode_pos | ||||||
| //             let abi_encode_length_72_972 := 0x3 |  | ||||||
| //             let abi_encode_srcPtr_73_973 := _863 | //             let abi_encode_srcPtr_73_973 := _863 | ||||||
| //             let abi_encode_i_74_974 := _2 | //             let abi_encode_i_74_974 := 0 | ||||||
| //             for { | //             for { | ||||||
| //             } | //             } | ||||||
| //             lt(abi_encode_i_74_974, abi_encode_length_72_972) | //             lt(abi_encode_i_74_974, 0x3) | ||||||
| //             { | //             { | ||||||
| //                 abi_encode_i_74_974 := add(abi_encode_i_74_974, 1) | //                 abi_encode_i_74_974 := add(abi_encode_i_74_974, 1) | ||||||
| //             } | //             } | ||||||
| @ -497,28 +495,24 @@ | |||||||
| //         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(_1), mload(0x40)) | //         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(_1), mload(0x40)) | ||||||
| //         sstore(a, b) | //         sstore(a, b) | ||||||
| //         sstore(c, d) | //         sstore(c, d) | ||||||
| //         sstore(_2, abi_encode_pos) | //         sstore(0, abi_encode_pos) | ||||||
| //     } | //     } | ||||||
| //     function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset_3, end_4) -> array_5 | //     function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset_3, end_4) -> array_5 | ||||||
| //     { | //     { | ||||||
| //         if iszero(slt(add(offset_3, 0x1f), end_4)) | //         if iszero(slt(add(offset_3, 0x1f), end_4)) | ||||||
| //         { | //         { | ||||||
| //             revert(array_5, array_5) | //             revert(0, 0) | ||||||
| //         } | //         } | ||||||
| //         let length_6 := calldataload(offset_3) | //         let length_6 := calldataload(offset_3) | ||||||
| //         let array_5_254 := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_6)) | //         let array_5_254 := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_6)) | ||||||
| //         array_5 := array_5_254 | //         array_5 := array_5_254 | ||||||
| //         let dst_7 := array_5_254 | //         let dst_7 := array_5_254 | ||||||
| //         mstore(array_5_254, length_6) | //         mstore(array_5_254, length_6) | ||||||
| //         let _36 := 0x20 | //         dst_7 := add(array_5_254, 0x20) | ||||||
| //         let offset_3_256 := add(offset_3, _36) | //         let src_8 := add(offset_3, 0x20) | ||||||
| //         dst_7 := add(array_5_254, _36) | //         if gt(add(add(offset_3, mul(length_6, 0x40)), 0x20), end_4) | ||||||
| //         let src_8 := offset_3_256 |  | ||||||
| //         let _38 := 0x40 |  | ||||||
| //         if gt(add(add(offset_3, mul(length_6, _38)), _36), end_4) |  | ||||||
| //         { | //         { | ||||||
| //             let _42 := 0 | //             revert(0, 0) | ||||||
| //             revert(_42, _42) |  | ||||||
| //         } | //         } | ||||||
| //         let i_9 := 0 | //         let i_9 := 0 | ||||||
| //         for { | //         for { | ||||||
| @ -529,46 +523,42 @@ | |||||||
| //         } | //         } | ||||||
| //         { | //         { | ||||||
| //             mstore(dst_7, abi_decode_t_array$_t_uint256_$2_memory(src_8, end_4)) | //             mstore(dst_7, abi_decode_t_array$_t_uint256_$2_memory(src_8, end_4)) | ||||||
| //             dst_7 := add(dst_7, _36) | //             dst_7 := add(dst_7, 0x20) | ||||||
| //             src_8 := add(src_8, _38) | //             src_8 := add(src_8, 0x40) | ||||||
| //         } | //         } | ||||||
| //     } | //     } | ||||||
| //     function abi_decode_t_array$_t_uint256_$2_memory(offset_11, end_12) -> array_13 | //     function abi_decode_t_array$_t_uint256_$2_memory(offset_11, end_12) -> array_13 | ||||||
| //     { | //     { | ||||||
| //         if iszero(slt(add(offset_11, 0x1f), end_12)) | //         if iszero(slt(add(offset_11, 0x1f), end_12)) | ||||||
| //         { | //         { | ||||||
| //             revert(array_13, array_13) | //             revert(0, 0) | ||||||
| //         } | //         } | ||||||
| //         let length_14 := 0x2 | //         let array_13_263 := allocateMemory(64) | ||||||
| //         let array_allo__559 := 0x20 |  | ||||||
| //         let array_allo_size_95_605 := 64 |  | ||||||
| //         let array_13_263 := allocateMemory(array_allo_size_95_605) |  | ||||||
| //         array_13 := array_13_263 | //         array_13 := array_13_263 | ||||||
| //         let dst_15 := array_13_263 | //         let dst_15 := array_13_263 | ||||||
| //         let src_16 := offset_11 | //         let src_16 := offset_11 | ||||||
| //         if gt(add(offset_11, array_allo_size_95_605), end_12) | //         if gt(add(offset_11, 64), end_12) | ||||||
| //         { | //         { | ||||||
| //             let _59 := 0 | //             revert(0, 0) | ||||||
| //             revert(_59, _59) |  | ||||||
| //         } | //         } | ||||||
| //         let i_17 := 0 | //         let i_17 := 0 | ||||||
| //         for { | //         for { | ||||||
| //         } | //         } | ||||||
| //         lt(i_17, length_14) | //         lt(i_17, 0x2) | ||||||
| //         { | //         { | ||||||
| //             i_17 := add(i_17, 1) | //             i_17 := add(i_17, 1) | ||||||
| //         } | //         } | ||||||
| //         { | //         { | ||||||
| //             mstore(dst_15, calldataload(src_16)) | //             mstore(dst_15, calldataload(src_16)) | ||||||
| //             dst_15 := add(dst_15, array_allo__559) | //             dst_15 := add(dst_15, 0x20) | ||||||
| //             src_16 := add(src_16, array_allo__559) | //             src_16 := add(src_16, 0x20) | ||||||
| //         } | //         } | ||||||
| //     } | //     } | ||||||
| //     function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset_27, end_28) -> array_29 | //     function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset_27, end_28) -> array_29 | ||||||
| //     { | //     { | ||||||
| //         if iszero(slt(add(offset_27, 0x1f), end_28)) | //         if iszero(slt(add(offset_27, 0x1f), end_28)) | ||||||
| //         { | //         { | ||||||
| //             revert(array_29, array_29) | //             revert(0, 0) | ||||||
| //         } | //         } | ||||||
| //         let length_30 := calldataload(offset_27) | //         let length_30 := calldataload(offset_27) | ||||||
| //         let array_29_279 := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_30)) | //         let array_29_279 := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_30)) | ||||||
| @ -576,13 +566,11 @@ | |||||||
| //         let dst_31 := array_29_279 | //         let dst_31 := array_29_279 | ||||||
| //         mstore(array_29_279, length_30) | //         mstore(array_29_279, length_30) | ||||||
| //         let _91 := 0x20 | //         let _91 := 0x20 | ||||||
| //         let offset_27_281 := add(offset_27, _91) |  | ||||||
| //         dst_31 := add(array_29_279, _91) | //         dst_31 := add(array_29_279, _91) | ||||||
| //         let src_32 := offset_27_281 | //         let src_32 := add(offset_27, _91) | ||||||
| //         if gt(add(add(offset_27, mul(length_30, _91)), _91), end_28) | //         if gt(add(add(offset_27, mul(length_30, _91)), _91), end_28) | ||||||
| //         { | //         { | ||||||
| //             let _97 := 0 | //             revert(0, 0) | ||||||
| //             revert(_97, _97) |  | ||||||
| //         } | //         } | ||||||
| //         let i_33 := 0 | //         let i_33 := 0 | ||||||
| //         for { | //         for { | ||||||
| @ -621,40 +609,36 @@ | |||||||
| //             let offset_65 := calldataload(add(headStart_58, 96)) | //             let offset_65 := calldataload(add(headStart_58, 96)) | ||||||
| //             if gt(offset_65, 0xffffffffffffffff) | //             if gt(offset_65, 0xffffffffffffffff) | ||||||
| //             { | //             { | ||||||
| //                 revert(value3, value3) | //                 revert(0, 0) | ||||||
| //             } | //             } | ||||||
| //             value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart_58, offset_65), dataEnd_59) | //             value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart_58, offset_65), dataEnd_59) | ||||||
| //         } | //         } | ||||||
| //     } | //     } | ||||||
| //     function allocateMemory(size) -> memPtr | //     function allocateMemory(size) -> memPtr | ||||||
| //     { | //     { | ||||||
| //         let _199 := 64 | //         let memPtr_315 := mload(64) | ||||||
| //         let memPtr_315 := mload(_199) |  | ||||||
| //         memPtr := memPtr_315 | //         memPtr := memPtr_315 | ||||||
| //         let newFreePtr := add(memPtr_315, size) | //         let newFreePtr := add(memPtr_315, size) | ||||||
| //         if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr_315)) | //         if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr_315)) | ||||||
| //         { | //         { | ||||||
| //             let _204 := 0 | //             revert(0, 0) | ||||||
| //             revert(_204, _204) |  | ||||||
| //         } | //         } | ||||||
| //         mstore(_199, newFreePtr) | //         mstore(64, newFreePtr) | ||||||
| //     } | //     } | ||||||
| //     function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_92) -> size_93 | //     function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_92) -> size_93 | ||||||
| //     { | //     { | ||||||
| //         if gt(length_92, 0xffffffffffffffff) | //         if gt(length_92, 0xffffffffffffffff) | ||||||
| //         { | //         { | ||||||
| //             revert(size_93, size_93) | //             revert(0, 0) | ||||||
| //         } | //         } | ||||||
| //         let _217 := 0x20 | //         size_93 := add(mul(length_92, 0x20), 0x20) | ||||||
| //         size_93 := add(mul(length_92, _217), _217) |  | ||||||
| //     } | //     } | ||||||
| //     function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_98) -> size_99 | //     function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_98) -> size_99 | ||||||
| //     { | //     { | ||||||
| //         if gt(length_98, 0xffffffffffffffff) | //         if gt(length_98, 0xffffffffffffffff) | ||||||
| //         { | //         { | ||||||
| //             revert(size_99, size_99) | //             revert(0, 0) | ||||||
| //         } | //         } | ||||||
| //         let _234 := 0x20 | //         size_99 := add(mul(length_98, 0x20), 0x20) | ||||||
| //         size_99 := add(mul(length_98, _234), _234) |  | ||||||
| //     } | //     } | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -20,12 +20,11 @@ | |||||||
| // fullSuite | // fullSuite | ||||||
| // { | // { | ||||||
| //     { | //     { | ||||||
| //         let _1 := 0x20 |  | ||||||
| //         let allocate__19 := 0x40 | //         let allocate__19 := 0x40 | ||||||
| //         mstore(allocate__19, add(mload(allocate__19), _1)) | //         mstore(allocate__19, add(mload(allocate__19), 0x20)) | ||||||
| //         let allocate_p_24_41 := mload(allocate__19) | //         let allocate_p_24_41 := mload(allocate__19) | ||||||
| //         mstore(allocate__19, add(allocate_p_24_41, allocate__19)) | //         mstore(allocate__19, add(allocate_p_24_41, allocate__19)) | ||||||
| //         mstore(add(allocate_p_24_41, 96), 2) | //         mstore(add(allocate_p_24_41, 96), 2) | ||||||
| //         mstore(allocate__19, _1) | //         mstore(allocate__19, 0x20) | ||||||
| //     } | //     } | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
|     let a := 1 |     let a := caller() | ||||||
|     for { pop(a) } a { pop(a) } { |     for { pop(a) } a { pop(a) } { | ||||||
|         pop(a) |         pop(a) | ||||||
|     } |     } | ||||||
| @ -7,15 +7,15 @@ | |||||||
| // ---- | // ---- | ||||||
| // rematerialiser | // rematerialiser | ||||||
| // { | // { | ||||||
| //     let a := 1 | //     let a := caller() | ||||||
| //     for { | //     for { | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     1 | //     caller() | ||||||
| //     { | //     { | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     { | //     { | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|     let a := 1 |     let a := caller() | ||||||
|     for { pop(a) } a { pop(a) } { |     for { pop(a) } a { pop(a) } { | ||||||
|         a := 7 |         a := address() | ||||||
|         let c := a |         let c := a | ||||||
|     } |     } | ||||||
|     let x := a |     let x := a | ||||||
| @ -9,17 +9,17 @@ | |||||||
| // ---- | // ---- | ||||||
| // rematerialiser | // rematerialiser | ||||||
| // { | // { | ||||||
| //     let a := 1 | //     let a := caller() | ||||||
| //     for { | //     for { | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     a | //     a | ||||||
| //     { | //     { | ||||||
| //         pop(7) | //         pop(address()) | ||||||
| //     } | //     } | ||||||
| //     { | //     { | ||||||
| //         a := 7 | //         a := address() | ||||||
| //         let c := 7 | //         let c := address() | ||||||
| //     } | //     } | ||||||
| //     let x := a | //     let x := a | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|     let b := 0 |     let b := 0 | ||||||
|     for { let a := 1 pop(a) } a { pop(a) } { |     for { let a := caller() pop(a) } a { pop(a) } { | ||||||
|         b := 1 pop(a) |         b := 1 pop(a) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -9,15 +9,15 @@ | |||||||
| // { | // { | ||||||
| //     let b := 0 | //     let b := 0 | ||||||
| //     for { | //     for { | ||||||
| //         let a := 1 | //         let a := caller() | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     1 | //     caller() | ||||||
| //     { | //     { | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     { | //     { | ||||||
| //         b := 1 | //         b := 1 | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|     let b := 0 |     let b := 0 | ||||||
|     for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { |     for { let a := caller() pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { | ||||||
|         b := 1 pop(a) |         b := 1 pop(a) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -9,8 +9,8 @@ | |||||||
| // { | // { | ||||||
| //     let b := 0 | //     let b := 0 | ||||||
| //     for { | //     for { | ||||||
| //         let a := 1 | //         let a := caller() | ||||||
| //         pop(1) | //         pop(caller()) | ||||||
| //     } | //     } | ||||||
| //     lt(a, 0) | //     lt(a, 0) | ||||||
| //     { | //     { | ||||||
|  | |||||||
| @ -1,18 +1,18 @@ | |||||||
| { | { | ||||||
|     let a := 1 |     let a := caller() | ||||||
|     let b := 2 |     let b := address() | ||||||
|     if b { pop(b) b := a } |     if b { pop(b) b := a } | ||||||
|     let c := b |     let c := b | ||||||
| } | } | ||||||
| // ---- | // ---- | ||||||
| // rematerialiser | // rematerialiser | ||||||
| // { | // { | ||||||
| //     let a := 1 | //     let a := caller() | ||||||
| //     let b := 2 | //     let b := address() | ||||||
| //     if 2 | //     if address() | ||||||
| //     { | //     { | ||||||
| //         pop(2) | //         pop(address()) | ||||||
| //         b := 1 | //         b := caller() | ||||||
| //     } | //     } | ||||||
| //     let c := b | //     let c := b | ||||||
| // } | // } | ||||||
|  | |||||||
| @ -0,0 +1,16 @@ | |||||||
|  | { | ||||||
|  |     // The caller opcode is cheap, so inline it, | ||||||
|  |     // no matter how often it is used | ||||||
|  |     let a := caller() | ||||||
|  |     mstore(a, a) | ||||||
|  |     mstore(add(a, a), mload(a)) | ||||||
|  |     sstore(a, sload(a)) | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // rematerialiser | ||||||
|  | // { | ||||||
|  | //     let a := caller() | ||||||
|  | //     mstore(caller(), caller()) | ||||||
|  | //     mstore(add(caller(), caller()), mload(caller())) | ||||||
|  | //     sstore(caller(), sload(caller())) | ||||||
|  | // } | ||||||
| @ -1,10 +0,0 @@ | |||||||
| { |  | ||||||
| 	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()) |  | ||||||
| // } |  | ||||||
| @ -6,5 +6,5 @@ | |||||||
| // rematerialiser | // rematerialiser | ||||||
| // { | // { | ||||||
| //     let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) | //     let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) | ||||||
| //     let b := x | //     let b := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) | ||||||
| // } | // } | ||||||
| @ -1,10 +0,0 @@ | |||||||
| { |  | ||||||
|     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())) |  | ||||||
| // } |  | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | { | ||||||
|  |     // Constants cost depending on their magnitude. | ||||||
|  |     // Do not rematerialize large constants. | ||||||
|  |     let a := 0xffffffffffffffffffffff | ||||||
|  |     mstore(a, a) | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // rematerialiser | ||||||
|  | // { | ||||||
|  | //     let a := 0xffffffffffffffffffffff | ||||||
|  | //     mstore(a, a) | ||||||
|  | // } | ||||||
| @ -0,0 +1,13 @@ | |||||||
|  | { | ||||||
|  |     // Constants cost depending on their magnitude. | ||||||
|  |     // Do not rematerialize large constants, | ||||||
|  |     // unless they are used exactly once. | ||||||
|  |     let a := 0xffffffffffffffffffffff | ||||||
|  |     mstore(0, a) | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // rematerialiser | ||||||
|  | // { | ||||||
|  | //     let a := 0xffffffffffffffffffffff | ||||||
|  | //     mstore(0, 0xffffffffffffffffffffff) | ||||||
|  | // } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | { | ||||||
|  |     // Constants cost depending on their magnitude. | ||||||
|  |     // Rematerialize small constants only if they are | ||||||
|  |     // not used too often. | ||||||
|  |     // b is used 5 times | ||||||
|  |     let b := 2 | ||||||
|  |     mstore(b, b) | ||||||
|  |     mstore(add(b, b), b) | ||||||
|  |     // a is used 7 times | ||||||
|  |     let a := 1 | ||||||
|  |     mstore(a, a) | ||||||
|  |     mstore(add(a, a), a) | ||||||
|  |     mstore(a, mload(a)) | ||||||
|  | } | ||||||
|  | // ---- | ||||||
|  | // rematerialiser | ||||||
|  | // { | ||||||
|  | //     let b := 2 | ||||||
|  | //     mstore(2, 2) | ||||||
|  | //     mstore(add(2, 2), 2) | ||||||
|  | //     let a := 1 | ||||||
|  | //     mstore(a, a) | ||||||
|  | //     mstore(add(a, a), a) | ||||||
|  | //     mstore(a, mload(a)) | ||||||
|  | // } | ||||||
| @ -182,7 +182,7 @@ public: | |||||||
| 				RedundantAssignEliminator::run(*m_ast); | 				RedundantAssignEliminator::run(*m_ast); | ||||||
| 				break; | 				break; | ||||||
| 			case 'm': | 			case 'm': | ||||||
| 				Rematerialiser{}(*m_ast); | 				Rematerialiser::run(*m_ast); | ||||||
| 				break; | 				break; | ||||||
| 			default: | 			default: | ||||||
| 				cout << "Unknown option." << endl; | 				cout << "Unknown option." << endl; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user