diff options
author | chriseth <c@ethdev.com> | 2015-04-03 01:20:30 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-04-16 00:11:16 +0800 |
commit | cf9515c750474fdd7f31e53efd30be7438786b96 (patch) | |
tree | 28169ee7dee60c13a65cc43f72ed2a2196326b7c | |
parent | 5469743891679267ea1fdad0cd68099101e43b19 (diff) | |
download | dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar.gz dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar.bz2 dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar.lz dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar.xz dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.tar.zst dexon-solidity-cf9515c750474fdd7f31e53efd30be7438786b96.zip |
Control flow analysis.
-rw-r--r-- | SolidityOptimizer.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/SolidityOptimizer.cpp b/SolidityOptimizer.cpp index f523847f..450ae3c2 100644 --- a/SolidityOptimizer.cpp +++ b/SolidityOptimizer.cpp @@ -28,6 +28,7 @@ #include <boost/lexical_cast.hpp> #include <test/solidityExecutionFramework.h> #include <libevmcore/CommonSubexpressionEliminator.h> +#include <libevmcore/ControlFlowGraph.h> #include <libevmcore/Assembly.h> using namespace std; @@ -96,6 +97,18 @@ public: BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } + void checkCFG(AssemblyItems const& _input, AssemblyItems const& _expectation) + { + AssemblyItems output = _input; + // Running it four times should be enough for these tests. + for (unsigned i = 0; i < 4; ++i) + { + eth::ControlFlowGraph cfg(output); + output = cfg.optimisedItems(); + } + BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); + } + protected: Address m_optimizedContract; Address m_nonOptimizedContract; @@ -731,6 +744,73 @@ BOOST_AUTO_TEST_CASE(cse_sha3_twice_same_content_noninterfering_store_in_between BOOST_CHECK_EQUAL(1, count(output.begin(), output.end(), AssemblyItem(Instruction::SHA3))); } +BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused) +{ + // remove parts of the code that are unused + AssemblyItems input{ + AssemblyItem(PushTag, 1), + Instruction::JUMP, + u256(7), + AssemblyItem(Tag, 1), + }; + checkCFG(input, {}); +} + +BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused_loop) +{ + AssemblyItems input{ + AssemblyItem(PushTag, 3), + Instruction::JUMP, + AssemblyItem(Tag, 1), + u256(7), + AssemblyItem(PushTag, 2), + Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(8), + AssemblyItem(PushTag, 1), + Instruction::JUMP, + AssemblyItem(Tag, 3), + u256(11) + }; + checkCFG(input, {u256(11)}); +} + +BOOST_AUTO_TEST_CASE(control_flow_graph_reconnect_single_jump_source) +{ + // move code that has only one unconditional jump source + AssemblyItems input{ + u256(1), + AssemblyItem(PushTag, 1), + Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(2), + AssemblyItem(PushTag, 3), + Instruction::JUMP, + AssemblyItem(Tag, 1), + u256(3), + AssemblyItem(PushTag, 2), + Instruction::JUMP, + AssemblyItem(Tag, 3), + u256(4), + }; + checkCFG(input, {u256(1), u256(3), u256(2), u256(4)}); +} + +BOOST_AUTO_TEST_CASE(control_flow_graph_do_not_remove_returned_to) +{ + // do not remove parts that are "returned to" + AssemblyItems input{ + AssemblyItem(PushTag, 1), + AssemblyItem(PushTag, 2), + Instruction::JUMP, + AssemblyItem(Tag, 2), + Instruction::JUMP, + AssemblyItem(PushTag, 1), + u256(2) + }; + checkCFG(input, {u256(2)}); +} + BOOST_AUTO_TEST_SUITE_END() } |