diff --git a/Changelog.md b/Changelog.md index a63b80697..e1d6663cf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Bugfixes: Compiler Features: * Build System: Update internal dependency of jsoncpp to 1.9.3. * Optimizer: Add rule to remove shifts inside the byte opcode. + * Peephole Optimizer: Add rule to remove swap after dup. ### 0.6.11 (2020-07-07) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 861cae0f2..343f2f824 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -205,6 +205,30 @@ struct SwapComparison: SimplePeepholeOptimizerMethod } }; +/// Remove swapN after dupN +struct DupSwap: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _dupN, + AssemblyItem const& _swapN, + std::back_insert_iterator _out + ) + { + if ( + SemanticInformation::isDupInstruction(_dupN) && + SemanticInformation::isSwapInstruction(_swapN) && + getDupNumber(_dupN.instruction()) == getSwapNumber(_swapN.instruction()) + ) + { + *_out = _dupN; + return true; + } + else + return false; + } +}; + + struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -357,7 +381,7 @@ bool PeepholeOptimiser::optimise() applyMethods( state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - IsZeroIsZeroJumpI(), JumpToNext(), UnreachableCode(), + DupSwap(), IsZeroIsZeroJumpI(), JumpToNext(), UnreachableCode(), TagConjunctions(), TruthyAnd(), Identity() ); if (m_optimisedItems.size() < m_items.size() || ( diff --git a/test/cmdlineTests/dup_opt_peephole/args b/test/cmdlineTests/dup_opt_peephole/args new file mode 100644 index 000000000..d3047670e --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/args @@ -0,0 +1 @@ +--asm \ No newline at end of file diff --git a/test/cmdlineTests/dup_opt_peephole/err b/test/cmdlineTests/dup_opt_peephole/err new file mode 100644 index 000000000..cfaa88dcf --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/err @@ -0,0 +1,5 @@ +Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. +--> dup_opt_peephole/input.sol + +Warning: Source file does not specify required compiler version! +--> dup_opt_peephole/input.sol diff --git a/test/cmdlineTests/dup_opt_peephole/input.sol b/test/cmdlineTests/dup_opt_peephole/input.sol new file mode 100644 index 000000000..1474a8f44 --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/input.sol @@ -0,0 +1,9 @@ +contract C { + fallback() external { + assembly { + let x := calldataload(0) + x := x + sstore(0, x) + } + } +} diff --git a/test/cmdlineTests/dup_opt_peephole/output b/test/cmdlineTests/dup_opt_peephole/output new file mode 100644 index 000000000..020260c2b --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/output @@ -0,0 +1,54 @@ + +======= dup_opt_peephole/input.sol:C ======= +EVM assembly: + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_3 + jumpi + 0x00 + dup1 + revert + tag_3: + pop + /* "dup_opt_peephole/input.sol":74:75 0 */ + 0x00 + /* "dup_opt_peephole/input.sol":61:76 calldataload(0) */ + calldataload + /* "dup_opt_peephole/input.sol":100:101 x */ + dup1 + /* "dup_opt_peephole/input.sol":97:98 0 */ + 0x00 + /* "dup_opt_peephole/input.sol":90:102 sstore(0, x) */ + sstore + /* "dup_opt_peephole/input.sol":47:106 {... */ + pop + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + stop + + auxdata: AUXDATA REMOVED +}