diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 1ce7ba920..bead74407 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -83,10 +83,7 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, lan bigint gas = 0; for (AssemblyItem const& item: _items) if (item.type() == Push) - { - auto const instruction = (item.data() == u256(0) && _evmVersion.hasPush0()) ? Instruction::PUSH0 : Instruction::PUSH1; - gas += GasMeter::runGas(instruction, _evmVersion); - } + gas += GasMeter::pushGas(item.data(), _evmVersion); else if (item.type() == Operation) { if (item.instruction() == Instruction::EXP) diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 271a6ce2d..b6c265142 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -277,6 +277,14 @@ unsigned GasMeter::runGas(Instruction _instruction, langutil::EVMVersion _evmVer return 0; } +unsigned GasMeter::pushGas(u256 _value, langutil::EVMVersion _evmVersion) +{ + return runGas( + (_evmVersion.hasPush0() && _value == u256(0)) ? Instruction::PUSH0 : Instruction::PUSH1, + _evmVersion + ); +} + u256 GasMeter::dataGas(bytes const& _data, bool _inCreation, langutil::EVMVersion _evmVersion) { bigint gas = 0; diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index ec1946644..9a7f6621f 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -223,6 +223,9 @@ public: /// change with EVM versions) static unsigned runGas(Instruction _instruction, langutil::EVMVersion _evmVersion); + /// @returns gas costs for push instructions (may change depending on EVM version) + static unsigned pushGas(u256 _value, langutil::EVMVersion _evmVersion); + /// @returns the gas cost of the supplied data, depending whether it is in creation code, or not. /// In case of @a _inCreation, the data is only sent as a transaction and is not stored, whereas /// otherwise code will be stored and have to pay "createDataGas" cost. diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 095969838..1760b19a0 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -88,14 +88,16 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall) void GasMeterVisitor::operator()(Literal const& _lit) { - m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1, m_dialect.evmVersion()); - m_dataGas += - singleByteDataGas() + - evmasm::GasMeter::dataGas( - toCompactBigEndian(valueOfLiteral(_lit), 1), - m_isCreation, - m_dialect.evmVersion() - ); + m_runGas += evmasm::GasMeter::pushGas(valueOfLiteral(_lit), m_dialect.evmVersion()); + + if (!m_dialect.evmVersion().hasPush0() || valueOfLiteral(_lit) != u256(0)) + m_dataGas += + singleByteDataGas() + + evmasm::GasMeter::dataGas( + toCompactBigEndian(valueOfLiteral(_lit), 1), + m_isCreation, + m_dialect.evmVersion() + ); } void GasMeterVisitor::operator()(Identifier const&) @@ -121,5 +123,7 @@ void GasMeterVisitor::instructionCostsInternal(evmasm::Instruction _instruction) m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas; else m_runGas += evmasm::GasMeter::runGas(_instruction, m_dialect.evmVersion()); - m_dataGas += singleByteDataGas(); + + if (_instruction != evmasm::Instruction::PUSH0) + m_dataGas += singleByteDataGas(); } diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 71bf19458..8501655f0 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -772,7 +772,7 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi yulAssert(util::contains(m_currentFunctionInfo->returnVariables, get(_slot))); // Strictly speaking the cost of the PUSH0 depends on the targeted EVM version, but the difference // will not matter here. - opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(0), langutil::EVMVersion());; + opGas += evmasm::GasMeter::pushGas(u256(0), langutil::EVMVersion()); } } };