Merge pull request #9572 from ethereum/yul-optimiser-tests

Return object format in expectation for yulOptimizerTests
This commit is contained in:
Alex Beregszaszi 2020-08-05 12:57:01 +01:00 committed by GitHub
commit a21c8e18f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 105 deletions

View File

@ -76,7 +76,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin
return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo); return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo);
} }
pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse( pair<shared_ptr<Object>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(
string const& _source, string const& _source,
Dialect const& _dialect, Dialect const& _dialect,
ErrorList& _errors ErrorList& _errors
@ -94,7 +94,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(
// TODO this should be done recursively. // TODO this should be done recursively.
if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors()) if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors())
return {}; return {};
return {std::move(parserResult->code), std::move(analysisInfo)}; return {std::move(parserResult), std::move(analysisInfo)};
} }
yul::Block yul::test::disambiguate(string const& _source, bool _yul) yul::Block yul::test::disambiguate(string const& _source, bool _yul)

View File

@ -21,8 +21,6 @@
#pragma once #pragma once
#include <libyul/AsmData.h>
#include <liblangutil/EVMVersion.h> #include <liblangutil/EVMVersion.h>
#include <string> #include <string>
@ -38,6 +36,8 @@ using ErrorList = std::vector<std::shared_ptr<Error const>>;
namespace solidity::yul namespace solidity::yul
{ {
struct AsmAnalysisInfo; struct AsmAnalysisInfo;
struct Block;
struct Object;
struct Dialect; struct Dialect;
} }
@ -49,7 +49,7 @@ void printErrors(langutil::ErrorList const& _errors);
std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>> std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>>
parse(std::string const& _source, bool _yul = true); parse(std::string const& _source, bool _yul = true);
std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>> std::pair<std::shared_ptr<Object>, std::shared_ptr<AsmAnalysisInfo>>
parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors);
Block disambiguate(std::string const& _source, bool _yul = true); Block disambiguate(std::string const& _source, bool _yul = true);

View File

@ -28,6 +28,7 @@
#include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/FunctionHoister.h>
#include <libyul/optimiser/FunctionGrouper.h> #include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/AsmPrinter.h> #include <libyul/AsmPrinter.h>
#include <libyul/AsmData.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>

View File

@ -126,225 +126,225 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
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_object->code);
} }
else if (m_optimizerStep == "blockFlattener") else if (m_optimizerStep == "blockFlattener")
{ {
disambiguate(); disambiguate();
BlockFlattener::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "constantOptimiser") else if (m_optimizerStep == "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_object->code);
} }
else if (m_optimizerStep == "varDeclInitializer") else if (m_optimizerStep == "varDeclInitializer")
VarDeclInitializer::run(*m_context, *m_ast); VarDeclInitializer::run(*m_context, *m_object->code);
else if (m_optimizerStep == "varNameCleaner") else if (m_optimizerStep == "varNameCleaner")
VarNameCleaner::run(*m_context, *m_ast); VarNameCleaner::run(*m_context, *m_object->code);
else if (m_optimizerStep == "forLoopConditionIntoBody") else if (m_optimizerStep == "forLoopConditionIntoBody")
{ {
disambiguate(); disambiguate();
ForLoopConditionIntoBody::run(*m_context, *m_ast); ForLoopConditionIntoBody::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "forLoopInitRewriter") else if (m_optimizerStep == "forLoopInitRewriter")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "commonSubexpressionEliminator") else if (m_optimizerStep == "commonSubexpressionEliminator")
{ {
disambiguate(); disambiguate();
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "conditionalUnsimplifier") else if (m_optimizerStep == "conditionalUnsimplifier")
{ {
disambiguate(); disambiguate();
ConditionalUnsimplifier::run(*m_context, *m_ast); ConditionalUnsimplifier::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "conditionalSimplifier") else if (m_optimizerStep == "conditionalSimplifier")
{ {
disambiguate(); disambiguate();
ConditionalSimplifier::run(*m_context, *m_ast); ConditionalSimplifier::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "expressionSplitter") else if (m_optimizerStep == "expressionSplitter")
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
else if (m_optimizerStep == "expressionJoiner") else if (m_optimizerStep == "expressionJoiner")
{ {
disambiguate(); disambiguate();
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "splitJoin") else if (m_optimizerStep == "splitJoin")
{ {
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "functionGrouper") else if (m_optimizerStep == "functionGrouper")
{ {
disambiguate(); disambiguate();
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "functionHoister") else if (m_optimizerStep == "functionHoister")
{ {
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "expressionInliner") else if (m_optimizerStep == "expressionInliner")
{ {
disambiguate(); disambiguate();
ExpressionInliner::run(*m_context, *m_ast); ExpressionInliner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "fullInliner") else if (m_optimizerStep == "fullInliner")
{ {
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_object->code);
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_object->code);
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
FullInliner::run(*m_context, *m_ast); FullInliner::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "mainFunction") else if (m_optimizerStep == "mainFunction")
{ {
disambiguate(); disambiguate();
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_object->code);
MainFunction::run(*m_context, *m_ast); MainFunction::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "rematerialiser") else if (m_optimizerStep == "rematerialiser")
{ {
disambiguate(); disambiguate();
Rematerialiser::run(*m_context, *m_ast); Rematerialiser::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "expressionSimplifier") else if (m_optimizerStep == "expressionSimplifier")
{ {
disambiguate(); disambiguate();
ExpressionSimplifier::run(*m_context, *m_ast); ExpressionSimplifier::run(*m_context, *m_object->code);
ExpressionSimplifier::run(*m_context, *m_ast); ExpressionSimplifier::run(*m_context, *m_object->code);
ExpressionSimplifier::run(*m_context, *m_ast); ExpressionSimplifier::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "fullSimplify") else if (m_optimizerStep == "fullSimplify")
{ {
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_object->code);
ExpressionSimplifier::run(*m_context, *m_ast); ExpressionSimplifier::run(*m_context, *m_object->code);
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_object->code);
CircularReferencesPruner::run(*m_context, *m_ast); CircularReferencesPruner::run(*m_context, *m_object->code);
DeadCodeEliminator::run(*m_context, *m_ast); DeadCodeEliminator::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "unusedPruner") else if (m_optimizerStep == "unusedPruner")
{ {
disambiguate(); disambiguate();
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "circularReferencesPruner") else if (m_optimizerStep == "circularReferencesPruner")
{ {
disambiguate(); disambiguate();
FunctionHoister::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_object->code);
CircularReferencesPruner::run(*m_context, *m_ast); CircularReferencesPruner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "deadCodeEliminator") else if (m_optimizerStep == "deadCodeEliminator")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
DeadCodeEliminator::run(*m_context, *m_ast); DeadCodeEliminator::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "ssaTransform") else if (m_optimizerStep == "ssaTransform")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
SSATransform::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "redundantAssignEliminator") else if (m_optimizerStep == "redundantAssignEliminator")
{ {
disambiguate(); disambiguate();
RedundantAssignEliminator::run(*m_context, *m_ast); RedundantAssignEliminator::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "ssaPlusCleanup") else if (m_optimizerStep == "ssaPlusCleanup")
{ {
disambiguate(); disambiguate();
SSATransform::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_object->code);
RedundantAssignEliminator::run(*m_context, *m_ast); RedundantAssignEliminator::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "loadResolver") else if (m_optimizerStep == "loadResolver")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_object->code);
ExpressionSimplifier::run(*m_context, *m_ast); ExpressionSimplifier::run(*m_context, *m_object->code);
LoadResolver::run(*m_context, *m_ast); LoadResolver::run(*m_context, *m_object->code);
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "loopInvariantCodeMotion") else if (m_optimizerStep == "loopInvariantCodeMotion")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
LoopInvariantCodeMotion::run(*m_context, *m_ast); LoopInvariantCodeMotion::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "controlFlowSimplifier") else if (m_optimizerStep == "controlFlowSimplifier")
{ {
disambiguate(); disambiguate();
ControlFlowSimplifier::run(*m_context, *m_ast); ControlFlowSimplifier::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "structuralSimplifier") else if (m_optimizerStep == "structuralSimplifier")
{ {
disambiguate(); disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_object->code);
LiteralRematerialiser::run(*m_context, *m_ast); LiteralRematerialiser::run(*m_context, *m_object->code);
StructuralSimplifier::run(*m_context, *m_ast); StructuralSimplifier::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "equivalentFunctionCombiner") else if (m_optimizerStep == "equivalentFunctionCombiner")
{ {
disambiguate(); disambiguate();
EquivalentFunctionCombiner::run(*m_context, *m_ast); EquivalentFunctionCombiner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "ssaReverser") else if (m_optimizerStep == "ssaReverser")
{ {
disambiguate(); disambiguate();
SSAReverser::run(*m_context, *m_ast); SSAReverser::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "ssaAndBack") else if (m_optimizerStep == "ssaAndBack")
{ {
disambiguate(); disambiguate();
// apply SSA // apply SSA
SSATransform::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_object->code);
RedundantAssignEliminator::run(*m_context, *m_ast); RedundantAssignEliminator::run(*m_context, *m_object->code);
// reverse SSA // reverse SSA
SSAReverser::run(*m_context, *m_ast); SSAReverser::run(*m_context, *m_object->code);
CommonSubexpressionEliminator::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_object->code);
UnusedPruner::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "stackCompressor") else if (m_optimizerStep == "stackCompressor")
{ {
disambiguate(); disambiguate();
FunctionGrouper::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_object->code);
size_t maxIterations = 16; size_t maxIterations = 16;
Object obj; Object obj;
obj.code = m_ast; obj.code = m_object->code;
StackCompressor::run(*m_dialect, obj, true, maxIterations); StackCompressor::run(*m_dialect, obj, true, maxIterations);
m_ast = obj.code; m_object->code = obj.code;
BlockFlattener::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_object->code);
} }
else if (m_optimizerStep == "wordSizeTransform") else if (m_optimizerStep == "wordSizeTransform")
{ {
disambiguate(); disambiguate();
ExpressionSplitter::run(*m_context, *m_ast); ExpressionSplitter::run(*m_context, *m_object->code);
WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser); WordSizeTransform::run(*m_dialect, *m_dialect, *m_object->code, *m_nameDispenser);
} }
else if (m_optimizerStep == "fullSuite") else if (m_optimizerStep == "fullSuite")
{ {
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200); GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
yul::Object obj; yul::Object obj;
obj.code = m_ast; obj.code = m_object->code;
obj.analysisInfo = m_analysisInfo; obj.analysisInfo = m_analysisInfo;
OptimiserSuite::run(*m_dialect, &meter, obj, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps); OptimiserSuite::run(*m_dialect, &meter, obj, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps);
} }
@ -354,7 +354,10 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
return TestResult::FatalError; return TestResult::FatalError;
} }
m_obtainedResult = "step: " + m_optimizerStep + "\n\n" + AsmPrinter{ *m_dialect }(*m_ast) + "\n"; m_obtainedResult =
"step: " + m_optimizerStep + "\n\n" +
(m_object->subObjects.empty() ? AsmPrinter{ *m_dialect }(*m_object->code) : m_object->toString(m_dialect)) +
"\n";
return checkResult(_stream, _linePrefix, _formatted); return checkResult(_stream, _linePrefix, _formatted);
} }
@ -363,8 +366,8 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
{ {
ErrorList errors; ErrorList errors;
soltestAssert(m_dialect, ""); soltestAssert(m_dialect, "");
std::tie(m_ast, m_analysisInfo) = yul::test::parse(m_source, *m_dialect, errors); std::tie(m_object, m_analysisInfo) = yul::test::parse(m_source, *m_dialect, errors);
if (!m_ast || !m_analysisInfo || !Error::containsOnlyWarnings(errors)) if (!m_object || !m_analysisInfo || !Error::containsOnlyWarnings(errors))
{ {
AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
printErrors(_stream, errors); printErrors(_stream, errors);
@ -375,14 +378,14 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
void YulOptimizerTest::disambiguate() void YulOptimizerTest::disambiguate()
{ {
*m_ast = std::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast)); *m_object->code = std::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_object->code));
m_analysisInfo.reset(); m_analysisInfo.reset();
updateContext(); updateContext();
} }
void YulOptimizerTest::updateContext() void YulOptimizerTest::updateContext()
{ {
m_nameDispenser = make_unique<NameDispenser>(*m_dialect, *m_ast, m_reservedIdentifiers); m_nameDispenser = make_unique<NameDispenser>(*m_dialect, *m_object->code, m_reservedIdentifiers);
m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{ m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{
*m_dialect, *m_dialect,
*m_nameDispenser, *m_nameDispenser,

View File

@ -38,7 +38,7 @@ using ErrorList = std::vector<std::shared_ptr<Error const>>;
namespace solidity::yul namespace solidity::yul
{ {
struct AsmAnalysisInfo; struct AsmAnalysisInfo;
struct Block; struct Object;
struct Dialect; struct Dialect;
} }
@ -71,7 +71,7 @@ private:
std::unique_ptr<NameDispenser> m_nameDispenser; std::unique_ptr<NameDispenser> m_nameDispenser;
std::unique_ptr<OptimiserStepContext> m_context; std::unique_ptr<OptimiserStepContext> m_context;
std::shared_ptr<Block> m_ast; std::shared_ptr<Object> m_object;
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo; std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
}; };

View File

@ -17,7 +17,8 @@ object "main" {
// ---- // ----
// step: commonSubexpressionEliminator // step: commonSubexpressionEliminator
// //
// { // object "main" {
// code {
// let r := "abc" // let r := "abc"
// let a := datasize("abc") // let a := datasize("abc")
// let x := dataoffset("abc") // let x := dataoffset("abc")
@ -25,3 +26,5 @@ object "main" {
// datacopy(r, x, a) // datacopy(r, x, a)
// mstore(a, x) // mstore(a, x)
// } // }
// data "abc" hex"48656c6c6f2c20576f726c6421"
// }

View File

@ -12,7 +12,8 @@ object "main" {
// ---- // ----
// step: expressionSplitter // step: expressionSplitter
// //
// { // object "main" {
// code {
// let x := dataoffset("abc") // let x := dataoffset("abc")
// let y := datasize("abc") // let y := datasize("abc")
// let _1 := 2 // let _1 := 2
@ -23,3 +24,5 @@ object "main" {
// let _6 := mload(_5) // let _6 := mload(_5)
// datacopy(_6, _4, _2) // datacopy(_6, _4, _2)
// } // }
// data "abc" hex"48656c6c6f2c20576f726c6421"
// }