Skip to content

Commit

Permalink
Change the constant optimizer to make use of PUSH0
Browse files Browse the repository at this point in the history
  • Loading branch information
axic committed Apr 17, 2023
1 parent c6aab84 commit 6c756d2
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 24 deletions.
85 changes: 62 additions & 23 deletions libevmasm/ConstantOptimiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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, <offset>, 32)
u256(32),
AssemblyItem(PushData, u256(1) << 16), // replaced above in actualCopyRoutine[3]
u256(0),
Instruction::CODECOPY,

// codecopy(0, <offset>, 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, <offset>, 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)
Expand Down
2 changes: 1 addition & 1 deletion libevmasm/ConstantOptimiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class CodeCopyMethod: public ConstantOptimisationMethod
AssemblyItems execute(Assembly& _assembly) const override;

protected:
static AssemblyItems const& copyRoutine();
AssemblyItems const& copyRoutine() const;
};

/**
Expand Down

0 comments on commit 6c756d2

Please sign in to comment.