mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Construct computation routine using Yul.
This commit is contained in:
parent
80e5dd4b85
commit
0a98fd4c7c
@ -186,21 +186,15 @@ AssemblyItems const& CodeCopyMethod::copyRoutine()
|
|||||||
return copyRoutine;
|
return copyRoutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
AssemblyItems ComputeMethod::yulRoutineToAssemblyItems(string const& _routine) const
|
||||||
{
|
{
|
||||||
string routine = findRepresentationInternal(_value);
|
if (_routine.empty())
|
||||||
if (routine.empty())
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return yulRoutineToAssemblyItems(routine);
|
string routine = "{ pop(" + _routine + ") }";
|
||||||
}
|
|
||||||
|
|
||||||
AssemblyItems ComputeMethod::yulRoutineToAssemblyItems(string _routine)
|
|
||||||
{
|
|
||||||
_routine = "{ pop(" + _routine + ") }";
|
|
||||||
langutil::ErrorList errors;
|
langutil::ErrorList errors;
|
||||||
langutil::ErrorReporter errorReporter(errors);
|
langutil::ErrorReporter errorReporter(errors);
|
||||||
auto scanner = make_shared<langutil::Scanner>(langutil::CharStream(_routine, "--CODEGEN--"));
|
auto scanner = make_shared<langutil::Scanner>(langutil::CharStream(routine, "--CODEGEN--"));
|
||||||
auto parserResult = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM(m_params.evmVersion)).parse(scanner, false);
|
auto parserResult = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM(m_params.evmVersion)).parse(scanner, false);
|
||||||
solAssert(parserResult, "");
|
solAssert(parserResult, "");
|
||||||
yul::AsmAnalysisInfo analysisInfo;
|
yul::AsmAnalysisInfo analysisInfo;
|
||||||
@ -226,65 +220,64 @@ AssemblyItems ComputeMethod::yulRoutineToAssemblyItems(string _routine)
|
|||||||
return {_asm.items().begin(), --_asm.items().end()};
|
return {_asm.items().begin(), --_asm.items().end()};
|
||||||
}
|
}
|
||||||
|
|
||||||
string ComputeMethod::findRepresentationInternal(u256 const& _value)
|
string ComputeMethod::findRepresentation(u256 const& _value)
|
||||||
{
|
{
|
||||||
return _value.str();
|
if (_value < 0x10000)
|
||||||
// if (_value < 0x10000)
|
// Very small value, not worth computing
|
||||||
// // Very small value, not worth computing
|
return _value.str();
|
||||||
// return AssemblyItems{_value};
|
else if (dev::bytesRequired(~_value) < dev::bytesRequired(_value))
|
||||||
// else if (dev::bytesRequired(~_value) < dev::bytesRequired(_value))
|
// Negated is shorter to represent
|
||||||
// // Negated is shorter to represent
|
return "not(" + findRepresentation(~_value) + ")";
|
||||||
// return findRepresentation(~_value) + AssemblyItems{Instruction::NOT};
|
else
|
||||||
// else
|
{
|
||||||
// {
|
// Decompose value into a * 2**k + b where abs(b) << 2**k
|
||||||
// // Decompose value into a * 2**k + b where abs(b) << 2**k
|
// Is not always better, try literal and decomposition method.
|
||||||
// // Is not always better, try literal and decomposition method.
|
string routine{_value.str()};
|
||||||
// AssemblyItems routine{u256(_value)};
|
bigint bestGas = gasNeeded(routine);
|
||||||
// bigint bestGas = gasNeeded(routine);
|
for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits)
|
||||||
// for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits)
|
{
|
||||||
// {
|
unsigned gapDetector = unsigned((_value >> (bits - 8)) & 0x1ff);
|
||||||
// unsigned gapDetector = unsigned((_value >> (bits - 8)) & 0x1ff);
|
if (gapDetector != 0xff && gapDetector != 0x100)
|
||||||
// if (gapDetector != 0xff && gapDetector != 0x100)
|
continue;
|
||||||
// continue;
|
|
||||||
|
|
||||||
// u256 powerOfTwo = u256(1) << bits;
|
u256 powerOfTwo = u256(1) << bits;
|
||||||
// u256 upperPart = _value >> bits;
|
u256 upperPart = _value >> bits;
|
||||||
// bigint lowerPart = _value & (powerOfTwo - 1);
|
bigint lowerPart = _value & (powerOfTwo - 1);
|
||||||
// if ((powerOfTwo - lowerPart) < lowerPart)
|
if ((powerOfTwo - lowerPart) < lowerPart)
|
||||||
// {
|
{
|
||||||
// lowerPart = lowerPart - powerOfTwo; // make it negative
|
lowerPart = lowerPart - powerOfTwo; // make it negative
|
||||||
// upperPart++;
|
upperPart++;
|
||||||
// }
|
}
|
||||||
// if (upperPart == 0)
|
if (upperPart == 0)
|
||||||
// continue;
|
continue;
|
||||||
// if (abs(lowerPart) >= (powerOfTwo >> 8))
|
if (abs(lowerPart) >= (powerOfTwo >> 8))
|
||||||
// continue;
|
continue;
|
||||||
|
|
||||||
// AssemblyItems newRoutine;
|
string newRoutine;
|
||||||
// if (lowerPart != 0)
|
if (m_params.evmVersion.hasBitwiseShifting())
|
||||||
// newRoutine += findRepresentation(u256(abs(lowerPart)));
|
newRoutine = "shl(" + to_string(bits) + ", " + findRepresentation(upperPart) + ")";
|
||||||
// if (m_params.evmVersion.hasBitwiseShifting())
|
else
|
||||||
// newRoutine += AssemblyItems{u256(1), u256(bits), Instruction::SHL};
|
{
|
||||||
// else
|
newRoutine = "exp(2, " + to_string(bits) + ")";
|
||||||
// newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
|
if (upperPart != 1)
|
||||||
// if (upperPart != 1)
|
newRoutine = "mul(" + findRepresentation(upperPart) + ", " + newRoutine + ")";
|
||||||
// newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
|
}
|
||||||
// if (lowerPart > 0)
|
if (lowerPart > 0)
|
||||||
// newRoutine += AssemblyItems{Instruction::ADD};
|
newRoutine = "add(" + newRoutine + ", " + findRepresentation(u256(abs(lowerPart))) + ")";
|
||||||
// else if (lowerPart < 0)
|
else if (lowerPart < 0)
|
||||||
// newRoutine.push_back(Instruction::SUB);
|
newRoutine = "sub(" + newRoutine + ", " + findRepresentation(u256(abs(lowerPart))) + ")";
|
||||||
|
|
||||||
// if (m_maxSteps > 0)
|
if (m_maxSteps > 0)
|
||||||
// m_maxSteps--;
|
m_maxSteps--;
|
||||||
// bigint newGas = gasNeeded(newRoutine);
|
bigint newGas = gasNeeded(newRoutine);
|
||||||
// if (newGas < bestGas)
|
if (newGas < bestGas)
|
||||||
// {
|
{
|
||||||
// bestGas = move(newGas);
|
bestGas = move(newGas);
|
||||||
// routine = move(newRoutine);
|
routine = move(newRoutine);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// return routine;
|
return routine;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
|
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
|
||||||
@ -353,6 +346,11 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
|
|||||||
return stack.size() == 1 && stack.front() == _value;
|
return stack.size() == 1 && stack.front() == _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bigint ComputeMethod::gasNeeded(string const& _routine) const
|
||||||
|
{
|
||||||
|
return gasNeeded(yulRoutineToAssemblyItems(_routine));
|
||||||
|
}
|
||||||
|
|
||||||
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
|
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
|
||||||
{
|
{
|
||||||
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
|
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
|
||||||
|
@ -146,7 +146,7 @@ public:
|
|||||||
explicit ComputeMethod(Params const& _params, u256 const& _value):
|
explicit ComputeMethod(Params const& _params, u256 const& _value):
|
||||||
ConstantOptimisationMethod(_params, _value)
|
ConstantOptimisationMethod(_params, _value)
|
||||||
{
|
{
|
||||||
m_routine = findRepresentation(m_value);
|
m_routine = yulRoutineToAssemblyItems(findRepresentation(m_value));
|
||||||
assertThrow(
|
assertThrow(
|
||||||
checkRepresentation(m_value, m_routine),
|
checkRepresentation(m_value, m_routine),
|
||||||
OptimizerException,
|
OptimizerException,
|
||||||
@ -161,12 +161,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
AssemblyItems yulRoutineToAssemblyItems(std::string const& _routine) const;
|
||||||
/// Tries to recursively find a way to compute @a _value.
|
/// Tries to recursively find a way to compute @a _value.
|
||||||
AssemblyItems findRepresentation(u256 const& _value);
|
std::string findRepresentation(u256 const& _value);
|
||||||
AssemblyItems yulRoutineToAssemblyItems(std::string _routine);
|
|
||||||
std::string findRepresentationInternal(u256 const& _value);
|
|
||||||
/// Recomputes the value from the calculated representation and checks for correctness.
|
/// Recomputes the value from the calculated representation and checks for correctness.
|
||||||
bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const;
|
bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const;
|
||||||
|
bigint gasNeeded(std::string const& _routine) const;
|
||||||
bigint gasNeeded(AssemblyItems const& _routine) const;
|
bigint gasNeeded(AssemblyItems const& _routine) const;
|
||||||
|
|
||||||
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
||||||
|
Loading…
Reference in New Issue
Block a user