aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-08-01 22:54:34 +0800
committerGitHub <noreply@github.com>2016-08-01 22:54:34 +0800
commit560471c972e5c83689d812b0be76515597547e58 (patch)
tree963a9850bae4e46656543baa61d5a742b96c80cb
parent74cb76d8fad24fd84a15c309beec28fbe818ec59 (diff)
parente1e6f3ba139b53fa1eb55ad8a87317ce83f67f66 (diff)
downloaddexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar.gz
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar.bz2
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar.lz
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar.xz
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.tar.zst
dexon-solidity-560471c972e5c83689d812b0be76515597547e58.zip
Merge pull request #762 from chriseth/optimizer
Optimizer
-rw-r--r--libevmasm/Assembly.cpp3
-rw-r--r--libevmasm/ControlFlowGraph.cpp5
-rw-r--r--libevmasm/ControlFlowGraph.h7
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp58
4 files changed, 70 insertions, 3 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 7f7e1b9c..2024b1e9 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -322,7 +322,8 @@ Assembly& Assembly::optimise(bool _enable, bool _isCreation, size_t _runs)
count++;
{
- ControlFlowGraph cfg(m_items);
+ // Control flow graph that resets knowledge at path joins.
+ ControlFlowGraph cfg(m_items, false);
AssemblyItems optimisedItems;
for (BasicBlock const& block: cfg.optimisedBlocks())
{
diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp
index fc2144c7..61b24e4b 100644
--- a/libevmasm/ControlFlowGraph.cpp
+++ b/libevmasm/ControlFlowGraph.cpp
@@ -250,7 +250,10 @@ void ControlFlowGraph::gatherKnowledge()
KnownStatePointer state = item.state;
if (block.startState)
{
- state->reduceToCommonKnowledge(*block.startState, !item.blocksSeen.count(item.blockId));
+ if (m_joinKnowledge)
+ state->reduceToCommonKnowledge(*block.startState, !item.blocksSeen.count(item.blockId));
+ else
+ state->reset();
if (*state == *block.startState)
continue;
}
diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h
index 4480ba49..a6a9df8e 100644
--- a/libevmasm/ControlFlowGraph.h
+++ b/libevmasm/ControlFlowGraph.h
@@ -94,7 +94,11 @@ class ControlFlowGraph
public:
/// Initializes the control flow graph.
/// @a _items has to persist across the usage of this class.
- ControlFlowGraph(AssemblyItems const& _items): m_items(_items) {}
+ /// @a _joinKnowledge if true, reduces state knowledge to common base at the join of two paths
+ explicit ControlFlowGraph(AssemblyItems const& _items, bool _joinKnowledge = true):
+ m_items(_items),
+ m_joinKnowledge(_joinKnowledge)
+ {}
/// @returns vector of basic blocks in the order they should be used in the final code.
/// Should be called only once.
BasicBlocks optimisedBlocks();
@@ -112,6 +116,7 @@ private:
unsigned m_lastUsedId = 0;
AssemblyItems const& m_items;
+ bool m_joinKnowledge;
std::map<BlockId, BasicBlock> m_blocks;
};
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index 67b161b9..2e4ed4b3 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -1177,6 +1177,64 @@ BOOST_AUTO_TEST_CASE(computing_constants)
) == optimizedBytecode.cend());
}
+BOOST_AUTO_TEST_CASE(inconsistency)
+{
+ // This is a test of a bug in the optimizer.
+ char const* sourceCode = R"(
+ contract Inconsistency {
+ struct Value {
+ uint badnum;
+ uint number;
+ }
+
+ struct Container {
+ uint[] valueIndices;
+ Value[] values;
+ }
+
+ Container[] containers;
+ uint[] valueIndices;
+ uint INDEX_ZERO = 0;
+ uint debug;
+
+ // Called with params: containerIndex=0, valueIndex=0
+ function levelIII(uint containerIndex, uint valueIndex) private {
+ Container container = containers[containerIndex];
+ Value value = container.values[valueIndex];
+ debug = container.valueIndices[value.number];
+ }
+ function levelII() private {
+ for (uint i = 0; i < valueIndices.length; i++) {
+ levelIII(INDEX_ZERO, valueIndices[i]);
+ }
+ }
+
+ function trigger() public returns (uint) {
+ containers.length++;
+ Container container = containers[0];
+
+ container.values.push(Value({
+ badnum: 9000,
+ number: 0
+ }));
+
+ container.valueIndices.length++;
+ valueIndices.length++;
+
+ levelII();
+ return debug;
+ }
+
+ function DoNotCallButDoNotDelete() public {
+ levelII();
+ levelIII(1, 2);
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("trigger()");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}