diff options
author | chriseth <c@ethdev.com> | 2015-04-16 23:26:35 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-04-16 23:26:35 +0800 |
commit | 0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc (patch) | |
tree | 24e50774fe43dae51a95121909aa4bb5dc3b97fd | |
parent | 968ebf6dbc27c1ab489ea64841246a283d985261 (diff) | |
parent | 4362c93ebfcf0c8b5f8de227b6161aee2fb63a66 (diff) | |
download | dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar.gz dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar.bz2 dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar.lz dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar.xz dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.tar.zst dexon-solidity-0f9b0f3bc4fbebb2ab956f0178ec82442065b1bc.zip |
Merge pull request #1503 from chriseth/sol_mergeBasicBlocks
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..f57380ac 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(Tag, 1), + u256(2) + }; + checkCFG(input, {u256(2)}); +} + BOOST_AUTO_TEST_SUITE_END() } |