Optimize multiplication by constant to shift.

This commit is contained in:
chriseth 2021-03-11 11:30:22 +01:00
parent e179d0aa4d
commit 4bfa7e088e

View File

@ -57,6 +57,15 @@ template <class S> S shlWorkaround(S const& _x, unsigned _amount)
return u256((bigint(_x) << _amount) & u256(-1));
}
/// @returns k if _x == 2**k, nullopt otherwise
inline std::optional<size_t> binaryLogarithm(u256 const& _x)
{
if (!_x)
return std::nullopt;
size_t msb = boost::multiprecision::msb(_x);
return (u256(1) << msb) == _x ? std::make_optional(msb) : std::nullopt;
}
// simplificationRuleList below was split up into parts to prevent
// stack overflows in the JavaScript optimizer for emscripten builds
// that affected certain browser versions.
@ -633,7 +642,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart8(
template<class Pattern>
std::vector<SimplificationRule<Pattern>> evmRuleList(
langutil::EVMVersion _evmVersion,
Pattern,
Pattern A,
Pattern,
Pattern,
Pattern,
@ -661,10 +670,27 @@ std::vector<SimplificationRule<Pattern>> evmRuleList(
[=]() -> Pattern { return Word(1); }
);
if (_evmVersion.hasBitwiseShifting())
{
rules.emplace_back(
Builtins::EXP(2, X),
[=]() -> Pattern { return Builtins::SHL(X, 1); }
);
rules.emplace_back(
Builtins::MUL(A, X),
[=]() -> Pattern { return Builtins::SHL(u256(*binaryLogarithm(A.d())), X); },
[=] { return binaryLogarithm(A.d()).has_value(); }
);
rules.emplace_back(
Builtins::MUL(X, A),
[=]() -> Pattern { return Builtins::SHL(u256(*binaryLogarithm(A.d())), X); },
[=] { return binaryLogarithm(A.d()).has_value(); }
);
rules.emplace_back(
Builtins::DIV(X, A),
[=]() -> Pattern { return Builtins::SHR(u256(*binaryLogarithm(A.d())), X); },
[=] { return binaryLogarithm(A.d()).has_value(); }
);
}
rules.emplace_back(
Builtins::EXP(Word(-1), X),
[=]() -> Pattern