Merge pull request #10811 from ethereum/prep-for-fuzzable-opt-steps

Minor refactor yul optimizer test framework to make it easier to fuzz
This commit is contained in:
chriseth 2021-01-19 13:05:35 +01:00 committed by GitHub
commit f5092088b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 276 additions and 312 deletions

View File

@ -85,123 +85,96 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
m_analysisInfo = m_object->analysisInfo; m_analysisInfo = m_object->analysisInfo;
m_dialect = &_dialect; m_dialect = &_dialect;
m_optimizerStep = _optimizerStep; m_optimizerStep = _optimizerStep;
}
bool YulOptimizerTestCommon::runStep() m_namedSteps = {
{ {"disambiguator", [&]() { disambiguate(); }},
yulAssert(m_dialect, "Dialect not set."); {"nameDisplacer", [&]() {
updateContext();
if (m_optimizerStep == "disambiguator")
disambiguate();
else if (m_optimizerStep == "nameDisplacer")
{
disambiguate(); disambiguate();
NameDisplacer{ NameDisplacer{
*m_nameDispenser, *m_nameDispenser,
{"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring}
}(*m_ast); }(*m_ast);
} }},
else if (m_optimizerStep == "blockFlattener") {"blockFlattener", [&]() {
{
disambiguate(); disambiguate();
BlockFlattener::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "constantOptimiser") {"constantOptimiser", [&]() {
{
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200); GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
ConstantOptimiser{dynamic_cast<EVMDialect const&>(*m_dialect), meter}(*m_ast); ConstantOptimiser{dynamic_cast<EVMDialect const&>(*m_dialect), meter}(*m_ast);
} }},
else if (m_optimizerStep == "varDeclInitializer") {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, *m_ast); }},
VarDeclInitializer::run(*m_context, *m_ast); {"varNameCleaner", [&]() {
else if (m_optimizerStep == "varNameCleaner")
{
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast);
VarNameCleaner::run(*m_context, *m_ast); VarNameCleaner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "forLoopConditionIntoBody") {"forLoopConditionIntoBody", [&]() {
{
disambiguate(); disambiguate();
ForLoopConditionIntoBody::run(*m_context, *m_ast); ForLoopConditionIntoBody::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "forLoopInitRewriter") {"forLoopInitRewriter", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "commonSubexpressionEliminator") {"commonSubexpressionEliminator", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "conditionalUnsimplifier") {"conditionalUnsimplifier", [&]() {
{
disambiguate(); disambiguate();
ConditionalUnsimplifier::run(*m_context, *m_ast); ConditionalUnsimplifier::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "conditionalSimplifier") {"conditionalSimplifier", [&]() {
{
disambiguate(); disambiguate();
ConditionalSimplifier::run(*m_context, *m_ast); ConditionalSimplifier::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "expressionSplitter") {"expressionSplitter", [&]() { ExpressionSplitter::run(*m_context, *m_ast); }},
ExpressionSplitter::run(*m_context, *m_ast); {"expressionJoiner", [&]() {
else if (m_optimizerStep == "expressionJoiner")
{
disambiguate(); disambiguate();
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "splitJoin") {"splitJoin", [&]() {
{
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "functionGrouper") {"functionGrouper", [&]() {
{
disambiguate(); disambiguate();
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "functionHoister") {"functionHoister", [&]() {
{
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "expressionInliner") {"expressionInliner", [&]() {
{
disambiguate(); disambiguate();
ExpressionInliner::run(*m_context, *m_ast); ExpressionInliner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "fullInliner") {"fullInliner", [&]() {
{
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast);
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_ast);
FullInliner::run(*m_context, *m_ast); FullInliner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "mainFunction") {"mainFunction", [&]() {
{
disambiguate(); disambiguate();
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast);
MainFunction::run(*m_context, *m_ast); MainFunction::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "rematerialiser") {"rematerialiser", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
Rematerialiser::run(*m_context, *m_ast); Rematerialiser::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "expressionSimplifier") {"expressionSimplifier", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
@ -213,9 +186,8 @@ bool YulOptimizerTestCommon::runStep()
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "fullSimplify") {"fullSimplify", [&]() {
{
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_ast);
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
@ -227,53 +199,45 @@ bool YulOptimizerTestCommon::runStep()
DeadCodeEliminator::run(*m_context, *m_ast); DeadCodeEliminator::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "unusedFunctionParameterPruner") {"unusedFunctionParameterPruner", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_object->code); FunctionHoister::run(*m_context, *m_object->code);
LiteralRematerialiser::run(*m_context, *m_object->code); LiteralRematerialiser::run(*m_context, *m_object->code);
UnusedFunctionParameterPruner::run(*m_context, *m_object->code); UnusedFunctionParameterPruner::run(*m_context, *m_object->code);
} }},
else if (m_optimizerStep == "unusedPruner") {"unusedPruner", [&]() {
{
disambiguate(); disambiguate();
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "circularReferencesPruner") {"circularReferencesPruner", [&]() {
{
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
CircularReferencesPruner::run(*m_context, *m_ast); CircularReferencesPruner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "deadCodeEliminator") {"deadCodeEliminator", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
DeadCodeEliminator::run(*m_context, *m_ast); DeadCodeEliminator::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "ssaTransform") {"ssaTransform", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
SSATransform::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "redundantAssignEliminator") {"redundantAssignEliminator", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
RedundantAssignEliminator::run(*m_context, *m_ast); RedundantAssignEliminator::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "ssaPlusCleanup") {"ssaPlusCleanup", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
SSATransform::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast);
RedundantAssignEliminator::run(*m_context, *m_ast); RedundantAssignEliminator::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "loadResolver") {"loadResolver", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
@ -286,47 +250,40 @@ bool YulOptimizerTestCommon::runStep()
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "loopInvariantCodeMotion") {"loopInvariantCodeMotion", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
LoopInvariantCodeMotion::run(*m_context, *m_ast); LoopInvariantCodeMotion::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "controlFlowSimplifier") {"controlFlowSimplifier", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
ControlFlowSimplifier::run(*m_context, *m_ast); ControlFlowSimplifier::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "structuralSimplifier") {"structuralSimplifier", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
LiteralRematerialiser::run(*m_context, *m_ast); LiteralRematerialiser::run(*m_context, *m_ast);
StructuralSimplifier::run(*m_context, *m_ast); StructuralSimplifier::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "reasoningBasedSimplifier") {"reasoningBasedSimplifier", [&]() {
{
disambiguate(); disambiguate();
ReasoningBasedSimplifier::run(*m_context, *m_object->code); ReasoningBasedSimplifier::run(*m_context, *m_object->code);
} }},
else if (m_optimizerStep == "equivalentFunctionCombiner") {"equivalentFunctionCombiner", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
EquivalentFunctionCombiner::run(*m_context, *m_ast); EquivalentFunctionCombiner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "ssaReverser") {"ssaReverser", [&]() {
{
disambiguate(); disambiguate();
SSAReverser::run(*m_context, *m_ast); SSAReverser::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "ssaAndBack") {"ssaAndBack", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
// apply SSA // apply SSA
@ -337,9 +294,8 @@ bool YulOptimizerTestCommon::runStep()
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_ast);
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "stackCompressor") {"stackCompressor", [&]() {
{
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast);
@ -347,29 +303,25 @@ bool YulOptimizerTestCommon::runStep()
size_t maxIterations = 16; size_t maxIterations = 16;
StackCompressor::run(*m_dialect, *m_object, true, maxIterations); StackCompressor::run(*m_dialect, *m_object, true, maxIterations);
BlockFlattener::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_ast);
} }},
else if (m_optimizerStep == "wordSizeTransform") {"wordSizeTransform", [&]() {
{
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_ast);
WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser); WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser);
} }},
else if (m_optimizerStep == "fullSuite") {"fullSuite", [&]() {
{
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200); GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps);
} }},
else if (m_optimizerStep == "stackLimitEvader") {"stackLimitEvader", [&]() {
{
disambiguate(); disambiguate();
StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{
*m_dialect, *m_dialect,
*m_object, *m_object,
true true
}.unreachableVariables); }.unreachableVariables);
} }},
else if (m_optimizerStep == "fakeStackLimitEvader") {"fakeStackLimitEvader", [&]() {
{
disambiguate(); disambiguate();
// Mark all variables with a name starting with "$" for escalation to memory. // Mark all variables with a name starting with "$" for escalation to memory.
struct FakeUnreachableGenerator: ASTWalker struct FakeUnreachableGenerator: ASTWalker
@ -404,7 +356,18 @@ bool YulOptimizerTestCommon::runStep()
FakeUnreachableGenerator fakeUnreachableGenerator; FakeUnreachableGenerator fakeUnreachableGenerator;
fakeUnreachableGenerator(*m_ast); fakeUnreachableGenerator(*m_ast);
StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables);
}}
};
} }
bool YulOptimizerTestCommon::runStep()
{
yulAssert(m_dialect, "Dialect not set.");
updateContext();
if (m_namedSteps.count(m_optimizerStep))
m_namedSteps[m_optimizerStep]();
else else
return false; return false;

View File

@ -63,6 +63,7 @@ private:
std::shared_ptr<Object> m_object; std::shared_ptr<Object> m_object;
std::shared_ptr<Block> m_ast; std::shared_ptr<Block> m_ast;
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo; std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
std::map<std::string, std::function<void(void)>> m_namedSteps;
}; };
} }