From 40dfac76838a96eb564acd19ad962e84cf3c60f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 29 Feb 2020 21:55:32 +0100 Subject: [PATCH] [yul-phaser] Require specifying weights for Program::codeSize() --- test/yulPhaser/AlgorithmRunner.cpp | 5 +- test/yulPhaser/FitnessMetrics.cpp | 77 ++++++++++++++++-------------- test/yulPhaser/Program.cpp | 2 +- test/yulPhaser/ProgramCache.cpp | 12 +++-- tools/yulPhaser/FitnessMetrics.cpp | 7 +-- tools/yulPhaser/FitnessMetrics.h | 9 +++- tools/yulPhaser/Phaser.cpp | 3 ++ tools/yulPhaser/Program.cpp | 4 +- tools/yulPhaser/Program.h | 5 +- tools/yulPhaser/ProgramCache.cpp | 4 +- 10 files changed, 76 insertions(+), 52 deletions(-) diff --git a/test/yulPhaser/AlgorithmRunner.cpp b/test/yulPhaser/AlgorithmRunner.cpp index 8dd6e7564..042cd4c2b 100644 --- a/test/yulPhaser/AlgorithmRunner.cpp +++ b/test/yulPhaser/AlgorithmRunner.cpp @@ -37,6 +37,7 @@ using namespace boost::unit_test::framework; using namespace boost::test_tools; using namespace solidity::langutil; using namespace solidity::util; +using namespace solidity::yul; namespace fs = boost::filesystem; @@ -299,8 +300,8 @@ BOOST_FIXTURE_TEST_CASE(run_should_print_cache_stats_if_requested, AlgorithmRunn make_shared(programs[1]), }; shared_ptr fitnessMetric = make_shared(vector>{ - make_shared(nullopt, caches[0]), - make_shared(nullopt, caches[1]), + make_shared(nullopt, caches[0], CodeWeights{}), + make_shared(nullopt, caches[1], CodeWeights{}), }); Population population = Population::makeRandom(fitnessMetric, 2, 0, 5); diff --git a/test/yulPhaser/FitnessMetrics.cpp b/test/yulPhaser/FitnessMetrics.cpp index 524ef6357..e668b54e9 100644 --- a/test/yulPhaser/FitnessMetrics.cpp +++ b/test/yulPhaser/FitnessMetrics.cpp @@ -62,12 +62,12 @@ protected: Program optimisedProgram(Program _program) const { - [[maybe_unused]] size_t originalSize = _program.codeSize(); + [[maybe_unused]] size_t originalSize = _program.codeSize(m_weights); Program result = move(_program); result.optimise(m_chromosome.optimisationSteps()); // Make sure that the program and the chromosome we have chosen are suitable for the test - assert(result.codeSize() != originalSize); + assert(result.codeSize(m_weights) != originalSize); return result; } @@ -77,15 +77,16 @@ protected: Program m_program = get(Program::load(m_sourceStream)); Program m_optimisedProgram = optimisedProgram(m_program); shared_ptr m_programCache = make_shared(m_program); + static constexpr CodeWeights m_weights{}; }; class FitnessMetricCombinationFixture: public ProgramBasedMetricFixture { protected: vector> m_simpleMetrics = { - make_shared(m_program, nullptr, 1), - make_shared(m_program, nullptr, 2), - make_shared(m_program, nullptr, 3), + make_shared(m_program, nullptr, m_weights, 1), + make_shared(m_program, nullptr, m_weights, 2), + make_shared(m_program, nullptr, m_weights, 3), }; vector m_fitness = { m_simpleMetrics[0]->evaluate(m_chromosome), @@ -100,7 +101,7 @@ BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest) BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(m_program, nullptr).optimisedProgram(m_chromosome)); + string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgram(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -108,7 +109,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program_even_if BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_use_cache_if_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(nullopt, m_programCache).optimisedProgram(m_chromosome)); + string code = toString(DummyProgramBasedMetric(nullopt, m_programCache, m_weights).optimisedProgram(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -117,7 +118,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_use_cache_if_available, ProgramB BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_return_optimised_program_even_if_cache_not_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(m_program, nullptr).optimisedProgramNoCache(m_chromosome)); + string code = toString(DummyProgramBasedMetric(m_program, nullptr, m_weights).optimisedProgramNoCache(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -125,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_return_optimised_program_ BOOST_FIXTURE_TEST_CASE(optimisedProgramNoCache_should_not_use_cache_even_if_available, ProgramBasedMetricFixture) { - string code = toString(DummyProgramBasedMetric(nullopt, m_programCache).optimisedProgramNoCache(m_chromosome)); + string code = toString(DummyProgramBasedMetric(nullopt, m_programCache, m_weights).optimisedProgramNoCache(m_chromosome)); BOOST_TEST(code != toString(m_program)); BOOST_TEST(code == toString(m_optimisedProgram)); @@ -137,18 +138,18 @@ BOOST_AUTO_TEST_SUITE(ProgramSizeTest) BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, ProgramBasedMetricFixture) { - size_t fitness = ProgramSize(m_program, nullptr).evaluate(m_chromosome); + size_t fitness = ProgramSize(m_program, nullptr, m_weights).evaluate(m_chromosome); - BOOST_TEST(fitness != m_program.codeSize()); - BOOST_TEST(fitness == m_optimisedProgram.codeSize()); + BOOST_TEST(fitness != m_program.codeSize(m_weights)); + BOOST_TEST(fitness == m_optimisedProgram.codeSize(m_weights)); } BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture) { - size_t fitness = ProgramSize(nullopt, m_programCache).evaluate(m_chromosome); + size_t fitness = ProgramSize(nullopt, m_programCache, m_weights).evaluate(m_chromosome); - BOOST_TEST(fitness != m_program.codeSize()); - BOOST_TEST(fitness == m_optimisedProgram.codeSize()); + BOOST_TEST(fitness != m_program.codeSize(m_weights)); + BOOST_TEST(fitness == m_optimisedProgram.codeSize(m_weights)); BOOST_TEST(m_programCache->size() == m_chromosome.length()); } @@ -157,21 +158,21 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number Program const& programOptimisedOnce = m_optimisedProgram; Program programOptimisedTwice = optimisedProgram(programOptimisedOnce); - ProgramSize metric(m_program, nullptr, 2); + ProgramSize metric(m_program, nullptr, m_weights, 2); size_t fitness = metric.evaluate(m_chromosome); - BOOST_TEST(fitness != m_program.codeSize()); - BOOST_TEST(fitness != programOptimisedOnce.codeSize()); - BOOST_TEST(fitness == programOptimisedTwice.codeSize()); + BOOST_TEST(fitness != m_program.codeSize(m_weights)); + BOOST_TEST(fitness != programOptimisedOnce.codeSize(m_weights)); + BOOST_TEST(fitness == programOptimisedTwice.codeSize(m_weights)); } BOOST_FIXTURE_TEST_CASE(evaluate_should_not_optimise_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture) { - ProgramSize metric(m_program, nullptr, 0); + ProgramSize metric(m_program, nullptr, m_weights, 0); size_t fitness = metric.evaluate(m_chromosome); - BOOST_TEST(fitness == m_program.codeSize()); - BOOST_TEST(fitness != m_optimisedProgram.codeSize()); + BOOST_TEST(fitness == m_program.codeSize(m_weights)); + BOOST_TEST(fitness != m_optimisedProgram.codeSize(m_weights)); } BOOST_AUTO_TEST_SUITE_END() @@ -179,12 +180,18 @@ BOOST_AUTO_TEST_SUITE(RelativeProgramSizeTest) BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_the_size_ratio_between_optimised_program_and_original_program, ProgramBasedMetricFixture) { - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 3).evaluate(m_chromosome) == round(1000.0 * m_optimisedProgram.codeSize() / m_program.codeSize())); + BOOST_TEST( + RelativeProgramSize(m_program, nullptr, 3, m_weights).evaluate(m_chromosome) == + round(1000.0 * m_optimisedProgram.codeSize(m_weights) / m_program.codeSize(m_weights)) + ); } BOOST_FIXTURE_TEST_CASE(evaluate_should_be_able_to_use_program_cache_if_available, ProgramBasedMetricFixture) { - BOOST_TEST(RelativeProgramSize(nullopt, m_programCache, 3).evaluate(m_chromosome) == round(1000.0 * m_optimisedProgram.codeSize() / m_program.codeSize())); + BOOST_TEST( + RelativeProgramSize(nullopt, m_programCache, 3, m_weights).evaluate(m_chromosome) == + round(1000.0 * m_optimisedProgram.codeSize(m_weights) / m_program.codeSize(m_weights)) + ); BOOST_TEST(m_programCache->size() == m_chromosome.length()); } @@ -193,17 +200,17 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number Program const& programOptimisedOnce = m_optimisedProgram; Program programOptimisedTwice = optimisedProgram(programOptimisedOnce); - RelativeProgramSize metric(m_program, nullptr, 3, 2); + RelativeProgramSize metric(m_program, nullptr, 3, m_weights, 2); size_t fitness = metric.evaluate(m_chromosome); BOOST_TEST(fitness != 1000); - BOOST_TEST(fitness != RelativeProgramSize(programOptimisedTwice, nullptr, 3, 1).evaluate(m_chromosome)); - BOOST_TEST(fitness == round(1000.0 * programOptimisedTwice.codeSize() / m_program.codeSize())); + BOOST_TEST(fitness != RelativeProgramSize(programOptimisedTwice, nullptr, 3, m_weights, 1).evaluate(m_chromosome)); + BOOST_TEST(fitness == round(1000.0 * programOptimisedTwice.codeSize(m_weights) / m_program.codeSize(m_weights))); } BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture) { - RelativeProgramSize metric(m_program, nullptr, 3, 0); + RelativeProgramSize metric(m_program, nullptr, 3, m_weights, 0); BOOST_TEST(metric.evaluate(m_chromosome) == 1000); } @@ -213,7 +220,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_the_original_program_size_ CharStream sourceStream = CharStream("{}", ""); Program program = get(Program::load(sourceStream)); - RelativeProgramSize metric(program, nullptr, 3); + RelativeProgramSize metric(program, nullptr, 3, m_weights); BOOST_TEST(metric.evaluate(m_chromosome) == 1000); BOOST_TEST(metric.evaluate(Chromosome("")) == 1000); @@ -222,12 +229,12 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_return_one_if_the_original_program_size_ BOOST_FIXTURE_TEST_CASE(evaluate_should_multiply_the_result_by_scaling_factor, ProgramBasedMetricFixture) { - double sizeRatio = static_cast(m_optimisedProgram.codeSize()) / m_program.codeSize(); - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 0).evaluate(m_chromosome) == round(1.0 * sizeRatio)); - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 1).evaluate(m_chromosome) == round(10.0 * sizeRatio)); - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 2).evaluate(m_chromosome) == round(100.0 * sizeRatio)); - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 3).evaluate(m_chromosome) == round(1000.0 * sizeRatio)); - BOOST_TEST(RelativeProgramSize(m_program, nullptr, 4).evaluate(m_chromosome) == round(10000.0 * sizeRatio)); + double sizeRatio = static_cast(m_optimisedProgram.codeSize(m_weights)) / m_program.codeSize(m_weights); + BOOST_TEST(RelativeProgramSize(m_program, nullptr, 0, m_weights).evaluate(m_chromosome) == round(1.0 * sizeRatio)); + BOOST_TEST(RelativeProgramSize(m_program, nullptr, 1, m_weights).evaluate(m_chromosome) == round(10.0 * sizeRatio)); + BOOST_TEST(RelativeProgramSize(m_program, nullptr, 2, m_weights).evaluate(m_chromosome) == round(100.0 * sizeRatio)); + BOOST_TEST(RelativeProgramSize(m_program, nullptr, 3, m_weights).evaluate(m_chromosome) == round(1000.0 * sizeRatio)); + BOOST_TEST(RelativeProgramSize(m_program, nullptr, 4, m_weights).evaluate(m_chromosome) == round(10000.0 * sizeRatio)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index e69f0fc5c..0a7520dd7 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -398,7 +398,7 @@ BOOST_AUTO_TEST_CASE(codeSize) CharStream sourceStream(sourceCode, current_test_case().p_name); Program program = get(Program::load(sourceStream)); - BOOST_TEST(program.codeSize() == CodeSize::codeSizeIncludingFunctions(program.ast())); + BOOST_TEST(program.codeSize(CodeWeights{}) == CodeSize::codeSizeIncludingFunctions(program.ast())); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/yulPhaser/ProgramCache.cpp b/test/yulPhaser/ProgramCache.cpp index 1ed6024bc..5e2a67c2a 100644 --- a/test/yulPhaser/ProgramCache.cpp +++ b/test/yulPhaser/ProgramCache.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -212,11 +214,11 @@ BOOST_FIXTURE_TEST_CASE(startRound_should_remove_entries_older_than_two_rounds, BOOST_FIXTURE_TEST_CASE(gatherStats_should_return_cache_statistics, ProgramCacheFixture) { - size_t sizeI = optimisedProgram(m_program, "I").codeSize(); - size_t sizeIu = optimisedProgram(m_program, "Iu").codeSize(); - size_t sizeIuO = optimisedProgram(m_program, "IuO").codeSize(); - size_t sizeL = optimisedProgram(m_program, "L").codeSize(); - size_t sizeLT = optimisedProgram(m_program, "LT").codeSize(); + size_t sizeI = optimisedProgram(m_program, "I").codeSize(CodeWeights{}); + size_t sizeIu = optimisedProgram(m_program, "Iu").codeSize(CodeWeights{}); + size_t sizeIuO = optimisedProgram(m_program, "IuO").codeSize(CodeWeights{}); + size_t sizeL = optimisedProgram(m_program, "L").codeSize(CodeWeights{}); + size_t sizeLT = optimisedProgram(m_program, "LT").codeSize(CodeWeights{}); m_programCache.optimiseProgram("L"); m_programCache.optimiseProgram("Iu"); diff --git a/tools/yulPhaser/FitnessMetrics.cpp b/tools/yulPhaser/FitnessMetrics.cpp index 5279cea72..134c13dfc 100644 --- a/tools/yulPhaser/FitnessMetrics.cpp +++ b/tools/yulPhaser/FitnessMetrics.cpp @@ -23,6 +23,7 @@ using namespace std; using namespace solidity::util; +using namespace solidity::yul; using namespace solidity::phaser; Program const& ProgramBasedMetric::program() const @@ -55,18 +56,18 @@ Program ProgramBasedMetric::optimisedProgramNoCache(Chromosome const& _chromosom size_t ProgramSize::evaluate(Chromosome const& _chromosome) { - return optimisedProgram(_chromosome).codeSize(); + return optimisedProgram(_chromosome).codeSize(codeWeights()); } size_t RelativeProgramSize::evaluate(Chromosome const& _chromosome) { size_t const scalingFactor = pow(10, m_fixedPointPrecision); - size_t unoptimisedSize = optimisedProgram(Chromosome("")).codeSize(); + size_t unoptimisedSize = optimisedProgram(Chromosome("")).codeSize(codeWeights()); if (unoptimisedSize == 0) return scalingFactor; - size_t optimisedSize = optimisedProgram(_chromosome).codeSize(); + size_t optimisedSize = optimisedProgram(_chromosome).codeSize(codeWeights()); return static_cast(round( static_cast(optimisedSize) / unoptimisedSize * scalingFactor diff --git a/tools/yulPhaser/FitnessMetrics.h b/tools/yulPhaser/FitnessMetrics.h index 72e811152..50f4c896f 100644 --- a/tools/yulPhaser/FitnessMetrics.h +++ b/tools/yulPhaser/FitnessMetrics.h @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -64,10 +66,12 @@ public: explicit ProgramBasedMetric( std::optional _program, std::shared_ptr _programCache, + yul::CodeWeights const& _codeWeights, size_t _repetitionCount = 1 ): m_program(std::move(_program)), m_programCache(std::move(_programCache)), + m_codeWeights(_codeWeights), m_repetitionCount(_repetitionCount) { assert(m_program.has_value() == (m_programCache == nullptr)); @@ -75,6 +79,7 @@ public: Program const& program() const; ProgramCache const* programCache() const { return m_programCache.get(); } + yul::CodeWeights const& codeWeights() const { return m_codeWeights; } size_t repetitionCount() const { return m_repetitionCount; } Program optimisedProgram(Chromosome const& _chromosome); @@ -83,6 +88,7 @@ public: private: std::optional m_program; std::shared_ptr m_programCache; + yul::CodeWeights m_codeWeights; size_t m_repetitionCount; }; @@ -111,9 +117,10 @@ public: std::optional _program, std::shared_ptr _programCache, size_t _fixedPointPrecision, + yul::CodeWeights const& _weights, size_t _repetitionCount = 1 ): - ProgramBasedMetric(std::move(_program), std::move(_programCache), _repetitionCount), + ProgramBasedMetric(std::move(_program), std::move(_programCache), _weights, _repetitionCount), m_fixedPointPrecision(_fixedPointPrecision) {} size_t fixedPointPrecision() const { return m_fixedPointPrecision; } diff --git a/tools/yulPhaser/Phaser.cpp b/tools/yulPhaser/Phaser.cpp index d5b3bdda7..68b9b05a9 100644 --- a/tools/yulPhaser/Phaser.cpp +++ b/tools/yulPhaser/Phaser.cpp @@ -39,6 +39,7 @@ using namespace std; using namespace solidity; using namespace solidity::langutil; using namespace solidity::util; +using namespace solidity::yul; using namespace solidity::phaser; namespace po = boost::program_options; @@ -216,6 +217,7 @@ unique_ptr FitnessMetricFactory::build( metrics.push_back(make_unique( _programCaches[i] != nullptr ? optional{} : move(_programs[i]), move(_programCaches[i]), + CodeWeights{}, _options.chromosomeRepetitions )); @@ -228,6 +230,7 @@ unique_ptr FitnessMetricFactory::build( _programCaches[i] != nullptr ? optional{} : move(_programs[i]), move(_programCaches[i]), _options.relativeMetricScale, + CodeWeights{}, _options.chromosomeRepetitions )); break; diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index a457750d2..2fd29f51a 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -207,7 +207,7 @@ unique_ptr Program::applyOptimisationSteps( return _ast; } -size_t Program::computeCodeSize(Block const& _ast) +size_t Program::computeCodeSize(Block const& _ast, CodeWeights const& _weights) { - return CodeSize::codeSizeIncludingFunctions(_ast); + return CodeSize::codeSizeIncludingFunctions(_ast, _weights); } diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index 10fed6de2..b96843ee4 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -41,6 +41,7 @@ namespace solidity::yul struct AsmAnalysisInfo; struct Dialect; +struct CodeWeights; } @@ -78,7 +79,7 @@ public: static std::variant load(langutil::CharStream& _sourceCode); void optimise(std::vector const& _optimisationSteps); - size_t codeSize() const { return computeCodeSize(*m_ast); } + size_t codeSize(yul::CodeWeights const& _weights) const { return computeCodeSize(*m_ast, _weights); } yul::Block const& ast() const { return *m_ast; } friend std::ostream& operator<<(std::ostream& _stream, Program const& _program); @@ -113,7 +114,7 @@ private: std::unique_ptr _ast, std::vector const& _optimisationSteps ); - static size_t computeCodeSize(yul::Block const& _ast); + static size_t computeCodeSize(yul::Block const& _ast, yul::CodeWeights const& _weights); std::unique_ptr m_ast; yul::Dialect const& m_dialect; diff --git a/tools/yulPhaser/ProgramCache.cpp b/tools/yulPhaser/ProgramCache.cpp index 7acec16bd..2556ea7c3 100644 --- a/tools/yulPhaser/ProgramCache.cpp +++ b/tools/yulPhaser/ProgramCache.cpp @@ -17,6 +17,8 @@ #include +#include + #include using namespace std; @@ -133,7 +135,7 @@ size_t ProgramCache::calculateTotalCachedCodeSize() const { size_t size = 0; for (auto const& pair: m_entries) - size += pair.second.program.codeSize(); + size += pair.second.program.codeSize(CodeWeights{}); return size; }