mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8215 from imapp-pl/yul-optimiser-step-abbreviations
Yul optimiser step abbreviations
This commit is contained in:
commit
967ce8dd51
@ -156,6 +156,23 @@ T convertContainer(U&& _from)
|
||||
};
|
||||
}
|
||||
|
||||
/// Gets a @a K -> @a V map and returns a map where values from the original map are keys and keys
|
||||
/// from the original map are values.
|
||||
///
|
||||
/// @pre @a originalMap must have unique values.
|
||||
template <typename K, typename V>
|
||||
std::map<V, K> invertMap(std::map<K, V> const& originalMap)
|
||||
{
|
||||
std::map<V, K> inverseMap;
|
||||
for (auto const& originalPair: originalMap)
|
||||
{
|
||||
assert(inverseMap.count(originalPair.second) == 0);
|
||||
inverseMap.insert({originalPair.second, originalPair.first});
|
||||
}
|
||||
|
||||
return inverseMap;
|
||||
}
|
||||
|
||||
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
||||
|
||||
enum class WhenError
|
||||
|
@ -370,6 +370,49 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
||||
return instance;
|
||||
}
|
||||
|
||||
map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
|
||||
{
|
||||
static map<string, char> lookupTable{
|
||||
{BlockFlattener::name, 'f'},
|
||||
{CommonSubexpressionEliminator::name, 'c'},
|
||||
{ConditionalSimplifier::name, 'C'},
|
||||
{ConditionalUnsimplifier::name, 'U'},
|
||||
{ControlFlowSimplifier::name, 'n'},
|
||||
{DeadCodeEliminator::name, 'D'},
|
||||
{EquivalentFunctionCombiner::name, 'v'},
|
||||
{ExpressionInliner::name, 'e'},
|
||||
{ExpressionJoiner::name, 'j'},
|
||||
{ExpressionSimplifier::name, 's'},
|
||||
{ExpressionSplitter::name, 'x'},
|
||||
{ForLoopConditionIntoBody::name, 'I'},
|
||||
{ForLoopConditionOutOfBody::name, 'O'},
|
||||
{ForLoopInitRewriter::name, 'o'},
|
||||
{FullInliner::name, 'i'},
|
||||
{FunctionGrouper::name, 'g'},
|
||||
{FunctionHoister::name, 'h'},
|
||||
{LiteralRematerialiser::name, 'T'},
|
||||
{LoadResolver::name, 'L'},
|
||||
{LoopInvariantCodeMotion::name, 'M'},
|
||||
{RedundantAssignEliminator::name, 'r'},
|
||||
{Rematerialiser::name, 'm'},
|
||||
{SSAReverser::name, 'V'},
|
||||
{SSATransform::name, 'a'},
|
||||
{StructuralSimplifier::name, 't'},
|
||||
{UnusedPruner::name, 'u'},
|
||||
{VarDeclInitializer::name, 'd'},
|
||||
};
|
||||
yulAssert(lookupTable.size() == allSteps().size(), "");
|
||||
|
||||
return lookupTable;
|
||||
}
|
||||
|
||||
map<char, string> const& OptimiserSuite::stepAbbreviationToNameMap()
|
||||
{
|
||||
static map<char, string> lookupTable = util::invertMap(stepNameToAbbreviationMap());
|
||||
|
||||
return lookupTable;
|
||||
}
|
||||
|
||||
void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
|
||||
{
|
||||
unique_ptr<Block> copy;
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
void runSequence(std::vector<std::string> const& _steps, Block& _ast);
|
||||
|
||||
static std::map<std::string, std::unique_ptr<OptimiserStep>> const& allSteps();
|
||||
static std::map<std::string, char> const& stepNameToAbbreviationMap();
|
||||
static std::map<char, std::string> const& stepAbbreviationToNameMap();
|
||||
|
||||
private:
|
||||
OptimiserSuite(
|
||||
|
@ -30,40 +30,11 @@
|
||||
#include <libyul/Object.h>
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <libyul/optimiser/BlockFlattener.h>
|
||||
#include <libyul/optimiser/Disambiguator.h>
|
||||
#include <libyul/optimiser/CallGraphGenerator.h>
|
||||
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||
#include <libyul/optimiser/ConditionalSimplifier.h>
|
||||
#include <libyul/optimiser/ConditionalUnsimplifier.h>
|
||||
#include <libyul/optimiser/ControlFlowSimplifier.h>
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||
#include <libyul/optimiser/ExpressionSplitter.h>
|
||||
#include <libyul/optimiser/FunctionGrouper.h>
|
||||
#include <libyul/optimiser/FunctionHoister.h>
|
||||
#include <libyul/optimiser/ExpressionInliner.h>
|
||||
#include <libyul/optimiser/FullInliner.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||
#include <libyul/optimiser/MainFunction.h>
|
||||
#include <libyul/optimiser/Rematerialiser.h>
|
||||
#include <libyul/optimiser/ExpressionSimplifier.h>
|
||||
#include <libyul/optimiser/UnusedPruner.h>
|
||||
#include <libyul/optimiser/DeadCodeEliminator.h>
|
||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||
#include <libyul/optimiser/OptimiserStep.h>
|
||||
#include <libyul/optimiser/RedundantAssignEliminator.h>
|
||||
#include <libyul/optimiser/SSAReverser.h>
|
||||
#include <libyul/optimiser/SSATransform.h>
|
||||
#include <libyul/optimiser/StackCompressor.h>
|
||||
#include <libyul/optimiser/StructuralSimplifier.h>
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
#include <libyul/optimiser/VarDeclInitializer.h>
|
||||
#include <libyul/optimiser/VarNameCleaner.h>
|
||||
#include <libyul/optimiser/LoadResolver.h>
|
||||
#include <libyul/optimiser/LoopInvariantCodeMotion.h>
|
||||
#include <libyul/optimiser/Suite.h>
|
||||
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
@ -122,6 +93,40 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void printUsageBanner(
|
||||
map<char, string> const& _optimizationSteps,
|
||||
map<char, string> const& _extraOptions,
|
||||
size_t _columns
|
||||
)
|
||||
{
|
||||
auto hasShorterString = [](auto const& a, auto const& b){ return a.second.size() < b.second.size(); };
|
||||
size_t longestDescriptionLength = max(
|
||||
max_element(_optimizationSteps.begin(), _optimizationSteps.end(), hasShorterString)->second.size(),
|
||||
max_element(_extraOptions.begin(), _extraOptions.end(), hasShorterString)->second.size()
|
||||
);
|
||||
|
||||
size_t index = 0;
|
||||
auto printPair = [&](auto const& optionAndDescription)
|
||||
{
|
||||
cout << optionAndDescription.first << ": ";
|
||||
cout << setw(longestDescriptionLength) << setiosflags(ios::left);
|
||||
cout << optionAndDescription.second << " ";
|
||||
|
||||
++index;
|
||||
if (index % _columns == 0)
|
||||
cout << endl;
|
||||
};
|
||||
|
||||
for (auto const& optionAndDescription: _extraOptions)
|
||||
{
|
||||
yulAssert(_optimizationSteps.count(optionAndDescription.first) == 0, "");
|
||||
printPair(optionAndDescription);
|
||||
}
|
||||
|
||||
for (auto const& abbreviationAndName: _optimizationSteps)
|
||||
printPair(abbreviationAndName);
|
||||
}
|
||||
|
||||
void runInteractive(string source)
|
||||
{
|
||||
bool disambiguated = false;
|
||||
@ -139,101 +144,36 @@ public:
|
||||
m_nameDispenser = make_shared<NameDispenser>(m_dialect, *m_ast, reservedIdentifiers);
|
||||
disambiguated = true;
|
||||
}
|
||||
cout << "(q)uit/(f)latten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl;
|
||||
cout << " (e)xpr inline/(i)nline/(s)implify/varname c(l)eaner/(u)nusedprune/ss(a) transform/" << endl;
|
||||
cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-init-rewriter/for-loop-condition-(I)nto-body/" << endl;
|
||||
cout << " for-loop-condition-(O)ut-of-body/s(t)ructural simplifier/equi(v)alent function combiner/ssa re(V)erser/" << endl;
|
||||
cout << " co(n)trol flow simplifier/stack com(p)ressor/(D)ead code eliminator/(L)oad resolver/" << endl;
|
||||
cout << " (C)onditional simplifier/conditional (U)nsimplifier/loop-invariant code (M)otion?" << endl;
|
||||
map<char, string> const& abbreviationMap = OptimiserSuite::stepAbbreviationToNameMap();
|
||||
map<char, string> const& extraOptions = {
|
||||
{'q', "quit"},
|
||||
{'l', "VarNameCleaner"},
|
||||
{'p', "StackCompressor"},
|
||||
};
|
||||
|
||||
printUsageBanner(abbreviationMap, extraOptions, 4);
|
||||
cout << "? ";
|
||||
cout.flush();
|
||||
int option = readStandardInputChar();
|
||||
cout << ' ' << char(option) << endl;
|
||||
|
||||
OptimiserStepContext context{m_dialect, *m_nameDispenser, reservedIdentifiers};
|
||||
switch (option)
|
||||
|
||||
auto abbreviationAndName = abbreviationMap.find(option);
|
||||
if (abbreviationAndName != abbreviationMap.end())
|
||||
{
|
||||
OptimiserStep const& step = *OptimiserSuite::allSteps().at(abbreviationAndName->second);
|
||||
step.run(context, *m_ast);
|
||||
}
|
||||
else switch (option)
|
||||
{
|
||||
case 'q':
|
||||
return;
|
||||
case 'f':
|
||||
BlockFlattener::run(context, *m_ast);
|
||||
break;
|
||||
case 'o':
|
||||
ForLoopInitRewriter::run(context, *m_ast);
|
||||
break;
|
||||
case 'O':
|
||||
ForLoopConditionOutOfBody::run(context, *m_ast);
|
||||
break;
|
||||
case 'I':
|
||||
ForLoopConditionIntoBody::run(context, *m_ast);
|
||||
break;
|
||||
case 'c':
|
||||
CommonSubexpressionEliminator::run(context, *m_ast);
|
||||
break;
|
||||
case 'C':
|
||||
ConditionalSimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 'U':
|
||||
ConditionalUnsimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 'd':
|
||||
VarDeclInitializer::run(context, *m_ast);
|
||||
break;
|
||||
case 'l':
|
||||
VarNameCleaner::run(context, *m_ast);
|
||||
// VarNameCleaner destroys the unique names guarantee of the disambiguator.
|
||||
disambiguated = false;
|
||||
break;
|
||||
case 'x':
|
||||
ExpressionSplitter::run(context, *m_ast);
|
||||
break;
|
||||
case 'j':
|
||||
ExpressionJoiner::run(context, *m_ast);
|
||||
break;
|
||||
case 'g':
|
||||
FunctionGrouper::run(context, *m_ast);
|
||||
break;
|
||||
case 'h':
|
||||
FunctionHoister::run(context, *m_ast);
|
||||
break;
|
||||
case 'e':
|
||||
ExpressionInliner::run(context, *m_ast);
|
||||
break;
|
||||
case 'i':
|
||||
FullInliner::run(context, *m_ast);
|
||||
break;
|
||||
case 's':
|
||||
ExpressionSimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 't':
|
||||
StructuralSimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 'T':
|
||||
LiteralRematerialiser::run(context, *m_ast);
|
||||
break;
|
||||
case 'n':
|
||||
ControlFlowSimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 'u':
|
||||
UnusedPruner::run(context, *m_ast);
|
||||
break;
|
||||
case 'D':
|
||||
DeadCodeEliminator::run(context, *m_ast);
|
||||
break;
|
||||
case 'a':
|
||||
SSATransform::run(context, *m_ast);
|
||||
break;
|
||||
case 'r':
|
||||
RedundantAssignEliminator::run(context, *m_ast);
|
||||
break;
|
||||
case 'm':
|
||||
Rematerialiser::run(context, *m_ast);
|
||||
break;
|
||||
case 'v':
|
||||
EquivalentFunctionCombiner::run(context, *m_ast);
|
||||
break;
|
||||
case 'V':
|
||||
SSAReverser::run(context, *m_ast);
|
||||
break;
|
||||
case 'p':
|
||||
{
|
||||
Object obj;
|
||||
@ -241,12 +181,6 @@ public:
|
||||
StackCompressor::run(m_dialect, obj, true, 16);
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
LoadResolver::run(context, *m_ast);
|
||||
break;
|
||||
case 'M':
|
||||
LoopInvariantCodeMotion::run(context, *m_ast);
|
||||
break;
|
||||
default:
|
||||
cout << "Unknown option." << endl;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user