aboutsummaryrefslogtreecommitdiffstats
path: root/Assembly.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-05-07 01:15:14 +0800
committerchriseth <c@ethdev.com>2015-05-11 18:56:40 +0800
commit9d3f0de31bb82217a5fc5f2daf933d21b18774a0 (patch)
tree26d587fe364a01e76636add94e2adc4eba831e11 /Assembly.cpp
parent6cc71a188f3c59b32ac1f131ee74c703f1f81a70 (diff)
downloaddexon-solidity-9d3f0de31bb82217a5fc5f2daf933d21b18774a0.tar.gz
dexon-solidity-9d3f0de31bb82217a5fc5f2daf933d21b18774a0.tar.zst
dexon-solidity-9d3f0de31bb82217a5fc5f2daf933d21b18774a0.zip
Reuse state during common subexpression elimination.
Diffstat (limited to 'Assembly.cpp')
-rw-r--r--Assembly.cpp80
1 files changed, 36 insertions, 44 deletions
diff --git a/Assembly.cpp b/Assembly.cpp
index 9530ded4..abcd4451 100644
--- a/Assembly.cpp
+++ b/Assembly.cpp
@@ -311,54 +311,45 @@ Assembly& Assembly::optimise(bool _enable)
copt << toString(*this);
count = 0;
- //@todo CFG interface should be a generator, that returns an item and a pointer to a
- // knownstate, which has to replace the current state if it is not null.
- // Feed these items to the CSE, but also store them and replace the stored version
- // if the items generated by the CSE are shorter. (or even use less gas?)
- copt << "Performing control flow analysis...";
+ copt << "Performing optimisation...";
{
ControlFlowGraph cfg(m_items);
- AssemblyItems optItems;
+ AssemblyItems optimisedItems;
for (BasicBlock const& block: cfg.optimisedBlocks())
- copy(m_items.begin() + block.begin, m_items.begin() + block.end,
- back_inserter(optItems));
- if (optItems.size() < m_items.size())
{
- copt << "Old size: " << m_items.size() << ", new size: " << optItems.size();
- m_items = move(optItems);
- count++;
- }
- }
-
- copt << "Performing common subexpression elimination...";
- for (auto iter = m_items.begin(); iter != m_items.end();)
- {
- //@todo use only a single state / expression classes instance.
- KnownState state(make_shared<ExpressionClasses>());
- CommonSubexpressionEliminator eliminator(state);
- auto orig = iter;
- iter = eliminator.feedItems(iter, m_items.end());
- AssemblyItems optItems;
- bool shouldReplace = false;
- try
- {
- optItems = eliminator.getOptimizedItems();
- shouldReplace = (optItems.size() < size_t(iter - orig));
- }
- catch (StackTooDeepException const&)
- {
- // This might happen if the opcode reconstruction is not as efficient
- // as the hand-crafted code.
- }
-
- if (shouldReplace)
- {
- copt << "Old size: " << (iter - orig) << ", new size: " << optItems.size();
- count++;
- for (auto moveIter = optItems.begin(); moveIter != optItems.end(); ++orig, ++moveIter)
- *orig = move(*moveIter);
- iter = m_items.erase(orig, iter);
+ assertThrow(!!block.startState, OptimizerException, "");
+ CommonSubexpressionEliminator eliminator(*block.startState);
+ auto iter = m_items.begin() + block.begin;
+ auto const end = m_items.begin() + block.end;
+ while (iter < end)
+ {
+ auto orig = iter;
+ iter = eliminator.feedItems(iter, end);
+ bool shouldReplace = false;
+ AssemblyItems optimisedChunk;
+ try
+ {
+ optimisedChunk = eliminator.getOptimizedItems();
+ shouldReplace = (optimisedChunk.size() < size_t(iter - orig));
+ }
+ catch (StackTooDeepException const&)
+ {
+ // This might happen if the opcode reconstruction is not as efficient
+ // as the hand-crafted code.
+ }
+
+ if (shouldReplace)
+ {
+ copt << "Old size: " << (iter - orig) << ", new size: " << optimisedChunk.size();
+ count++;
+ optimisedItems += optimisedChunk;
+ }
+ else
+ copy(orig, iter, back_inserter(optimisedItems));
+ }
}
+ if (optimisedItems.size() < m_items.size())
+ m_items = move(optimisedItems);
}
}
@@ -461,7 +452,8 @@ bytes Assembly::assemble() const
for (auto const& i: tagRef)
{
bytesRef r(ret.data() + i.first, bytesPerTag);
- toBigEndian(tagPos[i.second], r);
+ //@todo in the failure case, we could use the position of the invalid jumpdest
+ toBigEndian(i.second < tagPos.size() ? tagPos[i.second] : (1 << (8 * bytesPerTag)) - 1, r);
}
if (!m_data.empty())