Explicitly add reversed operands for commutative operations.

This commit is contained in:
chriseth 2018-01-18 13:56:42 +01:00
parent 9eea3f29ba
commit 295f8c07ad

View File

@ -43,11 +43,6 @@ template <class S> S modWorkaround(S const& _a, S const& _b)
return (S)(bigint(_a) % bigint(_b)); return (S)(bigint(_a) % bigint(_b));
} }
// TODO: Add a parameter that will cause rules with swapped arguments
// to be added explicitly. This is needed by the new optimizer, but not
// by the old. The new optimizer requires that the order of arbitrary
// expressions is not altered.
/// @returns a list of simplification rules given certain match placeholders. /// @returns a list of simplification rules given certain match placeholders.
/// A, B and C should represent constants, X and Y arbitrary expressions. /// A, B and C should represent constants, X and Y arbitrary expressions.
/// The third element in the tuple is a boolean flag that indicates whether /// The third element in the tuple is a boolean flag that indicates whether
@ -96,11 +91,16 @@ std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>> simplificationR
return u256(boost::multiprecision::bit_test(B.d(), testBit) ? B.d() | ~mask : B.d() & mask); return u256(boost::multiprecision::bit_test(B.d(), testBit) ? B.d() | ~mask : B.d() & mask);
}, false}, }, false},
// invariants involving known constants (commutative instructions will be checked with swapped operants too) // invariants involving known constants
{{Instruction::ADD, {X, 0}}, [=]{ return X; }, false}, {{Instruction::ADD, {X, 0}}, [=]{ return X; }, false},
{{Instruction::ADD, {0, X}}, [=]{ return X; }, false},
{{Instruction::SUB, {X, 0}}, [=]{ return X; }, false}, {{Instruction::SUB, {X, 0}}, [=]{ return X; }, false},
{{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }, true}, {{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }, true},
{{Instruction::MUL, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::MUL, {X, 1}}, [=]{ return X; }, false}, {{Instruction::MUL, {X, 1}}, [=]{ return X; }, false},
{{Instruction::MUL, {1, X}}, [=]{ return X; }, false},
{{Instruction::MUL, {X, u256(-1)}}, [=]() -> Pattern { return {Instruction::SUB, {0, X}}; }, false},
{{Instruction::MUL, {u256(-1), X}}, [=]() -> Pattern { return {Instruction::SUB, {0, X}}; }, false},
{{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }, true}, {{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }, true},
{{Instruction::DIV, {0, X}}, [=]{ return u256(0); }, true}, {{Instruction::DIV, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::DIV, {X, 1}}, [=]{ return X; }, false}, {{Instruction::DIV, {X, 1}}, [=]{ return X; }, false},
@ -108,13 +108,19 @@ std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>> simplificationR
{{Instruction::SDIV, {0, X}}, [=]{ return u256(0); }, true}, {{Instruction::SDIV, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::SDIV, {X, 1}}, [=]{ return X; }, false}, {{Instruction::SDIV, {X, 1}}, [=]{ return X; }, false},
{{Instruction::AND, {X, ~u256(0)}}, [=]{ return X; }, false}, {{Instruction::AND, {X, ~u256(0)}}, [=]{ return X; }, false},
{{Instruction::AND, {~u256(0), X}}, [=]{ return X; }, false},
{{Instruction::AND, {X, 0}}, [=]{ return u256(0); }, true}, {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }, true},
{{Instruction::AND, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::OR, {X, 0}}, [=]{ return X; }, false}, {{Instruction::OR, {X, 0}}, [=]{ return X; }, false},
{{Instruction::OR, {0, X}}, [=]{ return X; }, false},
{{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }, true}, {{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }, true},
{{Instruction::OR, {~u256(0), X}}, [=]{ return ~u256(0); }, true},
{{Instruction::XOR, {X, 0}}, [=]{ return X; }, false}, {{Instruction::XOR, {X, 0}}, [=]{ return X; }, false},
{{Instruction::XOR, {0, X}}, [=]{ return X; }, false},
{{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }, true}, {{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }, true},
{{Instruction::MOD, {0, X}}, [=]{ return u256(0); }, true}, {{Instruction::MOD, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false }, {{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false },
{{Instruction::EQ, {0, X}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; }, false },
// operations involving an expression and itself // operations involving an expression and itself
{{Instruction::AND, {X, X}}, [=]{ return X; }, true}, {{Instruction::AND, {X, X}}, [=]{ return X; }, true},
@ -130,14 +136,25 @@ std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>> simplificationR
// logical instruction combinations // logical instruction combinations
{{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }, false}, {{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }, false},
{{Instruction::XOR, {{{X}, {Instruction::XOR, {X, Y}}}}}, [=]{ return Y; }, true}, {{Instruction::XOR, {X, {Instruction::XOR, {X, Y}}}}, [=]{ return Y; }, true},
{{Instruction::OR, {{{X}, {Instruction::AND, {X, Y}}}}}, [=]{ return X; }, true}, {{Instruction::XOR, {X, {Instruction::XOR, {Y, X}}}}, [=]{ return Y; }, true},
{{Instruction::AND, {{{X}, {Instruction::OR, {X, Y}}}}}, [=]{ return X; }, true}, {{Instruction::XOR, {{Instruction::XOR, {X, Y}}, X}}, [=]{ return Y; }, true},
{{Instruction::AND, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return u256(0); }, true}, {{Instruction::XOR, {{Instruction::XOR, {Y, X}}, X}}, [=]{ return Y; }, true},
{{Instruction::OR, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return ~u256(0); }, true}, {{Instruction::OR, {X, {Instruction::AND, {X, Y}}}}, [=]{ return X; }, true},
{{Instruction::OR, {X, {Instruction::AND, {Y, X}}}}, [=]{ return X; }, true},
{{Instruction::OR, {{Instruction::AND, {X, Y}}, X}}, [=]{ return X; }, true},
{{Instruction::OR, {{Instruction::AND, {Y, X}}, X}}, [=]{ return X; }, true},
{{Instruction::AND, {X, {Instruction::OR, {X, Y}}}}, [=]{ return X; }, true},
{{Instruction::AND, {X, {Instruction::OR, {Y, X}}}}, [=]{ return X; }, true},
{{Instruction::AND, {{Instruction::OR, {X, Y}}, X}}, [=]{ return X; }, true},
{{Instruction::AND, {{Instruction::OR, {Y, X}}, X}}, [=]{ return X; }, true},
{{Instruction::AND, {X, {Instruction::NOT, {X}}}}, [=]{ return u256(0); }, true},
{{Instruction::AND, {{Instruction::NOT, {X}}, X}}, [=]{ return u256(0); }, true},
{{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true},
{{Instruction::OR, {{Instruction::NOT, {X}}, X}}, [=]{ return ~u256(0); }, true},
}; };
// Double negation of opcodes with binary result // Double negation of opcodes with boolean result
for (auto const& op: std::vector<Instruction>{ for (auto const& op: std::vector<Instruction>{
Instruction::EQ, Instruction::EQ,
Instruction::LT, Instruction::LT,
@ -174,29 +191,34 @@ std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>> simplificationR
{ {
auto op = opFun.first; auto op = opFun.first;
auto fun = opFun.second; auto fun = opFun.second;
// Moving constants to the outside, order matters here! // Moving constants to the outside, order matters here - we first add rules
// we need actions that return expressions (or patterns?) here, and we need also reversed rules // for constants and then for non-constants.
// (X+A)+B -> X+(A+B) // xa can be (X, A) or (A, X)
for (auto xa: {std::vector<Pattern>{X, A}, std::vector<Pattern>{A, X}})
{
rules += std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>>{{ rules += std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>>{{
{op, {{op, {X, A}}, B}}, // (X+A)+B -> X+(A+B)
{op, {{op, xa}, B}},
[=]() -> Pattern { return {op, {X, fun(A.d(), B.d())}}; }, [=]() -> Pattern { return {op, {X, fun(A.d(), B.d())}}; },
false false
}, { }, {
// X+(Y+A) -> (X+Y)+A // (X+A)+Y -> (X+Y)+A
{op, {{op, {X, A}}, Y}}, {op, {{op, xa}, Y}},
[=]() -> Pattern { return {op, {{op, {X, Y}}, A}}; }, [=]() -> Pattern { return {op, {{op, {X, Y}}, A}}; },
false false
}, { }, {
// For now, we still need explicit commutativity for the inner pattern // B+(X+A) -> X+(A+B)
{op, {{op, {A, X}}, B}}, {op, {B, {op, xa}}},
[=]() -> Pattern { return {op, {X, fun(A.d(), B.d())}}; }, [=]() -> Pattern { return {op, {X, fun(A.d(), B.d())}}; },
false false
}, { }, {
{op, {{op, {A, X}}, Y}}, // Y+(X+A) -> (Y+X)+A
[=]() -> Pattern { return {op, {{op, {X, Y}}, A}}; }, {op, {Y, {op, xa}}},
[=]() -> Pattern { return {op, {{op, {Y, X}}, A}}; },
false false
}}; }};
} }
}
// move constants across subtractions // move constants across subtractions
rules += std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>>{ rules += std::vector<std::tuple<Pattern, std::function<Pattern()>, bool>>{