yul: Add new optimizer rules for create and create2 builtins

This commit is contained in:
Bhargava Shastry 2019-09-09 13:37:25 +02:00
parent 96b6b45658
commit 09fa31ccc5
5 changed files with 92 additions and 19 deletions

View File

@ -271,9 +271,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5(
Instruction::ADDRESS, Instruction::ADDRESS,
Instruction::CALLER, Instruction::CALLER,
Instruction::ORIGIN, Instruction::ORIGIN,
Instruction::COINBASE, Instruction::COINBASE
Instruction::CREATE,
Instruction::CREATE2
}) })
{ {
u256 const mask = (u256(1) << 160) - 1; u256 const mask = (u256(1) << 160) - 1;
@ -288,6 +286,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5(
false false
}); });
} }
return rules; return rules;
} }
@ -565,8 +564,48 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart8(
return rules; return rules;
} }
template <class Pattern>
std::vector<SimplificationRule<Pattern>> simplificationRuleListPart9(
Pattern,
Pattern,
Pattern,
Pattern W,
Pattern X,
Pattern Y,
Pattern Z
)
{
std::vector<SimplificationRule<Pattern>> rules;
u256 const mask = (u256(1) << 160) - 1;
// CREATE
rules.push_back({
{Instruction::AND, {{Instruction::CREATE, {W, X, Y}}, mask}},
[=]() -> Pattern { return {Instruction::CREATE, {W, X, Y}}; },
false
});
rules.push_back({
{Instruction::AND, {{mask, {Instruction::CREATE, {W, X, Y}}}}},
[=]() -> Pattern { return {Instruction::CREATE, {W, X, Y}}; },
false
});
// CREATE2
rules.push_back({
{Instruction::AND, {{Instruction::CREATE2, {W, X, Y, Z}}, mask}},
[=]() -> Pattern { return {Instruction::CREATE2, {W, X, Y, Z}}; },
false
});
rules.push_back({
{Instruction::AND, {{mask, {Instruction::CREATE2, {W, X, Y, Z}}}}},
[=]() -> Pattern { return {Instruction::CREATE2, {W, X, Y, Z}}; },
false
});
return rules;
}
/// @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, W, X, Y, and Z arbitrary expressions.
/// The simplifications should never change the order of evaluation of /// The simplifications should never change the order of evaluation of
/// arbitrary operations. /// arbitrary operations.
template <class Pattern> template <class Pattern>
@ -574,19 +613,22 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList(
Pattern A, Pattern A,
Pattern B, Pattern B,
Pattern C, Pattern C,
Pattern W,
Pattern X, Pattern X,
Pattern Y Pattern Y,
Pattern Z
) )
{ {
std::vector<SimplificationRule<Pattern>> rules; std::vector<SimplificationRule<Pattern>> rules;
rules += simplificationRuleListPart1(A, B, C, X, Y); rules += simplificationRuleListPart1(A, B, C, W, X);
rules += simplificationRuleListPart2(A, B, C, X, Y); rules += simplificationRuleListPart2(A, B, C, W, X);
rules += simplificationRuleListPart3(A, B, C, X, Y); rules += simplificationRuleListPart3(A, B, C, W, X);
rules += simplificationRuleListPart4(A, B, C, X, Y); rules += simplificationRuleListPart4(A, B, C, W, X);
rules += simplificationRuleListPart5(A, B, C, X, Y); rules += simplificationRuleListPart5(A, B, C, W, X);
rules += simplificationRuleListPart6(A, B, C, X, Y); rules += simplificationRuleListPart6(A, B, C, W, X);
rules += simplificationRuleListPart7(A, B, C, X, Y); rules += simplificationRuleListPart7(A, B, C, W, X);
rules += simplificationRuleListPart8(A, B, C, X, Y); rules += simplificationRuleListPart8(A, B, C, W, X);
rules += simplificationRuleListPart9(A, B, C, W, X, Y, Z);
return rules; return rules;
} }

View File

@ -83,15 +83,19 @@ Rules::Rules()
Pattern B(Push); Pattern B(Push);
Pattern C(Push); Pattern C(Push);
// Anything. // Anything.
Pattern W;
Pattern X; Pattern X;
Pattern Y; Pattern Y;
Pattern Z;
A.setMatchGroup(1, m_matchGroups); A.setMatchGroup(1, m_matchGroups);
B.setMatchGroup(2, m_matchGroups); B.setMatchGroup(2, m_matchGroups);
C.setMatchGroup(3, m_matchGroups); C.setMatchGroup(3, m_matchGroups);
X.setMatchGroup(4, m_matchGroups); W.setMatchGroup(4, m_matchGroups);
Y.setMatchGroup(5, m_matchGroups); X.setMatchGroup(5, m_matchGroups);
Y.setMatchGroup(6, m_matchGroups);
Z.setMatchGroup(7, m_matchGroups);
addRules(simplificationRuleList(A, B, C, X, Y)); addRules(simplificationRuleList(A, B, C, W, X, Y, Z));
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
} }

View File

@ -97,15 +97,19 @@ SimplificationRules::SimplificationRules()
Pattern B(PatternKind::Constant); Pattern B(PatternKind::Constant);
Pattern C(PatternKind::Constant); Pattern C(PatternKind::Constant);
// Anything. // Anything.
Pattern W;
Pattern X; Pattern X;
Pattern Y; Pattern Y;
Pattern Z;
A.setMatchGroup(1, m_matchGroups); A.setMatchGroup(1, m_matchGroups);
B.setMatchGroup(2, m_matchGroups); B.setMatchGroup(2, m_matchGroups);
C.setMatchGroup(3, m_matchGroups); C.setMatchGroup(3, m_matchGroups);
X.setMatchGroup(4, m_matchGroups); W.setMatchGroup(4, m_matchGroups);
Y.setMatchGroup(5, m_matchGroups); X.setMatchGroup(5, m_matchGroups);
Y.setMatchGroup(6, m_matchGroups);
Z.setMatchGroup(7, m_matchGroups);
addRules(simplificationRuleList(A, B, C, X, Y)); addRules(simplificationRuleList(A, B, C, W, X, Y, Z));
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
} }

View File

@ -0,0 +1,12 @@
{
let a := and(create2(0, 0, 0x20, 0), 0xffffffffffffffffffffffffffffffffffffffff)
let b := and(0xffffffffffffffffffffffffffffffffffffffff, create2(0, 0, 0x20, 0))
}
// ====
// step: expressionSimplifier
// EVMVersion: >=constantinople
// ----
// {
// let a := create2(0, 0, 0x20, 0)
// let b := create2(0, 0, 0x20, 0)
// }

View File

@ -0,0 +1,11 @@
{
let a := and(create(0, 0, 0x20), 0xffffffffffffffffffffffffffffffffffffffff)
let b := and(0xffffffffffffffffffffffffffffffffffffffff, create(0, 0, 0x20))
}
// ====
// step: expressionSimplifier
// ----
// {
// let a := create(0, 0, 0x20)
// let b := create(0, 0, 0x20)
// }