From 6c756d2737ce2c04917bb1fa3f708a1d4cab0ba1 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 13 Apr 2023 00:10:31 +0200 Subject: [PATCH] Change the constant optimizer to make use of PUSH0 --- libevmasm/ConstantOptimiser.cpp | 85 ++++++++++++++++++++++++--------- libevmasm/ConstantOptimiser.h | 2 +- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 5bce21cf1e10..a584a37ed11d 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -84,7 +84,10 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, lan bigint gas = 0; for (AssemblyItem const& item: _items) if (item.type() == Push) - gas += GasMeter::runGas(Instruction::PUSH1, _evmVersion); + { + auto const instruction = (item.data() == u256(0) && _evmVersion.hasPush0()) ? Instruction::PUSH0 : Instruction::PUSH1; + gas += GasMeter::runGas(instruction, _evmVersion); + } else if (item.type() == Operation) { if (item.instruction() == Instruction::EXP) @@ -155,36 +158,72 @@ AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) const bytes data = toBigEndian(m_value); assertThrow(data.size() == 32, OptimizerException, "Invalid number encoding."); AssemblyItems actualCopyRoutine = copyRoutine(); - actualCopyRoutine[4] = _assembly.newData(data); + if (m_params.evmVersion.hasPush0()) + actualCopyRoutine[3] = _assembly.newData(data); + else + actualCopyRoutine[4] = _assembly.newData(data); return actualCopyRoutine; } -AssemblyItems const& CodeCopyMethod::copyRoutine() +AssemblyItems const& CodeCopyMethod::copyRoutine() const { - AssemblyItems static copyRoutine{ - // constant to be reused 3+ times - u256(0), + // PUSH0 is cheaper than PUSHn/DUP/SWAP. + if (m_params.evmVersion.hasPush0()) + { + // This costs ~29 gas. + AssemblyItems static copyRoutine{ + // back up memory + // mload(0) + u256(0), + Instruction::MLOAD, - // back up memory - // mload(0) - Instruction::DUP1, - Instruction::MLOAD, + // codecopy(0, , 32) + u256(32), + AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[3] + u256(0), + Instruction::CODECOPY, - // codecopy(0, , 32) - u256(32), - AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4] - Instruction::DUP4, - Instruction::CODECOPY, + // mload(0) + u256(0), + Instruction::MLOAD, - // mload(0) - Instruction::DUP2, - Instruction::MLOAD, + // restore original memory + // mstore(0, x) + Instruction::SWAP1, + u256(0), + Instruction::MSTORE + }; + return copyRoutine; + } + else + { + // This costs ~33 gas. + AssemblyItems static copyRoutine{ + // constant to be reused 3+ times + u256(0), + + // back up memory + // mload(0) + Instruction::DUP1, + Instruction::MLOAD, + + // codecopy(0, , 32) + u256(32), + AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4] + Instruction::DUP4, + Instruction::CODECOPY, - // restore original memory - Instruction::SWAP2, - Instruction::MSTORE - }; - return copyRoutine; + // mload(0) + Instruction::DUP2, + Instruction::MLOAD, + + // restore original memory + // mstore(0, x) + Instruction::SWAP2, + Instruction::MSTORE + }; + return copyRoutine; + } } AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index b491fb00422f..5997931a971d 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -123,7 +123,7 @@ class CodeCopyMethod: public ConstantOptimisationMethod AssemblyItems execute(Assembly& _assembly) const override; protected: - static AssemblyItems const& copyRoutine(); + AssemblyItems const& copyRoutine() const; }; /**