diff options
author | Daniel Kirchner <daniel@ekpyron.org> | 2019-01-17 21:57:55 +0800 |
---|---|---|
committer | Daniel Kirchner <daniel@ekpyron.org> | 2019-01-18 03:37:43 +0800 |
commit | fd1658572463a246f602ae0fe161430429daa9e0 (patch) | |
tree | 40f3c0e5adf7a424e35b1218376a9ae9f7129811 | |
parent | 6de2d92f20d48d38797a628ee35e7615170cd63f (diff) | |
download | dexon-solidity-fd1658572463a246f602ae0fe161430429daa9e0.tar.gz dexon-solidity-fd1658572463a246f602ae0fe161430429daa9e0.tar.zst dexon-solidity-fd1658572463a246f602ae0fe161430429daa9e0.zip |
Undo second SSA transformation and add more tests.
15 files changed, 366 insertions, 75 deletions
diff --git a/libyul/optimiser/SSAReverser.cpp b/libyul/optimiser/SSAReverser.cpp index 313a677a..2cfa3d58 100644 --- a/libyul/optimiser/SSAReverser.cpp +++ b/libyul/optimiser/SSAReverser.cpp @@ -29,42 +29,74 @@ void SSAReverser::operator()(Block& _block) _block.statements, [&](Statement& _stmt1, Statement& _stmt2) -> boost::optional<vector<Statement>> { + auto* varDecl = boost::get<VariableDeclaration>(&_stmt1); + + if (!varDecl || varDecl->variables.size() != 1 || !varDecl->value) + return {}; + // Replaces // let a_1 := E // a := a_1 // with // a := E // let a_1 := a - - auto* varDecl = boost::get<VariableDeclaration>(&_stmt1); - auto* assignment = boost::get<Assignment>(&_stmt2); - - if (!varDecl || !assignment) - return {}; - - auto* identifier = boost::get<Identifier>(assignment->value.get()); - - if ( - varDecl->variables.size() == 1 && - varDecl->value && - assignment->variableNames.size() == 1 && - identifier && - identifier->name == varDecl->variables.front().name - ) + if (auto* assignment = boost::get<Assignment>(&_stmt2)) + { + auto* identifier = boost::get<Identifier>(assignment->value.get()); + if ( + assignment->variableNames.size() == 1 && + identifier && + identifier->name == varDecl->variables.front().name + ) + { + vector<Statement> result; + result.emplace_back(Assignment{ + std::move(assignment->location), + assignment->variableNames, + std::move(varDecl->value) + }); + result.emplace_back(VariableDeclaration{ + std::move(varDecl->location), + std::move(varDecl->variables), + std::make_unique<Expression>(std::move(assignment->variableNames.front())) + }); + return { std::move(result) }; + } + } + // Replaces + // let a_1 := E + // let a := a_1 + // with + // let a := E + // let a_1 := a + else if (auto* varDecl2 = boost::get<VariableDeclaration>(&_stmt2)) { - vector<Statement> result; - result.emplace_back(Assignment{ - std::move(assignment->location), - assignment->variableNames, - std::move(varDecl->value) - }); - result.emplace_back(VariableDeclaration{ - std::move(varDecl->location), - std::move(varDecl->variables), - std::make_unique<Expression>(std::move(assignment->variableNames.front())) - }); - return { std::move(result) }; + auto* identifier = boost::get<Identifier>(varDecl2->value.get()); + if ( + varDecl2->variables.size() == 1 && + identifier && + identifier->name == varDecl->variables.front().name + ) + { + vector<Statement> result; + auto varIdentifier2 = std::make_unique<Expression>(Identifier{ + varDecl2->variables.front().location, + varDecl2->variables.front().name + }); + result.emplace_back(VariableDeclaration{ + std::move(varDecl2->location), + std::move(varDecl2->variables), + std::move(varDecl->value) + }); + result.emplace_back(VariableDeclaration{ + std::move(varDecl->location), + std::move(varDecl->variables), + std::move(varIdentifier2) + }); + return { std::move(result) }; + } } + return {}; } ); diff --git a/libyul/optimiser/SSAReverser.h b/libyul/optimiser/SSAReverser.h index a4a11074..34b61647 100644 --- a/libyul/optimiser/SSAReverser.h +++ b/libyul/optimiser/SSAReverser.h @@ -33,11 +33,24 @@ namespace yul * let a_1 := E * a := a_1 * - * To undo this transformation, the SSAReverser changes this back to + * To undo this kind of transformation, the SSAReverser changes this back to * * a := E * let a_1 := a * + * Secondly, the SSA transform will rewrite + * + * let a := E + * to + * + * let a_1 := E + * let a := a_1 + * + * To undo this kind of transformation, the SSAReverser changes this back to + * + * let a := E + * let a_1 := a + * * After that the CSE can replace references of a_1 by references to a, * after which the unused pruner can remove the declaration of a_1. * diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul index 05a35673..d38025ae 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -531,8 +531,7 @@ // { // revert(0, 0) // } -// let i_9_296 := 0 -// let i_9 := i_9_296 +// let i_9 := 0 // for { // } // lt(i_9, length_6) @@ -542,17 +541,17 @@ // { // if iszero(slt(add(src_8, 0x1f), end_4)) // { -// revert(i_9_296, i_9_296) +// revert(0, 0) // } -// let abi_decode_array_13_300 := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(0x2)) -// let abi_decode_dst_15 := abi_decode_array_13_300 +// let abi_decode_dst_15 := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(0x2)) +// let abi_decode_dst_15_1155 := abi_decode_dst_15 // let abi_decode_src_16 := src_8 // let abi_decode__239 := add(src_8, 0x40) // if gt(abi_decode__239, end_4) // { -// revert(i_9_296, i_9_296) +// revert(0, 0) // } -// let abi_decode_i_17 := i_9_296 +// let abi_decode_i_17 := 0 // for { // } // lt(abi_decode_i_17, 0x2) @@ -564,7 +563,7 @@ // abi_decode_dst_15 := add(abi_decode_dst_15, _16) // abi_decode_src_16 := add(abi_decode_src_16, _16) // } -// mstore(dst_7, abi_decode_array_13_300) +// mstore(dst_7, abi_decode_dst_15_1155) // dst_7 := add(dst_7, _16) // src_8 := abi_decode__239 // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index e05a3c92..868c6b01 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -245,17 +245,16 @@ // mstore(0x00, 404) // revert(0x00, 0x20) // } -// let validateJo_kn_287 := calldataload(add(calldatasize(), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40)) -// let validateJo_kn := validateJo_kn_287 +// let validateJo_kn := calldataload(add(calldatasize(), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40)) // let validateJo__24 := 0x2a0 // mstore(validateJo__24, caller()) -// mstore(0x2c0, validateJo_kn_287) +// mstore(0x2c0, validateJo_kn) // mstore(0x2e0, validateJo_m) -// validateJo_kn := mulmod(sub(validateJo_gen_order, validateJo_kn_287), validateJo_challenge, validateJo_gen_order) +// validateJo_kn := mulmod(sub(validateJo_gen_order, validateJo_kn), validateJo_challenge, validateJo_gen_order) // hashCommitments(validateJo_notes, validateJo_n) // let validateJo_b := add(0x300, mul(validateJo_n, validateJo__6)) -// let validateJo_i_290 := 0 -// let validateJo_i := validateJo_i_290 +// let validateJo_i := 0 +// let validateJo_i_1306 := validateJo_i // for { // } // lt(validateJo_i, validateJo_n) @@ -266,9 +265,8 @@ // let validateJo__34 := 0x20 // let validateJo__351 := add(validateJo__10, mul(validateJo_i, 0xc0)) // let validateJo_noteIndex := add(validateJo__351, 0x24) -// let validateJo_k := validateJo_i_290 -// let validateJo_a_292 := calldataload(add(validateJo__351, 0x44)) -// let validateJo_a := validateJo_a_292 +// let validateJo_k := validateJo_i_1306 +// let validateJo_a := calldataload(add(validateJo__351, 0x44)) // let validateJo_c := validateJo_challenge // let validateJo__39 := add(validateJo_i, 0x01) // switch eq(validateJo__39, validateJo_n) @@ -282,15 +280,15 @@ // case 0 { // validateJo_k := calldataload(validateJo_noteIndex) // } -// validateCommitment(validateJo_noteIndex, validateJo_k, validateJo_a_292) +// validateCommitment(validateJo_noteIndex, validateJo_k, validateJo_a) // switch gt(validateJo__39, validateJo_m) // case 1 { // validateJo_kn := addmod(validateJo_kn, sub(validateJo_gen_order, validateJo_k), validateJo_gen_order) -// let validateJo_x := mod(mload(validateJo_i_290), validateJo_gen_order) +// let validateJo_x := mod(mload(validateJo_i_1306), validateJo_gen_order) // validateJo_k := mulmod(validateJo_k, validateJo_x, validateJo_gen_order) -// validateJo_a := mulmod(validateJo_a_292, validateJo_x, validateJo_gen_order) +// validateJo_a := mulmod(validateJo_a, validateJo_x, validateJo_gen_order) // validateJo_c := mulmod(validateJo_challenge, validateJo_x, validateJo_gen_order) -// mstore(validateJo_i_290, keccak256(validateJo_i_290, validateJo__34)) +// mstore(validateJo_i_1306, keccak256(validateJo_i_1306, validateJo__34)) // } // case 0 { // validateJo_kn := addmod(validateJo_kn, validateJo_k, validateJo_gen_order) @@ -304,13 +302,12 @@ // mstore(validateJo__62, validateJo_k) // mstore(0xc0, validateJo_a) // let validateJo__65 := 0x1a0 -// let validateJo_result_302 := call(gas(), 7, validateJo_i_290, 0xe0, validateJo__62, validateJo__65, validateJo__52) -// let validateJo_result := validateJo_result_302 -// let validateJo_result_303 := and(validateJo_result_302, call(gas(), 7, validateJo_i_290, validateJo__34, validateJo__62, validateJo__61, validateJo__52)) +// let validateJo_result := call(gas(), 7, validateJo_i_1306, 0xe0, validateJo__62, validateJo__65, validateJo__52) +// let validateJo_result_303 := and(validateJo_result, call(gas(), 7, validateJo_i_1306, validateJo__34, validateJo__62, validateJo__61, validateJo__52)) // let validateJo__80 := 0x160 -// let validateJo_result_304 := and(validateJo_result_303, call(gas(), 7, validateJo_i_290, validateJo__6, validateJo__62, validateJo__80, validateJo__52)) -// let validateJo_result_305 := and(validateJo_result_304, call(gas(), 6, validateJo_i_290, validateJo__61, validateJo__6, validateJo__80, validateJo__52)) -// validateJo_result := and(validateJo_result_305, call(gas(), 6, validateJo_i_290, validateJo__80, validateJo__6, validateJo_b, validateJo__52)) +// let validateJo_result_304 := and(validateJo_result_303, call(gas(), 7, validateJo_i_1306, validateJo__6, validateJo__62, validateJo__80, validateJo__52)) +// let validateJo_result_305 := and(validateJo_result_304, call(gas(), 6, validateJo_i_1306, validateJo__61, validateJo__6, validateJo__80, validateJo__52)) +// validateJo_result := and(validateJo_result_305, call(gas(), 6, validateJo_i_1306, validateJo__80, validateJo__6, validateJo_b, validateJo__52)) // if eq(validateJo_i, validateJo_m) // { // mstore(0x260, mload(validateJo__34)) @@ -322,14 +319,14 @@ // { // mstore(validateJo__62, validateJo_c) // let validateJo__120 := 0x220 -// let validateJo_result_307 := and(validateJo_result, call(gas(), 7, validateJo_i_290, validateJo__34, validateJo__62, validateJo__120, validateJo__52)) -// let validateJo_result_308 := and(validateJo_result_307, call(gas(), 6, validateJo_i_290, validateJo__120, validateJo__6, 0x260, validateJo__52)) -// validateJo_result := and(validateJo_result_308, call(gas(), 6, validateJo_i_290, validateJo__65, validateJo__6, 0x1e0, validateJo__52)) +// let validateJo_result_307 := and(validateJo_result, call(gas(), 7, validateJo_i_1306, validateJo__34, validateJo__62, validateJo__120, validateJo__52)) +// let validateJo_result_308 := and(validateJo_result_307, call(gas(), 6, validateJo_i_1306, validateJo__120, validateJo__6, 0x260, validateJo__52)) +// validateJo_result := and(validateJo_result_308, call(gas(), 6, validateJo_i_1306, validateJo__65, validateJo__6, 0x1e0, validateJo__52)) // } // if iszero(validateJo_result) // { -// mstore(validateJo_i_290, 400) -// revert(validateJo_i_290, validateJo__34) +// mstore(validateJo_i_1306, 400) +// revert(validateJo_i_1306, validateJo__34) // } // validateJo_b := add(validateJo_b, validateJo__52) // } @@ -339,13 +336,13 @@ // } // if iszero(eq(mod(keccak256(validateJo__24, add(validateJo_b, 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd60)), validateJo_gen_order), validateJo_challenge)) // { -// mstore(validateJo_i_290, 404) -// revert(validateJo_i_290, 0x20) +// mstore(validateJo_i_1306, 404) +// revert(validateJo_i_1306, 0x20) // } -// mstore(validateJo_i_290, 0x01) -// return(validateJo_i_290, 0x20) -// mstore(validateJo_i_290, 404) -// revert(validateJo_i_290, 0x20) +// mstore(validateJo_i_1306, 0x01) +// return(validateJo_i_1306, 0x20) +// mstore(validateJo_i_1306, 404) +// revert(validateJo_i_1306, 0x20) // function validatePairing(t2) // { // let t2_x_1 := calldataload(t2) diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul new file mode 100644 index 00000000..2e178f31 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverseComplex.yul @@ -0,0 +1,23 @@ +{ + let a := mload(0) + let b := mload(1) + if mload(2) { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + mstore(a, b) +} +// ---- +// fullSuite +// { +// let a := mload(0) +// let b := mload(1) +// if mload(2) +// { +// a := mload(mload(mload(b))) +// b := mload(a) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul new file mode 100644 index 00000000..18498e61 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul @@ -0,0 +1,36 @@ +{ + for { + let a := mload(0) + let b := mload(1) + } + lt(mload(a),mload(b)) + { + a := mload(b) + } + { + b := mload(a) + a := mload(b) + a := mload(b) + a := mload(b) + b := mload(a) + } +} +// ---- +// ssaAndBack +// { +// for { +// let a := mload(0) +// let b := mload(1) +// } +// lt(mload(a), mload(b)) +// { +// a := mload(b) +// } +// { +// let b_3 := mload(a) +// pop(mload(b_3)) +// pop(mload(b_3)) +// let a_6 := mload(b_3) +// b := mload(a_6) +// } +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul new file mode 100644 index 00000000..23c433d1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul @@ -0,0 +1,18 @@ +{ + let a := mload(0) + a := mload(1) + a := mload(2) + a := mload(3) + a := mload(4) + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// pop(mload(0)) +// pop(mload(1)) +// pop(mload(2)) +// pop(mload(3)) +// let a_5 := mload(4) +// mstore(a_5, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul new file mode 100644 index 00000000..fd5981ef --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_if.yul @@ -0,0 +1,22 @@ +{ + let a := mload(0) + if mload(1) + { + a := mload(1) + a := mload(2) + a := mload(3) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// if mload(1) +// { +// pop(mload(1)) +// pop(mload(2)) +// a := mload(3) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul new file mode 100644 index 00000000..b0b3efb5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul @@ -0,0 +1,25 @@ +{ + let a := mload(0) + let b := mload(1) + if mload(2) { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// let b := mload(1) +// if mload(2) +// { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul new file mode 100644 index 00000000..50f56b87 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul @@ -0,0 +1,38 @@ +{ + let a := mload(0) + let b := mload(1) + switch mload(2) + case 0 { + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + } + default { + b := mload(a) + a := mload(b) + b := mload(a) + a := mload(b) + } + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// let b := mload(1) +// switch mload(2) +// case 0 { +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// a := mload(b_4) +// b := mload(a) +// } +// default { +// let b_7 := mload(a) +// let a_8 := mload(b_7) +// b := mload(a_8) +// a := mload(b) +// } +// mstore(a, b) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul new file mode 100644 index 00000000..1efbbde7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_switch.yul @@ -0,0 +1,32 @@ +{ + let a := mload(0) + switch mload(1) + case 0 { + a := mload(1) + a := mload(2) + a := mload(3) + } + default { + a := mload(4) + a := mload(5) + a := mload(6) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// switch mload(1) +// case 0 { +// pop(mload(1)) +// pop(mload(2)) +// a := mload(3) +// } +// default { +// pop(mload(4)) +// pop(mload(5)) +// a := mload(6) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul index 23c433d1..912940c5 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul @@ -1,18 +1,12 @@ { let a := mload(0) a := mload(1) - a := mload(2) - a := mload(3) - a := mload(4) mstore(a, 0) } // ---- // ssaAndBack // { // pop(mload(0)) -// pop(mload(1)) -// pop(mload(2)) -// pop(mload(3)) -// let a_5 := mload(4) -// mstore(a_5, 0) +// let a_2 := mload(1) +// mstore(a_2, 0) // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul new file mode 100644 index 00000000..5185245c --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_if.yul @@ -0,0 +1,18 @@ +{ + let a := mload(0) + if mload(1) + { + a := mload(1) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// if mload(1) +// { +// a := mload(1) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul new file mode 100644 index 00000000..e0e53b3f --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/single_assign_switch.yul @@ -0,0 +1,24 @@ +{ + let a := mload(0) + switch mload(1) + case 0 { + a := mload(1) + } + default { + a := mload(2) + } + mstore(a, 0) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// switch mload(1) +// case 0 { +// a := mload(1) +// } +// default { +// a := mload(2) +// } +// mstore(a, 0) +// } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul new file mode 100644 index 00000000..85325fb9 --- /dev/null +++ b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul @@ -0,0 +1,20 @@ +{ + let a := mload(0) + let b := mload(a) + a := mload(b) + b := mload(a) + a := mload(b) + b := mload(a) + mstore(a, b) +} +// ---- +// ssaAndBack +// { +// let a := mload(0) +// let b := mload(a) +// let a_3 := mload(b) +// let b_4 := mload(a_3) +// let a_5 := mload(b_4) +// let b_6 := mload(a_5) +// mstore(a_5, b_6) +// } |