CFG returns vector of blocks instead of assembly items.

This commit is contained in:
chriseth 2015-05-05 17:45:58 +02:00
parent 85673ff00c
commit bebe76828a
3 changed files with 25 additions and 22 deletions

View File

@ -318,7 +318,10 @@ Assembly& Assembly::optimise(bool _enable)
copt << "Performing control flow analysis..."; copt << "Performing control flow analysis...";
{ {
ControlFlowGraph cfg(m_items); ControlFlowGraph cfg(m_items);
AssemblyItems optItems = cfg.optimisedItems(); AssemblyItems optItems;
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()) if (optItems.size() < m_items.size())
{ {
copt << "Old size: " << m_items.size() << ", new size: " << optItems.size(); copt << "Old size: " << m_items.size() << ", new size: " << optItems.size();

View File

@ -38,10 +38,10 @@ BlockId::BlockId(u256 const& _id): m_id(_id)
assertThrow( _id < initial().m_id, OptimizerException, "Tag number too large."); assertThrow( _id < initial().m_id, OptimizerException, "Tag number too large.");
} }
AssemblyItems ControlFlowGraph::optimisedItems() BasicBlocks ControlFlowGraph::optimisedBlocks()
{ {
if (m_items.empty()) if (m_items.empty())
return m_items; return BasicBlocks();
findLargestTag(); findLargestTag();
splitBlocks(); splitBlocks();
@ -216,17 +216,17 @@ void ControlFlowGraph::gatherKnowledge()
{ {
// @todo actually we know that memory is filled with zeros at the beginning, // @todo actually we know that memory is filled with zeros at the beginning,
// we could make use of that. // we could make use of that.
shared_ptr<KnownState> emptyState = make_shared<KnownState>(); KnownStatePointer emptyState = make_shared<KnownState>();
ExpressionClasses& expr = emptyState->expressionClasses(); ExpressionClasses& expr = emptyState->expressionClasses();
bool unknownJumpEncountered = false; bool unknownJumpEncountered = false;
vector<pair<BlockId, shared_ptr<KnownState>>> workQueue({make_pair(BlockId::initial(), emptyState->copy())}); vector<pair<BlockId, KnownStatePointer>> workQueue({make_pair(BlockId::initial(), emptyState->copy())});
while (!workQueue.empty()) while (!workQueue.empty())
{ {
//@todo we might have to do something like incrementing the sequence number for each JUMPDEST //@todo we might have to do something like incrementing the sequence number for each JUMPDEST
assertThrow(!!workQueue.back().first, OptimizerException, ""); assertThrow(!!workQueue.back().first, OptimizerException, "");
BasicBlock& block = m_blocks.at(workQueue.back().first); BasicBlock& block = m_blocks.at(workQueue.back().first);
shared_ptr<KnownState> state = workQueue.back().second; KnownStatePointer state = workQueue.back().second;
workQueue.pop_back(); workQueue.pop_back();
if (block.startState) if (block.startState)
{ {
@ -283,7 +283,7 @@ void ControlFlowGraph::gatherKnowledge()
} }
} }
AssemblyItems ControlFlowGraph::rebuildCode() BasicBlocks ControlFlowGraph::rebuildCode()
{ {
map<BlockId, unsigned> pushes; map<BlockId, unsigned> pushes;
for (auto& idAndBlock: m_blocks) for (auto& idAndBlock: m_blocks)
@ -294,7 +294,7 @@ AssemblyItems ControlFlowGraph::rebuildCode()
for (auto it: m_blocks) for (auto it: m_blocks)
blocksToAdd.insert(it.first); blocksToAdd.insert(it.first);
set<BlockId> blocksAdded; set<BlockId> blocksAdded;
AssemblyItems code; BasicBlocks blocks;
for ( for (
BlockId blockId = BlockId::initial(); BlockId blockId = BlockId::initial();
@ -311,22 +311,18 @@ AssemblyItems ControlFlowGraph::rebuildCode()
blocksToAdd.erase(blockId); blocksToAdd.erase(blockId);
blocksAdded.insert(blockId); blocksAdded.insert(blockId);
auto begin = m_items.begin() + block.begin; if (block.begin == block.end)
auto end = m_items.begin() + block.end;
if (begin == end)
continue; continue;
// If block starts with unused tag, skip it. // If block starts with unused tag, skip it.
if (previousHandedOver && !pushes[blockId] && begin->type() == Tag) if (previousHandedOver && !pushes[blockId] && m_items[block.begin].type() == Tag)
{
++begin;
++block.begin; ++block.begin;
} if (block.begin < block.end)
blocks.push_back(block);
previousHandedOver = (block.endType == BasicBlock::EndType::HANDOVER); previousHandedOver = (block.endType == BasicBlock::EndType::HANDOVER);
copy(begin, end, back_inserter(code));
} }
} }
return code; return blocks;
} }
BlockId ControlFlowGraph::expressionClassToBlockId( BlockId ControlFlowGraph::expressionClassToBlockId(

View File

@ -35,6 +35,7 @@ namespace eth
{ {
class KnownState; class KnownState;
using KnownStatePointer = std::shared_ptr<KnownState>;
/** /**
* Identifier for a block, coincides with the tag number of an AssemblyItem but adds a special * Identifier for a block, coincides with the tag number of an AssemblyItem but adds a special
@ -81,19 +82,22 @@ struct BasicBlock
/// Knowledge about the state when this block is entered. Intersection of all possible ways /// Knowledge about the state when this block is entered. Intersection of all possible ways
/// to enter this block. /// to enter this block.
std::shared_ptr<KnownState> startState; KnownStatePointer startState;
/// Knowledge about the state at the end of this block. /// Knowledge about the state at the end of this block.
std::shared_ptr<KnownState> endState; KnownStatePointer endState;
}; };
using BasicBlocks = std::vector<BasicBlock>;
class ControlFlowGraph class ControlFlowGraph
{ {
public: public:
/// Initializes the control flow graph. /// Initializes the control flow graph.
/// @a _items has to persist across the usage of this class. /// @a _items has to persist across the usage of this class.
ControlFlowGraph(AssemblyItems const& _items): m_items(_items) {} ControlFlowGraph(AssemblyItems const& _items): m_items(_items) {}
/// @returns the collection of optimised items, should be called only once. /// @returns vector of basic blocks in the order they should be used in the final code.
AssemblyItems optimisedItems(); /// Should be called only once.
BasicBlocks optimisedBlocks();
private: private:
void findLargestTag(); void findLargestTag();
@ -102,7 +106,7 @@ private:
void removeUnusedBlocks(); void removeUnusedBlocks();
void gatherKnowledge(); void gatherKnowledge();
void setPrevLinks(); void setPrevLinks();
AssemblyItems rebuildCode(); BasicBlocks rebuildCode();
/// @returns the corresponding BlockId if _id is a pushed jump tag, /// @returns the corresponding BlockId if _id is a pushed jump tag,
/// and an invalid BlockId otherwise. /// and an invalid BlockId otherwise.