aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-04-03 01:20:30 +0800
committerchriseth <c@ethdev.com>2015-04-16 00:11:16 +0800
commitcf9515c750474fdd7f31e53efd30be7438786b96 (patch)
tree28169ee7dee60c13a65cc43f72ed2a2196326b7c
parent5469743891679267ea1fdad0cd68099101e43b19 (diff)
downloaddexon-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.cpp80
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()
}