aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-03-31 22:37:13 +0800
committerchriseth <c@ethdev.com>2015-03-31 22:37:13 +0800
commit1ba183bf780a28c188600aaf12d3f6df0cf5691d (patch)
tree61a12b936352dd8dc62f6eff946e2835ca3fe855
parent91336ce42b1616ee8af39d5b2be9c96f097d375f (diff)
parent35274fb9b1a89589b60de7f54913d5f77712c6af (diff)
downloaddexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar.gz
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar.bz2
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar.lz
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar.xz
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.tar.zst
dexon-solidity-1ba183bf780a28c188600aaf12d3f6df0cf5691d.zip
Merge pull request #1432 from chriseth/sol_cseForMemoryAndStorage
Optimizer for memory and storage.
-rw-r--r--SolidityOptimizer.cpp265
1 files changed, 265 insertions, 0 deletions
diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp
index 2d5cff7a..e69d5120 100644
--- a/SolidityOptimizer.cpp
+++ b/SolidityOptimizer.cpp
@@ -303,6 +303,271 @@ BOOST_AUTO_TEST_CASE(cse_associativity2)
checkCSE(input, {Instruction::DUP2, Instruction::DUP2, Instruction::ADD, u256(5), Instruction::ADD});
}
+BOOST_AUTO_TEST_CASE(cse_storage)
+{
+ AssemblyItems input{
+ u256(0),
+ Instruction::SLOAD,
+ u256(0),
+ Instruction::SLOAD,
+ Instruction::ADD,
+ u256(0),
+ Instruction::SSTORE
+ };
+ checkCSE(input, {
+ u256(0),
+ Instruction::DUP1,
+ Instruction::SLOAD,
+ Instruction::DUP1,
+ Instruction::ADD,
+ Instruction::SWAP1,
+ Instruction::SSTORE
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_noninterleaved_storage)
+{
+ // two stores to the same location should be replaced by only one store, even if we
+ // read in the meantime
+ AssemblyItems input{
+ u256(7),
+ Instruction::DUP2,
+ Instruction::SSTORE,
+ Instruction::DUP1,
+ Instruction::SLOAD,
+ u256(8),
+ Instruction::DUP3,
+ Instruction::SSTORE
+ };
+ checkCSE(input, {
+ u256(8),
+ Instruction::DUP2,
+ Instruction::SSTORE,
+ u256(7)
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_interleaved_storage)
+{
+ // stores and reads to/from two unknown locations, should not optimize away the first store
+ AssemblyItems input{
+ u256(7),
+ Instruction::DUP2,
+ Instruction::SSTORE, // store to "DUP1"
+ Instruction::DUP2,
+ Instruction::SLOAD, // read from "DUP2", might be equal to "DUP1"
+ u256(0),
+ Instruction::DUP3,
+ Instruction::SSTORE // store different value to "DUP1"
+ };
+ checkCSE(input, input);
+}
+
+BOOST_AUTO_TEST_CASE(cse_interleaved_storage_same_value)
+{
+ // stores and reads to/from two unknown locations, should not optimize away the first store
+ // but it should optimize away the second, since we already know the value will be the same
+ AssemblyItems input{
+ u256(7),
+ Instruction::DUP2,
+ Instruction::SSTORE, // store to "DUP1"
+ Instruction::DUP2,
+ Instruction::SLOAD, // read from "DUP2", might be equal to "DUP1"
+ u256(6),
+ u256(1),
+ Instruction::ADD,
+ Instruction::DUP3,
+ Instruction::SSTORE // store same value to "DUP1"
+ };
+ checkCSE(input, {
+ u256(7),
+ Instruction::DUP2,
+ Instruction::SSTORE,
+ Instruction::DUP2,
+ Instruction::SLOAD
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_interleaved_storage_at_known_location)
+{
+ // stores and reads to/from two known locations, should optimize away the first store,
+ // because we know that the location is different
+ AssemblyItems input{
+ u256(0x70),
+ u256(1),
+ Instruction::SSTORE, // store to 1
+ u256(2),
+ Instruction::SLOAD, // read from 2, is different from 1
+ u256(0x90),
+ u256(1),
+ Instruction::SSTORE // store different value at 1
+ };
+ checkCSE(input, {
+ u256(2),
+ Instruction::SLOAD,
+ u256(0x90),
+ u256(1),
+ Instruction::SSTORE
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_interleaved_storage_at_known_location_offset)
+{
+ // stores and reads to/from two locations which are known to be different,
+ // should optimize away the first store, because we know that the location is different
+ AssemblyItems input{
+ u256(0x70),
+ Instruction::DUP2,
+ u256(1),
+ Instruction::ADD,
+ Instruction::SSTORE, // store to "DUP1"+1
+ Instruction::DUP1,
+ u256(2),
+ Instruction::ADD,
+ Instruction::SLOAD, // read from "DUP1"+2, is different from "DUP1"+1
+ u256(0x90),
+ Instruction::DUP3,
+ u256(1),
+ Instruction::ADD,
+ Instruction::SSTORE // store different value at "DUP1"+1
+ };
+ checkCSE(input, {
+ u256(2),
+ Instruction::DUP2,
+ Instruction::ADD,
+ Instruction::SLOAD,
+ u256(0x90),
+ u256(1),
+ Instruction::DUP4,
+ Instruction::ADD,
+ Instruction::SSTORE
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_interleaved_memory_at_known_location_offset)
+{
+ // stores and reads to/from two locations which are known to be different,
+ // should not optimize away the first store, because the location overlaps with the load,
+ // but it should optimize away the second, because we know that the location is different by 32
+ AssemblyItems input{
+ u256(0x50),
+ Instruction::DUP2,
+ u256(2),
+ Instruction::ADD,
+ Instruction::MSTORE, // ["DUP1"+2] = 0x50
+ u256(0x60),
+ Instruction::DUP2,
+ u256(32),
+ Instruction::ADD,
+ Instruction::MSTORE, // ["DUP1"+32] = 0x60
+ Instruction::DUP1,
+ Instruction::MLOAD, // read from "DUP1"
+ u256(0x70),
+ Instruction::DUP3,
+ u256(32),
+ Instruction::ADD,
+ Instruction::MSTORE, // ["DUP1"+32] = 0x70
+ u256(0x80),
+ Instruction::DUP3,
+ u256(2),
+ Instruction::ADD,
+ Instruction::MSTORE, // ["DUP1"+2] = 0x80
+ };
+ // If the actual code changes too much, we could also simply check that the output contains
+ // exactly 3 MSTORE and exactly 1 MLOAD instruction.
+ checkCSE(input, {
+ u256(0x50),
+ u256(2),
+ Instruction::DUP3,
+ Instruction::ADD,
+ Instruction::SWAP1,
+ Instruction::DUP2,
+ Instruction::MSTORE, // ["DUP1"+2] = 0x50
+ Instruction::DUP2,
+ Instruction::MLOAD, // read from "DUP1"
+ u256(0x70),
+ u256(32),
+ Instruction::DUP5,
+ Instruction::ADD,
+ Instruction::MSTORE, // ["DUP1"+32] = 0x70
+ u256(0x80),
+ Instruction::SWAP1,
+ Instruction::SWAP2,
+ Instruction::MSTORE // ["DUP1"+2] = 0x80
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_deep_stack)
+{
+ AssemblyItems input{
+ Instruction::ADD,
+ Instruction::SWAP1,
+ Instruction::POP,
+ Instruction::SWAP8,
+ Instruction::POP,
+ Instruction::SWAP8,
+ Instruction::POP,
+ Instruction::SWAP8,
+ Instruction::SWAP5,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ };
+ checkCSE(input, {
+ Instruction::SWAP4,
+ Instruction::SWAP12,
+ Instruction::SWAP3,
+ Instruction::SWAP11,
+ Instruction::POP,
+ Instruction::SWAP1,
+ Instruction::SWAP3,
+ Instruction::ADD,
+ Instruction::SWAP8,
+ Instruction::POP,
+ Instruction::SWAP6,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ Instruction::POP,
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_jumpi_no_jump)
+{
+ AssemblyItems input{
+ u256(0),
+ u256(1),
+ Instruction::DUP2,
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMPI
+ };
+ checkCSE(input, {
+ u256(0),
+ u256(1)
+ });
+}
+
+BOOST_AUTO_TEST_CASE(cse_jumpi_jump)
+{
+ AssemblyItems input{
+ u256(1),
+ u256(1),
+ Instruction::DUP2,
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMPI
+ };
+ checkCSE(input, {
+ u256(1),
+ Instruction::DUP1,
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMP
+ });
+}
+
BOOST_AUTO_TEST_SUITE_END()
}