mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #6131 from ethereum/fix-yul-opt
Yul Optimizer: reduce switches with const arguments
This commit is contained in:
		
						commit
						3dee9c50cd
					
				| @ -12,6 +12,7 @@ Compiler Features: | ||||
|  * Optimizer: Add rule for shifts with constants for Constantinople. | ||||
|  * Optimizer: Combine multiple shifts with constant shift-by values into one. | ||||
|  * Optimizer: Support shifts in the constant optimiser for Constantinople. | ||||
|  * Yul Optimizer: Add rule to replace switch statements with const expr. with matching case body | ||||
| 
 | ||||
| 
 | ||||
| Bugfixes: | ||||
|  | ||||
| @ -45,6 +45,26 @@ void StructuralSimplifier::operator()(Block& _block) | ||||
| 	popScope(); | ||||
| } | ||||
| 
 | ||||
| boost::optional<dev::u256> StructuralSimplifier::hasLiteralValue(Expression const& _expression) const | ||||
| { | ||||
| 	Expression const* expr = &_expression; | ||||
| 
 | ||||
| 	if (expr->type() == typeid(Identifier)) | ||||
| 	{ | ||||
| 		Identifier const& ident = boost::get<Identifier>(*expr); | ||||
| 		if (m_value.count(ident.name)) | ||||
| 			expr = m_value.at(ident.name); | ||||
| 	} | ||||
| 
 | ||||
| 	if (expr && expr->type() == typeid(Literal)) | ||||
| 	{ | ||||
| 		Literal const& literal = boost::get<Literal>(*expr); | ||||
| 		return valueOfNumberLiteral(literal); | ||||
| 	} | ||||
| 
 | ||||
| 	return boost::optional<u256>(); | ||||
| } | ||||
| 
 | ||||
| void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements) | ||||
| { | ||||
| 	using OptionalStatements = boost::optional<vector<Statement>>; | ||||
| @ -62,7 +82,7 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements) | ||||
| 				return {vector<Statement>{}}; | ||||
| 			return {}; | ||||
| 		}, | ||||
| 		[](Switch& _switchStmt) -> OptionalStatements { | ||||
| 		[&](Switch& _switchStmt) -> OptionalStatements { | ||||
| 			if (_switchStmt.cases.size() == 1) | ||||
| 			{ | ||||
| 				auto& switchCase = _switchStmt.cases.front(); | ||||
| @ -87,6 +107,32 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements) | ||||
| 					return s; | ||||
| 				} | ||||
| 			} | ||||
| 			else if (boost::optional<u256> const constExprVal = hasLiteralValue(*_switchStmt.expression)) | ||||
| 			{ | ||||
| 				Block* matchingCaseBlock = nullptr; | ||||
| 				Case* defaultCase = nullptr; | ||||
| 
 | ||||
| 				for (auto& _case: _switchStmt.cases) | ||||
| 				{ | ||||
| 					if (_case.value && valueOfNumberLiteral(*_case.value) == constExprVal) | ||||
| 					{ | ||||
| 						matchingCaseBlock = &_case.body; | ||||
| 						break; | ||||
| 					} | ||||
| 					else if (!_case.value) | ||||
| 						defaultCase = &_case; | ||||
| 				} | ||||
| 
 | ||||
| 				if (!matchingCaseBlock && defaultCase) | ||||
| 					matchingCaseBlock = &defaultCase->body; | ||||
| 
 | ||||
| 				OptionalStatements s = vector<Statement>{}; | ||||
| 
 | ||||
| 				if (matchingCaseBlock) | ||||
| 					s->emplace_back(std::move(*matchingCaseBlock)); | ||||
| 
 | ||||
| 				return s; | ||||
| 			} | ||||
| 			else | ||||
| 				return {}; | ||||
| 		}, | ||||
|  | ||||
| @ -18,6 +18,7 @@ | ||||
| 
 | ||||
| #include <libyul/optimiser/ASTWalker.h> | ||||
| #include <libyul/optimiser/DataFlowAnalyzer.h> | ||||
| #include <libdevcore/Common.h> | ||||
| 
 | ||||
| namespace yul | ||||
| { | ||||
| @ -29,6 +30,7 @@ namespace yul | ||||
|  * - remove if with false condition | ||||
|  * - turn switch with single case into if | ||||
|  * - replace switch with only default case with pop(expression) and body | ||||
|  * - replace switch with const expr with matching case body | ||||
|  * - remove for with false condition | ||||
|  * | ||||
|  * Prerequisites: Disambiguator | ||||
| @ -46,6 +48,7 @@ private: | ||||
| 	void simplify(std::vector<Statement>& _statements); | ||||
| 	bool expressionAlwaysTrue(Expression const& _expression); | ||||
| 	bool expressionAlwaysFalse(Expression const& _expression); | ||||
| 	boost::optional<dev::u256> hasLiteralValue(Expression const& _expression) const; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
							
								
								
									
										13
									
								
								test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/libyul/yulOptimizerTests/fullSuite/switch_inline.yul
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| { | ||||
| 	mstore(f(1), 0) | ||||
| 	function f(x) -> y { | ||||
| 		switch x | ||||
| 		case 0 { y := 8 } | ||||
| 		case 1 { y := 9 } | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // fullSuite | ||||
| // { | ||||
| //     mstore(9, 0) | ||||
| // } | ||||
| @ -0,0 +1,14 @@ | ||||
| { | ||||
| 	mstore(f(3), 0) | ||||
| 	function f(x) -> y { | ||||
| 		switch x | ||||
| 		case 0 { y := 8 } | ||||
| 		case 1 { y := 9 } | ||||
| 		default { y := 10 } | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // fullSuite | ||||
| // { | ||||
| //     mstore(10, 0) | ||||
| // } | ||||
| @ -0,0 +1,14 @@ | ||||
| { | ||||
| 	let y := 200 | ||||
| 	switch 1 | ||||
| 	case 0 { y := 8 } | ||||
| 	case 1 { y := 9 } | ||||
| } | ||||
| // ---- | ||||
| // structuralSimplifier | ||||
| // { | ||||
| //     let y := 200 | ||||
| //     { | ||||
| //         y := 9 | ||||
| //     } | ||||
| // } | ||||
| @ -0,0 +1,15 @@ | ||||
| { | ||||
| 	let y := 200 | ||||
| 	switch 3 | ||||
| 	case 0 { y := 8 } | ||||
| 	case 1 { y := 9 } | ||||
| 	default { y := 10 } | ||||
| } | ||||
| // ---- | ||||
| // structuralSimplifier | ||||
| // { | ||||
| //     let y := 200 | ||||
| //     { | ||||
| //         y := 10 | ||||
| //     } | ||||
| // } | ||||
| @ -0,0 +1,11 @@ | ||||
| { | ||||
| 	let y := 200 | ||||
| 	switch 3 | ||||
| 	case 0 { y := 8 } | ||||
| 	case 1 { y := 9 } | ||||
| } | ||||
| // ---- | ||||
| // structuralSimplifier | ||||
| // { | ||||
| //     let y := 200 | ||||
| // } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user