mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Adding ssa type check and test for that one
This commit is contained in:
		
							parent
							
								
									2efda4129b
								
							
						
					
					
						commit
						c891597204
					
				| @ -27,6 +27,8 @@ | |||||||
| 
 | 
 | ||||||
| #include <libsolutil/CommonData.h> | #include <libsolutil/CommonData.h> | ||||||
| 
 | 
 | ||||||
|  | #include <libyul/optimiser/TypeInfo.h> | ||||||
|  | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace solidity; | using namespace solidity; | ||||||
| using namespace solidity::yul; | using namespace solidity::yul; | ||||||
| @ -42,8 +44,14 @@ namespace | |||||||
| class IntroduceSSA: public ASTModifier | class IntroduceSSA: public ASTModifier | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	explicit IntroduceSSA(NameDispenser& _nameDispenser, set<YulString> const& _variablesToReplace): | 	explicit IntroduceSSA( | ||||||
| 		m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace) | 		NameDispenser& _nameDispenser, | ||||||
|  | 		set<YulString> const& _variablesToReplace, | ||||||
|  | 		TypeInfo& _typeInfo | ||||||
|  | 	): | ||||||
|  | 		m_nameDispenser(_nameDispenser), | ||||||
|  | 		m_variablesToReplace(_variablesToReplace), | ||||||
|  | 		m_typeInfo(_typeInfo) | ||||||
| 	{ } | 	{ } | ||||||
| 
 | 
 | ||||||
| 	void operator()(Block& _block) override; | 	void operator()(Block& _block) override; | ||||||
| @ -51,6 +59,7 @@ public: | |||||||
| private: | private: | ||||||
| 	NameDispenser& m_nameDispenser; | 	NameDispenser& m_nameDispenser; | ||||||
| 	set<YulString> const& m_variablesToReplace; | 	set<YulString> const& m_variablesToReplace; | ||||||
|  | 	TypeInfo const& m_typeInfo; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -83,10 +92,10 @@ void IntroduceSSA::operator()(Block& _block) | |||||||
| 				{ | 				{ | ||||||
| 					YulString oldName = var.name; | 					YulString oldName = var.name; | ||||||
| 					YulString newName = m_nameDispenser.newName(oldName); | 					YulString newName = m_nameDispenser.newName(oldName); | ||||||
| 					newVariables.emplace_back(TypedName{loc, newName, {}}); | 					newVariables.emplace_back(TypedName{loc, newName, var.type}); | ||||||
| 					statements.emplace_back(VariableDeclaration{ | 					statements.emplace_back(VariableDeclaration{ | ||||||
| 						loc, | 						loc, | ||||||
| 						{TypedName{loc, oldName, {}}}, | 						{TypedName{loc, oldName, var.type}}, | ||||||
| 						make_unique<Expression>(Identifier{loc, newName}) | 						make_unique<Expression>(Identifier{loc, newName}) | ||||||
| 					}); | 					}); | ||||||
| 				} | 				} | ||||||
| @ -110,7 +119,11 @@ void IntroduceSSA::operator()(Block& _block) | |||||||
| 				{ | 				{ | ||||||
| 					YulString oldName = var.name; | 					YulString oldName = var.name; | ||||||
| 					YulString newName = m_nameDispenser.newName(oldName); | 					YulString newName = m_nameDispenser.newName(oldName); | ||||||
| 					newVariables.emplace_back(TypedName{loc, newName, {}}); | 					newVariables.emplace_back(TypedName{ | ||||||
|  | 						loc, | ||||||
|  | 						newName, | ||||||
|  | 						m_typeInfo.typeOfVariable(oldName) | ||||||
|  | 					}); | ||||||
| 					statements.emplace_back(Assignment{ | 					statements.emplace_back(Assignment{ | ||||||
| 						loc, | 						loc, | ||||||
| 						{Identifier{loc, oldName}}, | 						{Identifier{loc, oldName}}, | ||||||
| @ -136,9 +149,12 @@ class IntroduceControlFlowSSA: public ASTModifier | |||||||
| public: | public: | ||||||
| 	explicit IntroduceControlFlowSSA( | 	explicit IntroduceControlFlowSSA( | ||||||
| 		NameDispenser& _nameDispenser, | 		NameDispenser& _nameDispenser, | ||||||
| 		set<YulString> const& _variablesToReplace | 		set<YulString> const& _variablesToReplace, | ||||||
|  | 		TypeInfo const& _typeInfo | ||||||
| 	): | 	): | ||||||
| 		m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace) | 		m_nameDispenser(_nameDispenser), | ||||||
|  | 		m_variablesToReplace(_variablesToReplace), | ||||||
|  | 		m_typeInfo(_typeInfo) | ||||||
| 	{ } | 	{ } | ||||||
| 
 | 
 | ||||||
| 	void operator()(FunctionDefinition& _function) override; | 	void operator()(FunctionDefinition& _function) override; | ||||||
| @ -153,6 +169,7 @@ private: | |||||||
| 	set<YulString> m_variablesInScope; | 	set<YulString> m_variablesInScope; | ||||||
| 	/// Set of variables that do not have a specific value.
 | 	/// Set of variables that do not have a specific value.
 | ||||||
| 	set<YulString> m_variablesToReassign; | 	set<YulString> m_variablesToReassign; | ||||||
|  | 	TypeInfo const& m_typeInfo; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) | void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) | ||||||
| @ -221,7 +238,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) | |||||||
| 				YulString newName = m_nameDispenser.newName(toReassign); | 				YulString newName = m_nameDispenser.newName(toReassign); | ||||||
| 				toPrepend.emplace_back(VariableDeclaration{ | 				toPrepend.emplace_back(VariableDeclaration{ | ||||||
| 					locationOf(_s), | 					locationOf(_s), | ||||||
| 					{TypedName{locationOf(_s), newName, {}}}, | 					{TypedName{locationOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, | ||||||
| 					make_unique<Expression>(Identifier{locationOf(_s), toReassign}) | 					make_unique<Expression>(Identifier{locationOf(_s), toReassign}) | ||||||
| 				}); | 				}); | ||||||
| 				assignedVariables.insert(toReassign); | 				assignedVariables.insert(toReassign); | ||||||
| @ -375,10 +392,11 @@ void PropagateValues::operator()(Block& _block) | |||||||
| 
 | 
 | ||||||
| void SSATransform::run(OptimiserStepContext& _context, Block& _ast) | void SSATransform::run(OptimiserStepContext& _context, Block& _ast) | ||||||
| { | { | ||||||
|  | 	TypeInfo typeInfo(_context.dialect, _ast); | ||||||
| 	Assignments assignments; | 	Assignments assignments; | ||||||
| 	assignments(_ast); | 	assignments(_ast); | ||||||
| 	IntroduceSSA{_context.dispenser, assignments.names()}(_ast); | 	IntroduceSSA{_context.dispenser, assignments.names(), typeInfo}(_ast); | ||||||
| 	IntroduceControlFlowSSA{_context.dispenser, assignments.names()}(_ast); | 	IntroduceControlFlowSSA{_context.dispenser, assignments.names(), typeInfo}(_ast); | ||||||
| 	PropagateValues{assignments.names()}(_ast); | 	PropagateValues{assignments.names()}(_ast); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -96,3 +96,8 @@ YulString TypeInfo::typeOf(Expression const& _expression) const | |||||||
| 		} | 		} | ||||||
| 	}, _expression); | 	}, _expression); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | YulString TypeInfo::typeOfVariable(YulString _name) const | ||||||
|  | { | ||||||
|  | 	return m_variableTypes.at(_name); | ||||||
|  | } | ||||||
|  | |||||||
| @ -44,6 +44,9 @@ public: | |||||||
| 	/// @returns the type of an expression that is assumed to return exactly one value.
 | 	/// @returns the type of an expression that is assumed to return exactly one value.
 | ||||||
| 	YulString typeOf(Expression const& _expression) const; | 	YulString typeOf(Expression const& _expression) const; | ||||||
| 
 | 
 | ||||||
|  | 	/// \returns the type of variable
 | ||||||
|  | 	YulString typeOfVariable(YulString _name) const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	class TypeCollector; | 	class TypeCollector; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed.yul
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | { | ||||||
|  |   let b:bool := true | ||||||
|  |   let c:bool := false | ||||||
|  |   c := b | ||||||
|  |   b := false | ||||||
|  | 
 | ||||||
|  |   let a:u256 := 1 | ||||||
|  |   a := add(a, 1) | ||||||
|  |   if c { | ||||||
|  |     a := add(a, 1) | ||||||
|  |   } | ||||||
|  |   a := add(a, 1) | ||||||
|  |   mstore(a, 1) | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // dialect: evmTyped | ||||||
|  | // step: ssaTransform | ||||||
|  | // ---- | ||||||
|  | // { | ||||||
|  | //     let b_1:bool := true | ||||||
|  | //     let b:bool := b_1 | ||||||
|  | //     let c_2:bool := false | ||||||
|  | //     let c:bool := c_2 | ||||||
|  | //     let c_3:bool := b_1 | ||||||
|  | //     c := c_3 | ||||||
|  | //     let b_4:bool := false | ||||||
|  | //     b := b_4 | ||||||
|  | //     let a_5 := 1 | ||||||
|  | //     let a := a_5 | ||||||
|  | //     let a_6 := add(a_5, 1) | ||||||
|  | //     a := a_6 | ||||||
|  | //     if c_3 | ||||||
|  | //     { | ||||||
|  | //         let a_7 := add(a_6, 1) | ||||||
|  | //         a := a_7 | ||||||
|  | //     } | ||||||
|  | //     let a_9 := a | ||||||
|  | //     let a_8 := add(a_9, 1) | ||||||
|  | //     a := a_8 | ||||||
|  | //     mstore(a_8, 1) | ||||||
|  | // } | ||||||
							
								
								
									
										25
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed_for.yul
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | { | ||||||
|  |   let b:bool := true | ||||||
|  |   let c:bool := false | ||||||
|  |   for {} b {} { | ||||||
|  |       c := true | ||||||
|  |   } | ||||||
|  |   let d: bool := c | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // dialect: evmTyped | ||||||
|  | // step: ssaTransform | ||||||
|  | // ---- | ||||||
|  | // { | ||||||
|  | //     let b:bool := true | ||||||
|  | //     let c_1:bool := false | ||||||
|  | //     let c:bool := c_1 | ||||||
|  | //     for { } b { } | ||||||
|  | //     { | ||||||
|  | //         let c_3:bool := c | ||||||
|  | //         let c_2:bool := true | ||||||
|  | //         c := c_2 | ||||||
|  | //     } | ||||||
|  | //     let c_4:bool := c | ||||||
|  | //     let d:bool := c_4 | ||||||
|  | // } | ||||||
							
								
								
									
										25
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/libyul/yulOptimizerTests/ssaTransform/typed_switch.yul
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | { | ||||||
|  |   let b:bool := true | ||||||
|  |   let c:bool := false | ||||||
|  |   switch b | ||||||
|  |   case true { c := true} | ||||||
|  |   case false { } | ||||||
|  |   let d: bool := c | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // dialect: evmTyped | ||||||
|  | // step: ssaTransform | ||||||
|  | // ---- | ||||||
|  | // { | ||||||
|  | //     let b:bool := true | ||||||
|  | //     let c_1:bool := false | ||||||
|  | //     let c:bool := c_1 | ||||||
|  | //     switch b | ||||||
|  | //     case true { | ||||||
|  | //         let c_2:bool := true | ||||||
|  | //         c := c_2 | ||||||
|  | //     } | ||||||
|  | //     case false { } | ||||||
|  | //     let c_3:bool := c | ||||||
|  | //     let d:bool := c_3 | ||||||
|  | // } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user