mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce LiteralRematerializer and thus simplify StructuralSimplifier.
This commit is contained in:
@@ -71,9 +71,9 @@ void Rematerialiser::visit(Expression& _e)
|
||||
if (_e.type() == typeid(Identifier))
|
||||
{
|
||||
Identifier& identifier = boost::get<Identifier>(_e);
|
||||
if (m_value.count(identifier.name))
|
||||
YulString name = identifier.name;
|
||||
if (m_value.count(name))
|
||||
{
|
||||
YulString name = identifier.name;
|
||||
assertThrow(m_value.at(name), OptimizerException, "");
|
||||
auto const& value = *m_value.at(name);
|
||||
size_t refs = m_referenceCounts[name];
|
||||
@@ -93,3 +93,20 @@ void Rematerialiser::visit(Expression& _e)
|
||||
}
|
||||
DataFlowAnalyzer::visit(_e);
|
||||
}
|
||||
|
||||
void LiteralRematerialiser::visit(Expression& _e)
|
||||
{
|
||||
if (_e.type() == typeid(Identifier))
|
||||
{
|
||||
Identifier& identifier = boost::get<Identifier>(_e);
|
||||
YulString name = identifier.name;
|
||||
if (m_value.count(name))
|
||||
{
|
||||
Expression const* value = m_value.at(name);
|
||||
assertThrow(value, OptimizerException, "");
|
||||
if (value->type() == typeid(Literal))
|
||||
_e = *value;
|
||||
}
|
||||
}
|
||||
DataFlowAnalyzer::visit(_e);
|
||||
}
|
||||
|
||||
@@ -68,4 +68,25 @@ protected:
|
||||
std::set<YulString> m_varsToAlwaysRematerialize;
|
||||
};
|
||||
|
||||
/**
|
||||
* If a variable is referenced that is known to have a literal
|
||||
* value at that point, replace it by a literal.
|
||||
*
|
||||
* This is mostly used so that other components do not have to rely
|
||||
* on the data flow analyzer.
|
||||
*
|
||||
* Prerequisite: Disambiguator, ForLoopInitRewriter.
|
||||
*/
|
||||
class LiteralRematerialiser: public DataFlowAnalyzer
|
||||
{
|
||||
public:
|
||||
LiteralRematerialiser(Dialect const& _dialect):
|
||||
DataFlowAnalyzer(_dialect)
|
||||
{}
|
||||
|
||||
using ASTModifier::visit;
|
||||
void visit(Expression& _e) override;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -61,29 +61,7 @@ OptionalStatements replaceConstArgSwitch(Switch& _switchStmt, u256 const& _const
|
||||
|
||||
void StructuralSimplifier::operator()(Block& _block)
|
||||
{
|
||||
pushScope(false);
|
||||
simplify(_block.statements);
|
||||
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 valueOfLiteral(literal);
|
||||
}
|
||||
|
||||
return boost::optional<u256>();
|
||||
}
|
||||
|
||||
void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
||||
@@ -124,34 +102,24 @@ void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
|
||||
|
||||
bool StructuralSimplifier::expressionAlwaysTrue(Expression const& _expression)
|
||||
{
|
||||
return boost::apply_visitor(GenericFallbackReturnsVisitor<bool, Identifier const, Literal const>(
|
||||
[&](Identifier const& _identifier) -> bool {
|
||||
if (auto expr = m_value[_identifier.name])
|
||||
return expressionAlwaysTrue(*expr);
|
||||
return false;
|
||||
},
|
||||
[](Literal const& _literal) -> bool {
|
||||
return
|
||||
(_literal.kind == LiteralKind::Boolean && _literal.value == "true"_yulstring) ||
|
||||
(_literal.kind == LiteralKind::Number && valueOfNumberLiteral(_literal) != u256(0))
|
||||
;
|
||||
}
|
||||
), _expression);
|
||||
if (boost::optional<u256> value = hasLiteralValue(_expression))
|
||||
return *value != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StructuralSimplifier::expressionAlwaysFalse(Expression const& _expression)
|
||||
{
|
||||
return boost::apply_visitor(GenericFallbackReturnsVisitor<bool, Identifier const, Literal const>(
|
||||
[&](Identifier const& _identifier) -> bool {
|
||||
if (auto expr = m_value[_identifier.name])
|
||||
return expressionAlwaysFalse(*expr);
|
||||
return false;
|
||||
},
|
||||
[](Literal const& _literal) -> bool {
|
||||
return
|
||||
(_literal.kind == LiteralKind::Boolean && _literal.value == "false"_yulstring) ||
|
||||
(_literal.kind == LiteralKind::Number && valueOfNumberLiteral(_literal) == u256(0))
|
||||
;
|
||||
}
|
||||
), _expression);
|
||||
if (boost::optional<u256> value = hasLiteralValue(_expression))
|
||||
return *value == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::optional<dev::u256> StructuralSimplifier::hasLiteralValue(Expression const& _expression) const
|
||||
{
|
||||
if (_expression.type() == typeid(Literal))
|
||||
return valueOfLiteral(boost::get<Literal>(_expression));
|
||||
else
|
||||
return boost::optional<u256>();
|
||||
}
|
||||
|
||||
@@ -30,16 +30,16 @@ namespace yul
|
||||
* - replace switch with const expr with matching case body
|
||||
* - replace for with false condition by its initialization part
|
||||
*
|
||||
* Prerequisite: Disambiguator, ForLoopInitRewriter.
|
||||
* The LiteralRematerialiser should be run before this.
|
||||
*
|
||||
* Prerequisite: Disambiguator.
|
||||
*
|
||||
* Important: Can only be used on EVM code.
|
||||
*/
|
||||
class StructuralSimplifier: public DataFlowAnalyzer
|
||||
class StructuralSimplifier: public ASTModifier
|
||||
{
|
||||
public:
|
||||
explicit StructuralSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}
|
||||
|
||||
using DataFlowAnalyzer::operator();
|
||||
using ASTModifier::operator();
|
||||
void operator()(Block& _block) override;
|
||||
private:
|
||||
void simplify(std::vector<Statement>& _statements);
|
||||
|
||||
@@ -91,7 +91,8 @@ void OptimiserSuite::run(
|
||||
UnusedPruner::runUntilStabilisedOnFullAST(_dialect, ast, reservedIdentifiers);
|
||||
BlockFlattener{}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
StructuralSimplifier{_dialect}(ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
StructuralSimplifier{}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
BlockFlattener{}(ast);
|
||||
|
||||
@@ -125,7 +126,8 @@ void OptimiserSuite::run(
|
||||
{
|
||||
// still in SSA, perform structural simplification
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
StructuralSimplifier{_dialect}(ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
StructuralSimplifier{}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
BlockFlattener{}(ast);
|
||||
DeadCodeEliminator{_dialect}(ast);
|
||||
@@ -182,7 +184,8 @@ void OptimiserSuite::run(
|
||||
RedundantAssignEliminator::run(_dialect, ast);
|
||||
LoadResolver::run(_dialect, ast);
|
||||
ExpressionSimplifier::run(_dialect, ast);
|
||||
StructuralSimplifier{_dialect}(ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
StructuralSimplifier{}(ast);
|
||||
BlockFlattener{}(ast);
|
||||
DeadCodeEliminator{_dialect}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
|
||||
Reference in New Issue
Block a user