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)); 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 // simplificationRuleList below was split up into parts to prevent
// stack overflows in the JavaScript optimizer for emscripten builds // stack overflows in the JavaScript optimizer for emscripten builds
// that affected certain browser versions. // that affected certain browser versions.
@ -633,7 +642,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart8(
template<class Pattern> template<class Pattern>
std::vector<SimplificationRule<Pattern>> evmRuleList( std::vector<SimplificationRule<Pattern>> evmRuleList(
langutil::EVMVersion _evmVersion, langutil::EVMVersion _evmVersion,
Pattern, Pattern A,
Pattern, Pattern,
Pattern, Pattern,
Pattern, Pattern,
@ -661,10 +670,27 @@ std::vector<SimplificationRule<Pattern>> evmRuleList(
[=]() -> Pattern { return Word(1); } [=]() -> Pattern { return Word(1); }
); );
if (_evmVersion.hasBitwiseShifting()) if (_evmVersion.hasBitwiseShifting())
{
rules.emplace_back( rules.emplace_back(
Builtins::EXP(2, X), Builtins::EXP(2, X),
[=]() -> Pattern { return Builtins::SHL(X, 1); } [=]() -> 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( rules.emplace_back(
Builtins::EXP(Word(-1), X), Builtins::EXP(Word(-1), X),
[=]() -> Pattern [=]() -> Pattern