diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index ecfece5d0..6b98f92c5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -15,6 +15,8 @@ install(TARGETS solidity-upgrade DESTINATION "${CMAKE_INSTALL_BINDIR}") add_executable(yul-phaser yulPhaser/main.cpp + yulPhaser/Chromosome.h + yulPhaser/Chromosome.cpp yulPhaser/Program.h yulPhaser/Program.cpp yulPhaser/Random.h diff --git a/tools/yulPhaser/Chromosome.cpp b/tools/yulPhaser/Chromosome.cpp new file mode 100644 index 000000000..6e887bd11 --- /dev/null +++ b/tools/yulPhaser/Chromosome.cpp @@ -0,0 +1,112 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#include + +#include + +#include +#include + +#include + +using namespace std; +using namespace solidity; +using namespace solidity::util; +using namespace solidity::yul; +using namespace solidity::phaser; + +namespace solidity::phaser +{ + +ostream& operator<<(ostream& _stream, Chromosome const& _chromosome); + +} + +Chromosome Chromosome::makeRandom(size_t _length) +{ + vector steps; + for (size_t i = 0; i < _length; ++i) + steps.push_back(randomOptimisationStep()); + + return Chromosome(move(steps)); +} + +ostream& phaser::operator<<(ostream& _stream, Chromosome const& _chromosome) +{ + for (auto const& stepName: _chromosome.m_optimisationSteps) + _stream << OptimiserSuite::stepNameToAbbreviationMap().at(stepName); + + return _stream; +} + +vector Chromosome::allStepNames() +{ + vector stepNames; + for (auto const& step: OptimiserSuite::allSteps()) + stepNames.push_back(step.first); + + return stepNames; +} + +vector Chromosome::allStepNamesExcept(vector const& _excludedStepNames) +{ + // This is not very efficient but vectors are small and the caller will cache the results anyway. + // What matters a bit more is that using vector rather than a set gives us O(1) access to + // random elements in other functions. + return convertContainer>( + convertContainer>(allStepNames()) - + convertContainer>(_excludedStepNames) + ); +} + +string const& Chromosome::randomOptimisationStep() +{ + static vector stepNames = allStepNamesExcept({ + // All possible steps, listed and commented-out for easy tweaking. + // The uncommented ones are not used (possibly because they fail). + //{BlockFlattener::name}, + //{CommonSubexpressionEliminator::name}, + //{ConditionalSimplifier::name}, + //{ConditionalUnsimplifier::name}, + //{ControlFlowSimplifier::name}, + //{DeadCodeEliminator::name}, + //{EquivalentFunctionCombiner::name}, + //{ExpressionInliner::name}, + //{ExpressionJoiner::name}, + //{ExpressionSimplifier::name}, + //{ExpressionSplitter::name}, + //{ForLoopConditionIntoBody::name}, + //{ForLoopConditionOutOfBody::name}, + //{ForLoopInitRewriter::name}, + //{FullInliner::name}, + //{FunctionGrouper::name}, + //{FunctionHoister::name}, + //{LiteralRematerialiser::name}, + //{LoadResolver::name}, + //{LoopInvariantCodeMotion::name}, + //{RedundantAssignEliminator::name}, + //{Rematerialiser::name}, + //{SSAReverser::name}, + //{SSATransform::name}, + //{StructuralSimplifier::name}, + //{UnusedPruner::name}, + //{VarDeclInitializer::name}, + }); + + return stepNames[uniformRandomInt(0, stepNames.size() - 1)]; +} diff --git a/tools/yulPhaser/Chromosome.h b/tools/yulPhaser/Chromosome.h new file mode 100644 index 000000000..84b33d356 --- /dev/null +++ b/tools/yulPhaser/Chromosome.h @@ -0,0 +1,65 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ + +#pragma once + +#include +#include +#include +#include + +namespace solidity::phaser +{ + +/** + * An object that represents a sequence of optimiser steps that can be applied to a program. + * Such sequences are used in our genetic algorithm to represent individual members of the + * population. + * + * To calculate the fitness of an individual one must apply its sequence to a specific program. + * This class does not provide any means to do so. It just stores information. + * + * Once created a sequence cannot be changed. The only way to mutate it is to generate a new + * chromosome based on the old one. + */ +class Chromosome +{ +public: + Chromosome() = default; + explicit Chromosome(std::vector _optimisationSteps): + m_optimisationSteps(std::move(_optimisationSteps)) {} + static Chromosome makeRandom(size_t _length); + + size_t length() const { return m_optimisationSteps.size(); } + std::vector const& optimisationSteps() const { return m_optimisationSteps; } + + friend std::ostream& operator<<(std::ostream& _stream, Chromosome const& _chromosome); + + bool operator==(Chromosome const& _other) const { return m_optimisationSteps == _other.m_optimisationSteps; } + bool operator!=(Chromosome const& _other) const { return !(*this == _other); } + +private: + static std::vector allStepNames(); + static std::vector allStepNamesExcept( + std::vector const& _excludedStepNames + ); + static std::string const& randomOptimisationStep(); + + std::vector m_optimisationSteps; +}; + +} diff --git a/tools/yulPhaser/main.cpp b/tools/yulPhaser/main.cpp index 6814acf6e..8bf32b135 100644 --- a/tools/yulPhaser/main.cpp +++ b/tools/yulPhaser/main.cpp @@ -15,6 +15,7 @@ along with solidity. If not, see . */ +#include #include #include @@ -39,8 +40,8 @@ struct CommandLineParsingResult void runAlgorithm(string const& _sourcePath) { - Program::load(_sourcePath); - cout << "Program load successful." << endl; + Program::load(_sourcePath).optimize(Chromosome::makeRandom(15).asSequence()); + cout << "Program load and optimization successful." << endl; } CommandLineParsingResult parseCommandLine(int argc, char** argv)