Commit 2e5432bf authored by Marius Wachtler's avatar Marius Wachtler

CFGBlock: remove successors vector

parent 93df6ef7
...@@ -83,8 +83,7 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init ...@@ -83,8 +83,7 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
analyzer.processBB(ending, block); analyzer.processBB(ending, block);
for (int i = 0; i < block->successors.size(); i++) { for (CFGBlock* next_block : block->successors()) {
CFGBlock* next_block = block->successors[i];
bool changed = false; bool changed = false;
bool initial = false; bool initial = false;
if (starting_states.count(next_block) == 0) { if (starting_states.count(next_block) == 0) {
......
...@@ -125,7 +125,7 @@ bool LivenessAnalysis::isLiveAtEnd(int vreg, CFGBlock* block) { ...@@ -125,7 +125,7 @@ bool LivenessAnalysis::isLiveAtEnd(int vreg, CFGBlock* block) {
return false; return false;
#endif #endif
if (block->successors.size() == 0) if (block->successors().size() == 0)
return false; return false;
if (!result_cache[vreg].size()) { if (!result_cache[vreg].size()) {
...@@ -376,10 +376,11 @@ PhiAnalysis::PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_m ...@@ -376,10 +376,11 @@ PhiAnalysis::PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_m
} }
const VRegSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block) { const VRegSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block) {
if (block->successors.size() == 0) auto successors = block->successors();
if (successors.size() == 0)
return empty_set; return empty_set;
assert(required_phis.count(block->successors[0])); assert(required_phis.count(successors[0]));
return required_phis.find(block->successors[0])->second; return required_phis.find(successors[0])->second;
} }
const VRegSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) { const VRegSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) {
...@@ -394,19 +395,20 @@ bool PhiAnalysis::isRequired(int vreg, CFGBlock* block) { ...@@ -394,19 +395,20 @@ bool PhiAnalysis::isRequired(int vreg, CFGBlock* block) {
} }
bool PhiAnalysis::isRequiredAfter(int vreg, CFGBlock* block) { bool PhiAnalysis::isRequiredAfter(int vreg, CFGBlock* block) {
auto successors = block->successors();
assert(vreg >= 0); assert(vreg >= 0);
// If there are multiple successors, then none of them are allowed // If there are multiple successors, then none of them are allowed
// to require any phi nodes // to require any phi nodes
if (block->successors.size() != 1) if (successors.size() != 1)
return false; return false;
// Fall back to the other method: // Fall back to the other method:
return isRequired(vreg, block->successors[0]); return isRequired(vreg, successors[0]);
} }
bool PhiAnalysis::isPotentiallyUndefinedAfter(int vreg, CFGBlock* block) { bool PhiAnalysis::isPotentiallyUndefinedAfter(int vreg, CFGBlock* block) {
assert(vreg >= 0); assert(vreg >= 0);
for (auto b : block->successors) { for (auto b : block->successors()) {
if (isPotentiallyUndefinedAt(vreg, b)) if (isPotentiallyUndefinedAt(vreg, b))
return true; return true;
} }
......
...@@ -51,8 +51,9 @@ ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(int vreg, CFGBlock* ...@@ -51,8 +51,9 @@ ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(int vreg, CFGBlock*
} }
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(int vreg, CFGBlock* block) { ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(int vreg, CFGBlock* block) {
assert(block->successors.size() > 0); auto successors = block->successors();
return getTypeAtBlockStart(vreg, block->successors[0]); assert(successors.size() > 0);
return getTypeAtBlockStart(vreg, successors[0]);
} }
...@@ -571,8 +572,9 @@ private: ...@@ -571,8 +572,9 @@ private:
public: public:
ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) override { ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) override {
assert(block->successors.size() > 0); auto successors = block->successors();
return getTypeAtBlockStart(vreg, block->successors[0]); assert(successors.size() > 0);
return getTypeAtBlockStart(vreg, successors[0]);
} }
ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) override { ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) override {
assert(starting_types.count(block)); assert(starting_types.count(block));
...@@ -686,8 +688,7 @@ public: ...@@ -686,8 +688,7 @@ public:
} }
} }
for (int i = 0; i < block->successors.size(); i++) { for (CFGBlock* next_block : block->successors()) {
CFGBlock* next_block = block->successors[i];
bool first = (starting_types.count(next_block) == 0); bool first = (starting_types.count(next_block) == 0);
if (first) if (first)
starting_types.insert(std::make_pair(next_block, TypeMap(num_vregs))); starting_types.insert(std::make_pair(next_block, TypeMap(num_vregs)));
......
...@@ -246,8 +246,7 @@ static std::vector<std::pair<CFGBlock*, CFGBlock*>> computeBlockTraversalOrder(c ...@@ -246,8 +246,7 @@ static std::vector<std::pair<CFGBlock*, CFGBlock*>> computeBlockTraversalOrder(c
while (idx < rtn.size()) { while (idx < rtn.size()) {
CFGBlock* cur = rtn[idx].first; CFGBlock* cur = rtn[idx].first;
for (int i = 0; i < cur->successors.size(); i++) { for (CFGBlock* b : cur->successors()) {
CFGBlock* b = cur->successors[i];
assert(blocks.count(b)); assert(blocks.count(b));
if (in_queue.count(b)) if (in_queue.count(b))
continue; continue;
...@@ -268,7 +267,7 @@ static std::vector<std::pair<CFGBlock*, CFGBlock*>> computeBlockTraversalOrder(c ...@@ -268,7 +267,7 @@ static std::vector<std::pair<CFGBlock*, CFGBlock*>> computeBlockTraversalOrder(c
continue; continue;
// Avoid picking any blocks where we can't add an epilogue to the predecessors // Avoid picking any blocks where we can't add an epilogue to the predecessors
if (b->predecessors.size() == 1 && b->predecessors[0]->successors.size() > 1) if (b->predecessors.size() == 1 && b->predecessors[0]->successors().size() > 1)
continue; continue;
if (best == NULL || b->idx < best->idx) if (best == NULL || b->idx < best->idx)
...@@ -972,8 +971,7 @@ static void computeBlockSetClosure(BlockSet& blocks) { ...@@ -972,8 +971,7 @@ static void computeBlockSetClosure(BlockSet& blocks) {
continue; continue;
expanded.insert(b); expanded.insert(b);
for (int i = 0; i < b->successors.size(); i++) { for (CFGBlock* b2 : b->successors()) {
CFGBlock* b2 = b->successors[i];
blocks.insert(b2); blocks.insert(b2);
q.push_back(b2); q.push_back(b2);
} }
......
...@@ -2604,7 +2604,7 @@ private: ...@@ -2604,7 +2604,7 @@ private:
ConcreteCompilerVariable* v = val->makeConverted(emitter, phi_type); ConcreteCompilerVariable* v = val->makeConverted(emitter, phi_type);
symbol_table[vreg] = v; symbol_table[vreg] = v;
} else { } else {
if (myblock->successors.size()) { if (myblock->successors().size()) {
// TODO getTypeAtBlockEnd will automatically convert up to the concrete type, which we don't // TODO getTypeAtBlockEnd will automatically convert up to the concrete type, which we don't
// want // want
// here, but this is just for debugging so I guess let it happen for now: // here, but this is just for debugging so I guess let it happen for now:
...@@ -2730,20 +2730,21 @@ public: ...@@ -2730,20 +2730,21 @@ public:
ASSERT(p.second->getType()->isUsable(), "%d", p.first); ASSERT(p.second->getType()->isUsable(), "%d", p.first);
} }
if (myblock->successors.size() == 0) { auto successors = myblock->successors();
if (successors.size() == 0) {
st->clear(); st->clear();
symbol_table.clear(); symbol_table.clear();
return EndingState(st, phi_st, def_vars, curblock, outgoing_exc_state); return EndingState(st, phi_st, def_vars, curblock, outgoing_exc_state);
} else if (myblock->successors.size() > 1) { } else if (successors.size() > 1) {
// Since there are no critical edges, all successors come directly from this node, // Since there are no critical edges, all successors come directly from this node,
// so there won't be any required phis. // so there won't be any required phis.
return EndingState(st, phi_st, def_vars, curblock, outgoing_exc_state); return EndingState(st, phi_st, def_vars, curblock, outgoing_exc_state);
} }
assert(myblock->successors.size() == 1); // other cases should have been handled assert(successors.size() == 1); // other cases should have been handled
// In theory this case shouldn't be necessary: // In theory this case shouldn't be necessary:
if (myblock->successors[0]->predecessors.size() == 1) { if (successors[0]->predecessors.size() == 1) {
// If the next block has a single predecessor, don't have to // If the next block has a single predecessor, don't have to
// emit any phis. // emit any phis.
// Should probably not emit no-op jumps like this though. // Should probably not emit no-op jumps like this though.
......
...@@ -231,25 +231,33 @@ static int getLastLineno(llvm::ArrayRef<AST_stmt*> body, int default_lineno) { ...@@ -231,25 +231,33 @@ static int getLastLineno(llvm::ArrayRef<AST_stmt*> body, int default_lineno) {
return getLastLinenoSub(body.back()); return getLastLinenoSub(body.back());
} }
void CFGBlock::connectTo(CFGBlock* successor, bool allow_backedge) { llvm::SmallVector<CFGBlock*, 2> CFGBlock::successors() const {
assert(successors.size() <= 1); llvm::SmallVector<CFGBlock*, 2> successors;
auto* last = getLastStmt();
if (last->type() == BST_TYPE::Jump) {
successors.push_back(bst_cast<BST_Jump>(last)->target);
} else if (last->type() == BST_TYPE::Branch) {
assert(bst_cast<BST_Branch>(last)->iftrue != bst_cast<BST_Branch>(last)->iffalse);
successors.push_back(bst_cast<BST_Branch>(last)->iftrue);
successors.push_back(bst_cast<BST_Branch>(last)->iffalse);
} else if (last->is_invoke()) {
successors.push_back(last->get_normal_block());
if (last->get_exc_block() != last->get_normal_block())
successors.push_back(last->get_exc_block());
}
return successors;
}
void CFGBlock::connectTo(CFGBlock* successor, bool allow_backedge) {
if (!allow_backedge) { if (!allow_backedge) {
assert(this->idx >= 0); assert(this->idx >= 0);
ASSERT(successor->idx == -1 || successor->idx > this->idx, "edge from %d (%s) to %d (%s)", this->idx, ASSERT(successor->idx == -1 || successor->idx > this->idx, "edge from %d (%s) to %d (%s)", this->idx,
this->info, successor->idx, successor->info); this->info, successor->idx, successor->info);
} }
// assert(successors.count(successor) == 0);
// assert(successor->predecessors.count(this) == 0);
successors.push_back(successor);
successor->predecessors.push_back(this); successor->predecessors.push_back(this);
} }
void CFGBlock::unconnectFrom(CFGBlock* successor) { void CFGBlock::unconnectFrom(CFGBlock* successor) {
// assert(successors.count(successor));
// assert(successor->predecessors.count(this));
successors.erase(std::remove(successors.begin(), successors.end(), successor), successors.end());
successor->predecessors.erase(std::remove(successor->predecessors.begin(), successor->predecessors.end(), this), successor->predecessors.erase(std::remove(successor->predecessors.begin(), successor->predecessors.end(), this),
successor->predecessors.end()); successor->predecessors.end());
} }
...@@ -264,8 +272,8 @@ void CFGBlock::print(const CodeConstants& code_constants, llvm::raw_ostream& str ...@@ -264,8 +272,8 @@ void CFGBlock::print(const CodeConstants& code_constants, llvm::raw_ostream& str
stream << " " << predecessors[j]->idx; stream << " " << predecessors[j]->idx;
} }
stream << " Successors:"; stream << " Successors:";
for (int j = 0; j < successors.size(); j++) { for (CFGBlock* successor : successors()) {
stream << " " << successors[j]->idx; stream << " " << successor->idx;
} }
stream << "\n"; stream << "\n";
...@@ -3225,8 +3233,9 @@ static int pruneUnnecessaryBlocks(CFG* rtn) { ...@@ -3225,8 +3233,9 @@ static int pruneUnnecessaryBlocks(CFG* rtn) {
for (auto it = rtn->blocks.begin(); it != rtn->blocks.end(); ++it) { for (auto it = rtn->blocks.begin(); it != rtn->blocks.end(); ++it) {
CFGBlock* b = *it; CFGBlock* b = *it;
if (b->successors.size() == 1) { auto b_successors = b->successors();
CFGBlock* b2 = b->successors[0]; if (b_successors.size() == 1) {
CFGBlock* b2 = b_successors[0];
if (b2->predecessors.size() != 1) if (b2->predecessors.size() != 1)
continue; continue;
...@@ -3246,7 +3255,7 @@ static int pruneUnnecessaryBlocks(CFG* rtn) { ...@@ -3246,7 +3255,7 @@ static int pruneUnnecessaryBlocks(CFG* rtn) {
b->unconnectFrom(b2); b->unconnectFrom(b2);
for (CFGBlock* b3 : b2->successors) { for (CFGBlock* b3 : b2->successors()) {
b->connectTo(b3, true); b->connectTo(b3, true);
b2->unconnectFrom(b3); b2->unconnectFrom(b3);
} }
...@@ -3394,13 +3403,13 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body, ...@@ -3394,13 +3403,13 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body,
for (CFGBlock* b2 : b->predecessors) { for (CFGBlock* b2 : b->predecessors) {
ASSERT(b2->idx != -1 && b->isPlaced(), "Forgot to place a block!"); ASSERT(b2->idx != -1 && b->isPlaced(), "Forgot to place a block!");
} }
for (CFGBlock* b2 : b->successors) { for (CFGBlock* b2 : b->successors()) {
ASSERT(b2->idx != -1 && b->isPlaced(), "Forgot to place a block!"); ASSERT(b2->idx != -1 && b->isPlaced(), "Forgot to place a block!");
} }
ASSERT(b->body() != NULL, "%d", b->idx); ASSERT(b->body() != NULL, "%d", b->idx);
ASSERT(b->successors.size() <= 2, "%d has too many successors!", b->idx); ASSERT(b->successors().size() <= 2, "%d has too many successors!", b->idx);
if (b->successors.size() == 0) { if (b->successors().size() == 0) {
BST_stmt* terminator = b->getLastStmt(); BST_stmt* terminator = b->getLastStmt();
assert(terminator->type() == BST_TYPE::Return || terminator->type() == BST_TYPE::Raise assert(terminator->type() == BST_TYPE::Return || terminator->type() == BST_TYPE::Raise
|| terminator->type() == BST_TYPE::Assert); || terminator->type() == BST_TYPE::Assert);
...@@ -3420,11 +3429,11 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body, ...@@ -3420,11 +3429,11 @@ static std::pair<CFG*, CodeConstants> computeCFG(llvm::ArrayRef<AST_stmt*> body,
// the cfg-computing code directly avoids making critical edges. // the cfg-computing code directly avoids making critical edges.
// Either way, double check to make sure that we don't have any: // Either way, double check to make sure that we don't have any:
for (int i = 0; i < rtn->blocks.size(); i++) { for (int i = 0; i < rtn->blocks.size(); i++) {
if (rtn->blocks[i]->successors.size() >= 2) { auto successors = rtn->blocks[i]->successors();
for (int j = 0; j < rtn->blocks[i]->successors.size(); j++) { if (successors.size() >= 2) {
for (CFGBlock* successor : successors) {
// It's ok to have zero predecessors if you are the entry block // It's ok to have zero predecessors if you are the entry block
ASSERT(rtn->blocks[i]->successors[j]->predecessors.size() < 2, "Critical edge from %d to %d!", i, ASSERT(successor->predecessors.size() < 2, "Critical edge from %d to %d!", i, successor->idx);
rtn->blocks[i]->successors[j]->idx);
} }
} }
} }
......
...@@ -75,9 +75,9 @@ public: ...@@ -75,9 +75,9 @@ public:
// contains the address of the entry function // contains the address of the entry function
std::pair<CFGBlock*, Box*>(*entry_code)(void* interpeter, CFGBlock* block, Box** vregs); std::pair<CFGBlock*, Box*>(*entry_code)(void* interpeter, CFGBlock* block, Box** vregs);
llvm::SmallVector<CFGBlock*, 2> predecessors, successors; llvm::TinyPtrVector<CFGBlock*> predecessors;
int idx; // index in the CFG
const char* info; const char* info;
int idx; // index in the CFG
int offset_of_first_stmt; // offset of this block into the bytecode array in bytes int offset_of_first_stmt; // offset of this block into the bytecode array in bytes
#ifndef NDEBUG #ifndef NDEBUG
...@@ -85,8 +85,11 @@ public: ...@@ -85,8 +85,11 @@ public:
bool allowed_to_add_stuff = false; bool allowed_to_add_stuff = false;
#endif #endif
// returns the successors by looking at the terminator (which requires iterating over all instructions in the block)
llvm::SmallVector<CFGBlock*, 2> successors() const;
CFGBlock(CFG* cfg, int idx, const char* info = NULL) CFGBlock(CFG* cfg, int idx, const char* info = NULL)
: cfg(cfg), code(NULL), entry_code(NULL), idx(idx), info(info), offset_of_first_stmt(-1) {} : cfg(cfg), code(NULL), entry_code(NULL), info(info), idx(idx), offset_of_first_stmt(-1) {}
BST_stmt* body() { BST_stmt* body() {
auto it = begin(); auto it = begin();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment