Support shifts in the constant optimiser when Constantinople is targeted

This commit is contained in:
Alex Beregszaszi 2019-02-21 23:50:37 +00:00
parent 91c664ca1e
commit 81d011335a
3 changed files with 25 additions and 3 deletions

View File

@ -7,6 +7,7 @@ Compiler Features:
* SMTChecker: Do not report underflow/overflow if they always revert. This removes false positives when using ``SafeMath``.
* Static Analyzer: Warn about expressions with custom types when they have no effect.
* Optimizer: Add rule for shifts with constants for Constantinople.
* Optimizer: Support shifts in the constant optimiser for Constantinople.
Bugfixes:

View File

@ -210,7 +210,10 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
AssemblyItems newRoutine;
if (lowerPart != 0)
newRoutine += findRepresentation(u256(abs(lowerPart)));
newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
if (m_params.evmVersion.hasBitwiseShifting())
newRoutine += AssemblyItems{u256(1), u256(bits), Instruction::SHL};
else
newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
if (upperPart != 1)
newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
if (lowerPart > 0)
@ -231,7 +234,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
}
}
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
{
// This is a tiny EVM that can only evaluate some instructions.
vector<u256> stack;
@ -263,6 +266,24 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
case Instruction::NOT:
sp[0] = ~sp[0];
break;
case Instruction::SHL:
assertThrow(
m_params.evmVersion.hasBitwiseShifting(),
OptimizerException,
"Shift generated for invalid EVM version."
);
assertThrow(sp[0] <= u256(255), OptimizerException, "Invalid shift generated.");
sp[-1] = u256(bigint(sp[-1]) << unsigned(sp[0]));
break;
case Instruction::SHR:
assertThrow(
m_params.evmVersion.hasBitwiseShifting(),
OptimizerException,
"Shift generated for invalid EVM version."
);
assertThrow(sp[0] <= u256(255), OptimizerException, "Invalid shift generated.");
sp[-1] = sp[-1] >> unsigned(sp[0]);
break;
default:
return false;
}

View File

@ -155,7 +155,7 @@ protected:
/// Tries to recursively find a way to compute @a _value.
AssemblyItems findRepresentation(u256 const& _value);
/// Recomputes the value from the calculated representation and checks for correctness.
static bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine);
bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const;
bigint gasNeeded(AssemblyItems const& _routine) const;
/// Counter for the complexity of optimization, will stop when it reaches zero.