From 37fb3cd2fd313ece351d2752f7b71fdd63259377 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 14 May 2019 13:12:51 +0200 Subject: [PATCH] Refactor: Pull out single value optimisation. --- libevmasm/ConstantOptimiser.cpp | 50 ++++++++++++++++++--------------- libevmasm/ConstantOptimiser.h | 13 +++++++-- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 267daa5e5..68c1e24fb 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -44,39 +44,45 @@ unsigned ConstantOptimisationMethod::optimiseConstants( map pendingReplacements; for (auto it: pushes) { - AssemblyItem const& item = it.first; - if (item.data() < 0x100) - continue; + u256 value = it.first.data(); Params params; params.multiplicity = it.second; params.isCreation = _isCreation; params.runs = _runs; params.evmVersion = _evmVersion; - LiteralMethod lit(params, item.data()); - bigint literalGas = lit.gasNeeded(); - CodeCopyMethod copy(params, item.data()); - bigint copyGas = copy.gasNeeded(); - ComputeMethod compute(params, item.data()); - bigint computeGas = compute.gasNeeded(); - AssemblyItems replacement; - if (copyGas < literalGas && copyGas < computeGas) - { - replacement = copy.execute(_assembly); - optimisations++; - } - else if (computeGas < literalGas && computeGas <= copyGas) - { - replacement = compute.execute(_assembly); - optimisations++; - } - if (!replacement.empty()) - pendingReplacements[item.data()] = replacement; + AssemblyItems replacement = optimiseSingleConstant(value, params, _assembly); + if (replacement.empty()) + continue; + pendingReplacements[value] = move(replacement); + optimisations++; } if (!pendingReplacements.empty()) replaceConstants(_items, pendingReplacements); return optimisations; } +AssemblyItems ConstantOptimisationMethod::optimiseSingleConstant( + u256 const& _value, + Params const& _params, + Assembly& _assembly +) +{ + if (_value < 0x100) + return {}; + + LiteralMethod lit(_params, _value); + bigint literalGas = lit.gasNeeded(); + CodeCopyMethod copy(_params, _value); + bigint copyGas = copy.gasNeeded(); + ComputeMethod compute(_params, _value); + bigint computeGas = compute.gasNeeded(); + if (copyGas < literalGas && copyGas < computeGas) + return copy.execute(_assembly); + else if (computeGas < literalGas && computeGas <= copyGas) + return compute.execute(_assembly); + return {}; +} + bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items) { bigint gas = 0; diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index be1628c71..a73f94c4e 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -57,8 +57,6 @@ public: ); protected: - /// This is the public API for the optimiser methods, but it doesn't need to be exposed to the caller. - struct Params { bool isCreation; ///< Whether this is called during contract creation or runtime. @@ -67,6 +65,17 @@ protected: langutil::EVMVersion evmVersion; ///< Version of the EVM }; + /// Computes the replacement for a single constant. + /// This can already modify @a _assembly by adding a data item, + /// but the return value still has to be inserted. + static AssemblyItems optimiseSingleConstant( + u256 const& _value, + Params const& _params, + Assembly& _assembly + ); + + /// This is the public API for the optimiser methods, but it doesn't need to be exposed to the caller. + explicit ConstantOptimisationMethod(Params const& _params, u256 const& _value): m_params(_params), m_value(_value) {} virtual ~ConstantOptimisationMethod() = default;