diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index ce00e95df..f2422ce58 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -271,9 +271,7 @@ std::vector> simplificationRuleListPart5( Instruction::ADDRESS, Instruction::CALLER, Instruction::ORIGIN, - Instruction::COINBASE, - Instruction::CREATE, - Instruction::CREATE2 + Instruction::COINBASE }) { u256 const mask = (u256(1) << 160) - 1; @@ -288,6 +286,7 @@ std::vector> simplificationRuleListPart5( false }); } + return rules; } @@ -565,8 +564,48 @@ std::vector> simplificationRuleListPart8( return rules; } +template +std::vector> simplificationRuleListPart9( + Pattern, + Pattern, + Pattern, + Pattern W, + Pattern X, + Pattern Y, + Pattern Z +) +{ + std::vector> 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. -/// 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 /// arbitrary operations. template @@ -574,19 +613,22 @@ std::vector> simplificationRuleList( Pattern A, Pattern B, Pattern C, + Pattern W, Pattern X, - Pattern Y + Pattern Y, + Pattern Z ) { std::vector> rules; - rules += simplificationRuleListPart1(A, B, C, X, Y); - rules += simplificationRuleListPart2(A, B, C, X, Y); - rules += simplificationRuleListPart3(A, B, C, X, Y); - rules += simplificationRuleListPart4(A, B, C, X, Y); - rules += simplificationRuleListPart5(A, B, C, X, Y); - rules += simplificationRuleListPart6(A, B, C, X, Y); - rules += simplificationRuleListPart7(A, B, C, X, Y); - rules += simplificationRuleListPart8(A, B, C, X, Y); + rules += simplificationRuleListPart1(A, B, C, W, X); + rules += simplificationRuleListPart2(A, B, C, W, X); + rules += simplificationRuleListPart3(A, B, C, W, X); + rules += simplificationRuleListPart4(A, B, C, W, X); + rules += simplificationRuleListPart5(A, B, C, W, X); + rules += simplificationRuleListPart6(A, B, C, W, X); + rules += simplificationRuleListPart7(A, B, C, W, X); + rules += simplificationRuleListPart8(A, B, C, W, X); + rules += simplificationRuleListPart9(A, B, C, W, X, Y, Z); return rules; } diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index 9fee79cf4..ca201862a 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -83,15 +83,19 @@ Rules::Rules() Pattern B(Push); Pattern C(Push); // Anything. + Pattern W; Pattern X; Pattern Y; + Pattern Z; A.setMatchGroup(1, m_matchGroups); B.setMatchGroup(2, m_matchGroups); C.setMatchGroup(3, m_matchGroups); - X.setMatchGroup(4, m_matchGroups); - Y.setMatchGroup(5, m_matchGroups); + W.setMatchGroup(4, 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."); } diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 48e883701..3f5d8541b 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -97,15 +97,19 @@ SimplificationRules::SimplificationRules() Pattern B(PatternKind::Constant); Pattern C(PatternKind::Constant); // Anything. + Pattern W; Pattern X; Pattern Y; + Pattern Z; A.setMatchGroup(1, m_matchGroups); B.setMatchGroup(2, m_matchGroups); C.setMatchGroup(3, m_matchGroups); - X.setMatchGroup(4, m_matchGroups); - Y.setMatchGroup(5, m_matchGroups); + W.setMatchGroup(4, 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."); } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul new file mode 100644 index 000000000..cd74d73ad --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create2_and_mask.yul @@ -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) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul new file mode 100644 index 000000000..c7cc887dc --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul @@ -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) +// }