Change the constant optimizer to make use of PUSH0

This commit is contained in:
Alex Beregszaszi 2023-04-13 00:10:31 +02:00 committed by Matheus Aguiar
parent 37e18612c5
commit cd611b2292
2 changed files with 63 additions and 24 deletions

View File

@ -83,7 +83,10 @@ bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items, lan
bigint gas = 0; bigint gas = 0;
for (AssemblyItem const& item: _items) for (AssemblyItem const& item: _items)
if (item.type() == Push) 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) else if (item.type() == Operation)
{ {
if (item.instruction() == Instruction::EXP) if (item.instruction() == Instruction::EXP)
@ -154,36 +157,72 @@ AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) const
bytes data = toBigEndian(m_value); bytes data = toBigEndian(m_value);
assertThrow(data.size() == 32, OptimizerException, "Invalid number encoding."); assertThrow(data.size() == 32, OptimizerException, "Invalid number encoding.");
AssemblyItems actualCopyRoutine = copyRoutine(); 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; return actualCopyRoutine;
} }
AssemblyItems const& CodeCopyMethod::copyRoutine() AssemblyItems const& CodeCopyMethod::copyRoutine() const
{ {
AssemblyItems static copyRoutine{ // PUSH0 is cheaper than PUSHn/DUP/SWAP.
// constant to be reused 3+ times if (m_params.evmVersion.hasPush0())
u256(0), {
// This costs ~29 gas.
AssemblyItems static copyRoutine{
// back up memory
// mload(0)
u256(0),
Instruction::MLOAD,
// back up memory // codecopy(0, <offset>, 32)
// mload(0) u256(32),
Instruction::DUP1, AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[3]
Instruction::MLOAD, u256(0),
Instruction::CODECOPY,
// codecopy(0, <offset>, 32) // mload(0)
u256(32), u256(0),
AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4] Instruction::MLOAD,
Instruction::DUP4,
Instruction::CODECOPY,
// mload(0) // restore original memory
Instruction::DUP2, // mstore(0, x)
Instruction::MLOAD, Instruction::SWAP1,
u256(0),
Instruction::MSTORE
};
return copyRoutine;
}
else
{
// This costs ~33 gas.
AssemblyItems static copyRoutine{
// constant to be reused 3+ times
u256(0),
// restore original memory // back up memory
Instruction::SWAP2, // mload(0)
Instruction::MSTORE Instruction::DUP1,
}; Instruction::MLOAD,
return copyRoutine;
// codecopy(0, <offset>, 32)
u256(32),
AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[4]
Instruction::DUP4,
Instruction::CODECOPY,
// mload(0)
Instruction::DUP2,
Instruction::MLOAD,
// restore original memory
// mstore(0, x)
Instruction::SWAP2,
Instruction::MSTORE
};
return copyRoutine;
}
} }
AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)

View File

@ -123,7 +123,7 @@ public:
AssemblyItems execute(Assembly& _assembly) const override; AssemblyItems execute(Assembly& _assembly) const override;
protected: protected:
static AssemblyItems const& copyRoutine(); AssemblyItems const& copyRoutine() const;
}; };
/** /**