mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Optimize constant optimization.
This commit is contained in:
parent
f1a4976ce6
commit
da5e171f3b
@ -38,6 +38,7 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
|
|||||||
for (AssemblyItem const& item: _items)
|
for (AssemblyItem const& item: _items)
|
||||||
if (item.type() == Push)
|
if (item.type() == Push)
|
||||||
pushes[item]++;
|
pushes[item]++;
|
||||||
|
map<u256, AssemblyItems> pendingReplacements;
|
||||||
for (auto it: pushes)
|
for (auto it: pushes)
|
||||||
{
|
{
|
||||||
AssemblyItem const& item = it.first;
|
AssemblyItem const& item = it.first;
|
||||||
@ -53,17 +54,22 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
|
|||||||
bigint copyGas = copy.gasNeeded();
|
bigint copyGas = copy.gasNeeded();
|
||||||
ComputeMethod compute(params, item.data());
|
ComputeMethod compute(params, item.data());
|
||||||
bigint computeGas = compute.gasNeeded();
|
bigint computeGas = compute.gasNeeded();
|
||||||
|
AssemblyItems replacement;
|
||||||
if (copyGas < literalGas && copyGas < computeGas)
|
if (copyGas < literalGas && copyGas < computeGas)
|
||||||
{
|
{
|
||||||
copy.execute(_assembly, _items);
|
replacement = copy.execute(_assembly);
|
||||||
optimisations++;
|
optimisations++;
|
||||||
}
|
}
|
||||||
else if (computeGas < literalGas && computeGas < copyGas)
|
else if (computeGas < literalGas && computeGas < copyGas)
|
||||||
{
|
{
|
||||||
compute.execute(_assembly, _items);
|
replacement = compute.execute(_assembly);
|
||||||
optimisations++;
|
optimisations++;
|
||||||
}
|
}
|
||||||
|
if (!replacement.empty())
|
||||||
|
pendingReplacements[item.data()] = replacement;
|
||||||
}
|
}
|
||||||
|
if (!pendingReplacements.empty())
|
||||||
|
replaceConstants(_items, pendingReplacements);
|
||||||
return optimisations;
|
return optimisations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,18 +107,24 @@ size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
|
|||||||
|
|
||||||
void ConstantOptimisationMethod::replaceConstants(
|
void ConstantOptimisationMethod::replaceConstants(
|
||||||
AssemblyItems& _items,
|
AssemblyItems& _items,
|
||||||
AssemblyItems const& _replacement
|
map<u256, AssemblyItems> const& _replacements
|
||||||
) const
|
)
|
||||||
{
|
{
|
||||||
assertThrow(_items.size() > 0, OptimizerException, "");
|
AssemblyItems replaced;
|
||||||
for (size_t i = 0; i < _items.size(); ++i)
|
for (AssemblyItem const& item: _items)
|
||||||
{
|
{
|
||||||
if (_items.at(i) != AssemblyItem(m_value))
|
if (item.type() == Push)
|
||||||
continue;
|
{
|
||||||
_items[i] = _replacement[0];
|
auto it = _replacements.find(item.data());
|
||||||
_items.insert(_items.begin() + i + 1, _replacement.begin() + 1, _replacement.end());
|
if (it != _replacements.end())
|
||||||
i += _replacement.size() - 1;
|
{
|
||||||
|
replaced += it->second;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replaced.push_back(item);
|
||||||
}
|
}
|
||||||
|
_items = std::move(replaced);
|
||||||
}
|
}
|
||||||
|
|
||||||
bigint LiteralMethod::gasNeeded()
|
bigint LiteralMethod::gasNeeded()
|
||||||
@ -128,7 +140,31 @@ bigint LiteralMethod::gasNeeded()
|
|||||||
CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
|
CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
|
||||||
ConstantOptimisationMethod(_params, _value)
|
ConstantOptimisationMethod(_params, _value)
|
||||||
{
|
{
|
||||||
m_copyRoutine = AssemblyItems{
|
}
|
||||||
|
|
||||||
|
bigint CodeCopyMethod::gasNeeded()
|
||||||
|
{
|
||||||
|
return combineGas(
|
||||||
|
// Run gas: we ignore memory increase costs
|
||||||
|
simpleRunGas(copyRoutine()) + GasCosts::copyGas,
|
||||||
|
// Data gas for copy routines: Some bytes are zero, but we ignore them.
|
||||||
|
bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
|
||||||
|
// Data gas for data itself
|
||||||
|
dataGas(toBigEndian(m_value))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssemblyItems CodeCopyMethod::execute(Assembly& _assembly)
|
||||||
|
{
|
||||||
|
bytes data = toBigEndian(m_value);
|
||||||
|
AssemblyItems actualCopyRoutine = copyRoutine();
|
||||||
|
actualCopyRoutine[4] = _assembly.newData(data);
|
||||||
|
return actualCopyRoutine;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssemblyItems const& CodeCopyMethod::copyRoutine() const
|
||||||
|
{
|
||||||
|
AssemblyItems static copyRoutine{
|
||||||
u256(0),
|
u256(0),
|
||||||
Instruction::DUP1,
|
Instruction::DUP1,
|
||||||
Instruction::MLOAD, // back up memory
|
Instruction::MLOAD, // back up memory
|
||||||
@ -141,25 +177,7 @@ CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
|
|||||||
Instruction::SWAP2,
|
Instruction::SWAP2,
|
||||||
Instruction::MSTORE
|
Instruction::MSTORE
|
||||||
};
|
};
|
||||||
}
|
return copyRoutine;
|
||||||
|
|
||||||
bigint CodeCopyMethod::gasNeeded()
|
|
||||||
{
|
|
||||||
return combineGas(
|
|
||||||
// Run gas: we ignore memory increase costs
|
|
||||||
simpleRunGas(m_copyRoutine) + GasCosts::copyGas,
|
|
||||||
// Data gas for copy routines: Some bytes are zero, but we ignore them.
|
|
||||||
bytesRequired(m_copyRoutine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
|
|
||||||
// Data gas for data itself
|
|
||||||
dataGas(toBigEndian(m_value))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CodeCopyMethod::execute(Assembly& _assembly, AssemblyItems& _items)
|
|
||||||
{
|
|
||||||
bytes data = toBigEndian(m_value);
|
|
||||||
m_copyRoutine[4] = _assembly.newData(data);
|
|
||||||
replaceConstants(_items, m_copyRoutine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
||||||
|
@ -60,7 +60,10 @@ public:
|
|||||||
explicit ConstantOptimisationMethod(Params const& _params, u256 const& _value):
|
explicit ConstantOptimisationMethod(Params const& _params, u256 const& _value):
|
||||||
m_params(_params), m_value(_value) {}
|
m_params(_params), m_value(_value) {}
|
||||||
virtual bigint gasNeeded() = 0;
|
virtual bigint gasNeeded() = 0;
|
||||||
virtual void execute(Assembly& _assembly, AssemblyItems& _items) = 0;
|
/// Executes the method, potentially appending to the assembly and returns a vector of
|
||||||
|
/// assembly items the constant should be relpaced with in one sweep.
|
||||||
|
/// If the vector is empty, the constants will not be deleted.
|
||||||
|
virtual AssemblyItems execute(Assembly& _assembly) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t dataSize() const { return std::max<size_t>(1, dev::bytesRequired(m_value)); }
|
size_t dataSize() const { return std::max<size_t>(1, dev::bytesRequired(m_value)); }
|
||||||
@ -83,8 +86,8 @@ protected:
|
|||||||
return m_params.runs * _runGas + m_params.multiplicity * _repeatedDataGas + _uniqueDataGas;
|
return m_params.runs * _runGas + m_params.multiplicity * _repeatedDataGas + _uniqueDataGas;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces the constant by the code given in @a _replacement.
|
/// Replaces all constants i by the code given in @a _replacement[i].
|
||||||
void replaceConstants(AssemblyItems& _items, AssemblyItems const& _replacement) const;
|
static void replaceConstants(AssemblyItems& _items, std::map<u256, AssemblyItems> const& _replacement);
|
||||||
|
|
||||||
Params m_params;
|
Params m_params;
|
||||||
u256 const& m_value;
|
u256 const& m_value;
|
||||||
@ -100,7 +103,7 @@ public:
|
|||||||
explicit LiteralMethod(Params const& _params, u256 const& _value):
|
explicit LiteralMethod(Params const& _params, u256 const& _value):
|
||||||
ConstantOptimisationMethod(_params, _value) {}
|
ConstantOptimisationMethod(_params, _value) {}
|
||||||
virtual bigint gasNeeded() override;
|
virtual bigint gasNeeded() override;
|
||||||
virtual void execute(Assembly&, AssemblyItems&) override {}
|
virtual AssemblyItems execute(Assembly&) override { return AssemblyItems{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,10 +114,10 @@ class CodeCopyMethod: public ConstantOptimisationMethod
|
|||||||
public:
|
public:
|
||||||
explicit CodeCopyMethod(Params const& _params, u256 const& _value);
|
explicit CodeCopyMethod(Params const& _params, u256 const& _value);
|
||||||
virtual bigint gasNeeded() override;
|
virtual bigint gasNeeded() override;
|
||||||
virtual void execute(Assembly& _assembly, AssemblyItems& _items) override;
|
virtual AssemblyItems execute(Assembly& _assembly) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AssemblyItems m_copyRoutine;
|
AssemblyItems const& copyRoutine() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,9 +133,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
|
virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
|
||||||
virtual void execute(Assembly&, AssemblyItems& _items) override
|
virtual AssemblyItems execute(Assembly&) override
|
||||||
{
|
{
|
||||||
replaceConstants(_items, m_routine);
|
return m_routine;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
Reference in New Issue
Block a user