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 <libyul/optimiser/TypeInfo.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::yul;
|
||||
@ -42,8 +44,14 @@ namespace
|
||||
class IntroduceSSA: public ASTModifier
|
||||
{
|
||||
public:
|
||||
explicit IntroduceSSA(NameDispenser& _nameDispenser, set<YulString> const& _variablesToReplace):
|
||||
m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace)
|
||||
explicit IntroduceSSA(
|
||||
NameDispenser& _nameDispenser,
|
||||
set<YulString> const& _variablesToReplace,
|
||||
TypeInfo& _typeInfo
|
||||
):
|
||||
m_nameDispenser(_nameDispenser),
|
||||
m_variablesToReplace(_variablesToReplace),
|
||||
m_typeInfo(_typeInfo)
|
||||
{ }
|
||||
|
||||
void operator()(Block& _block) override;
|
||||
@ -51,6 +59,7 @@ public:
|
||||
private:
|
||||
NameDispenser& m_nameDispenser;
|
||||
set<YulString> const& m_variablesToReplace;
|
||||
TypeInfo const& m_typeInfo;
|
||||
};
|
||||
|
||||
|
||||
@ -83,10 +92,10 @@ void IntroduceSSA::operator()(Block& _block)
|
||||
{
|
||||
YulString oldName = var.name;
|
||||
YulString newName = m_nameDispenser.newName(oldName);
|
||||
newVariables.emplace_back(TypedName{loc, newName, {}});
|
||||
newVariables.emplace_back(TypedName{loc, newName, var.type});
|
||||
statements.emplace_back(VariableDeclaration{
|
||||
loc,
|
||||
{TypedName{loc, oldName, {}}},
|
||||
{TypedName{loc, oldName, var.type}},
|
||||
make_unique<Expression>(Identifier{loc, newName})
|
||||
});
|
||||
}
|
||||
@ -110,7 +119,11 @@ void IntroduceSSA::operator()(Block& _block)
|
||||
{
|
||||
YulString oldName = var.name;
|
||||
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{
|
||||
loc,
|
||||
{Identifier{loc, oldName}},
|
||||
@ -136,9 +149,12 @@ class IntroduceControlFlowSSA: public ASTModifier
|
||||
public:
|
||||
explicit IntroduceControlFlowSSA(
|
||||
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;
|
||||
@ -153,6 +169,7 @@ private:
|
||||
set<YulString> m_variablesInScope;
|
||||
/// Set of variables that do not have a specific value.
|
||||
set<YulString> m_variablesToReassign;
|
||||
TypeInfo const& m_typeInfo;
|
||||
};
|
||||
|
||||
void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function)
|
||||
@ -221,7 +238,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block)
|
||||
YulString newName = m_nameDispenser.newName(toReassign);
|
||||
toPrepend.emplace_back(VariableDeclaration{
|
||||
locationOf(_s),
|
||||
{TypedName{locationOf(_s), newName, {}}},
|
||||
{TypedName{locationOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}},
|
||||
make_unique<Expression>(Identifier{locationOf(_s), toReassign})
|
||||
});
|
||||
assignedVariables.insert(toReassign);
|
||||
@ -375,10 +392,11 @@ void PropagateValues::operator()(Block& _block)
|
||||
|
||||
void SSATransform::run(OptimiserStepContext& _context, Block& _ast)
|
||||
{
|
||||
TypeInfo typeInfo(_context.dialect, _ast);
|
||||
Assignments assignments;
|
||||
assignments(_ast);
|
||||
IntroduceSSA{_context.dispenser, assignments.names()}(_ast);
|
||||
IntroduceControlFlowSSA{_context.dispenser, assignments.names()}(_ast);
|
||||
IntroduceSSA{_context.dispenser, assignments.names(), typeInfo}(_ast);
|
||||
IntroduceControlFlowSSA{_context.dispenser, assignments.names(), typeInfo}(_ast);
|
||||
PropagateValues{assignments.names()}(_ast);
|
||||
}
|
||||
|
||||
|
@ -96,3 +96,8 @@ YulString TypeInfo::typeOf(Expression const& _expression) const
|
||||
}
|
||||
}, _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.
|
||||
YulString typeOf(Expression const& _expression) const;
|
||||
|
||||
/// \returns the type of variable
|
||||
YulString typeOfVariable(YulString _name) const;
|
||||
|
||||
private:
|
||||
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