bool DivergenceAnalysis::_hasTrivialPathToExit( const DataflowGraph::iterator &block) const { // We can ignore divergent threads that immediately exit unsigned int exitingPaths = 0; const Analysis* dfgAnalysis = getAnalysis("DataflowGraphAnalysis"); assert(dfgAnalysis != 0); const DataflowGraph &dfg = static_cast<const DataflowGraph&>(*dfgAnalysis); auto exit = --dfg.end(); for (auto successor = block->successors().begin(); successor != block->successors().end(); ++successor) { auto path = *successor; while (true) { if (path == exit) { ++exitingPaths; break; } if (path->successors().size() != 1) { break; } if (!path->instructions().empty()) { if (path->instructions().size() == 1) { const ir::PTXInstruction &ptxI = *(static_cast<ir::PTXInstruction *> ( path->instructions().back().i)); if (ptxI.isExit()) { ++exitingPaths; } } break; } path = *path->successors().begin(); } } if (block->successors().size() - exitingPaths < 2) { return true; } return false; }
/* Assuming the file exists and is an acyclic graph, print the vertices in a topological order * Use the algorithm that finds no-predecessor vertices and deletes their successor edges. * ALERT: modifies the graph by deleting edges. * * Solves topocycleExercise.c */ void toposort2(GraphInfo gi) { Graph g = gi->graph; int numV = numVerts(g); short done[numV]; // 1 if vertex already printed, otherwise 0 for (int i = 0; i < numV; i++) done[i] = 0; for (int numPrinted = 0; numPrinted < numV; numPrinted++) { /* set noPred to a vertex with no predecessors and not already done */ int noPred; int* ps; // predecessor list for (int v = 0; v < numV; v++) { if (!done[v]) { ps = predecessors(g, v); if (ps[0] == -1 ) { // list is empty? noPred = v; break; } } } /* print noPred and mark as done */ printf("%s ", gi->vertnames[noPred]); done[noPred] = 1; /* get successors of noPred and delete them */ int* snoPred = successors(gi->graph, noPred); for (int i = 0; snoPred[i] != -1; i++) delEdge(gi->graph, noPred, snoPred[i]); } /* cleanup */ printf("\n"); }
// Computes the immediate post-dominator of the current block. Assumes that all // of its successors have already computed their post-dominators. This is // achieved visiting the nodes in reverse topological order. void BasicBlock::computePostDominator() { BasicBlock *Candidate = nullptr; // Walk forward from each successor to find the common post-dominator node. for (auto &Succ : successors()) { // Skip edges that have been pruned. if (Succ.get() == nullptr) continue; // Skip back-edges if (Succ->PostBlockID >= PostBlockID) continue; // If we don't yet have a candidate for post-dominator yet, take this one. if (Candidate == nullptr) { Candidate = Succ.get(); continue; } // Walk the alternate and current candidate back to find a common ancestor. auto *Alternate = Succ.get(); while (Alternate != Candidate) { if (!Alternate || !Candidate) { // TODO: warn on invalid CFG. Candidate = nullptr; break; } if (Candidate->PostBlockID > Alternate->PostBlockID) Candidate = Candidate->PostDominatorNode.Parent; else Alternate = Alternate->PostDominatorNode.Parent; } } PostDominatorNode.Parent = Candidate; PostDominatorNode.SizeOfSubTree = 1; }
void BasicBlock::deepDump(const Procedure& proc, PrintStream& out) const { out.print("BB", *this, ": ; frequency = ", m_frequency, "\n"); if (predecessors().size()) out.print(" Predecessors: ", pointerListDump(predecessors()), "\n"); for (Value* value : *this) out.print(" ", B3::deepDump(proc, value), "\n"); if (!successors().isEmpty()) { out.print(" Successors: "); if (size()) last()->dumpSuccessors(this, out); else out.print(listDump(successors())); out.print("\n"); } }
// dump the view in json format // the structure is: // {'nodes': // [ // {'path': '<path value>', // 'meta': // { 'version': '<version value>', // 'hash': '<hash value>', // 'name': '<name value>' // }, // 'nbChildren': '<nbChildren value>' // }, // ... // ], // 'links': // [ // {'source': '<source value>', // 'target': '<target value>' // }, // ... // ] // } void BlobMapView::json(std::string &to) const { std::stringstream oss_nodes; std::stringstream oss_links; for (Graph::vertex_iterator iter = graph_.begin(), end = graph_.end(); iter != end; ++iter) { boost::filesystem::path const &filename = graph_.key(*iter); Hash const &hash = graph_.hash(filename); MetadataInfo const &minfo = (*metadata_)[hash]; Graph::successors_type succs; successors(succs, filename); //TODO: .string() should be .native() but on windows we'd get a std::wstring() oss_nodes << "{\"path\":\"" << filename.string() << "\", " "\"meta\": {\"version\":\"" << minfo.version() << "\", " "\"hash\":\"" << hash.str() << "\", " "\"name\":\"" << minfo.name() << "\"" "}," "\"nbChildren\":" << succs.size() << "},"; BOOST_FOREACH(boost::filesystem::path const & succ, succs) { oss_links << "{\"source\":\"" << filename.string() << "\", " "\"target\":" << succ << "" "},"; } }
void AAStar::findPath(std::vector<ANode*>& path) { float c; ANode *x, *y; init(); printf("Pathfinding..."); open.push(start); start->open = true; visited.push_back(start); while (!open.empty()) { x = open.top(); open.pop(); x->open = false; if (x == goal) { tracePath(path); printf("[done]\n"); return; } x->closed = true; successors(x, succs); while (!succs.empty()) { y = succs.front(); succs.pop(); c = x->g + (y->w * heuristic(x, y)); if (y->open && c < y->g) y->open = false; /* Only happens with an admissable heuristic */ if (y->closed && c < y->g) y->closed = false; if (!y->open && !y->closed) { y->g = (unsigned int) c; y->parent = x; y->h = (y->w * heuristic(y, goal)); open.push(y); y->open = true; visited.push_back(y); history.push_back(y); history.push_back(x); } } } printf("[failed]\n"); }
void successors(bdd_manager *bddm, bdd_ptr p) { if (bdd_is_leaf(bddm, p)) { int i; int s = bdd_leaf_value(bddm, p); /* current_state is a predecessor of s */ for (i = 0; i < predused[s]; i++) /* already there? */ if (preds[s][i] == current_state) return; if (predalloc[s] == predused[s]) { /* need to reallocate? */ predalloc[s] = predalloc[s]*2+8; preds[s] = (int *) mem_resize(preds[s], sizeof(int) * predalloc[s]); } preds[s][predused[s]++] = current_state; } else { successors(bddm, bdd_else(bddm, p)); successors(bddm, bdd_then(bddm, p)); } }
bool AAStar::findPath(std::list<ANode*>* path) { float g; ANode *x, *y; init(); start->open = true; start->g = 0.0f; start->h = heuristic(start,goal); open.push(start); while (!open.empty()) { x = open.top(); open.pop(); if (x == goal) { if (path) tracePath(x, *path); return true; } x->open = false; x->closed = true; successors(x, succs); while (!succs.empty()) { y = succs.front(); succs.pop(); if (y->closed) continue; g = x->g + y->w*heuristic(x,y); if (y->open && g < y->g) y->open = false; if (!y->open) { y->g = g; y->parent = x; y->h = heuristic(y, goal); y->open = true; open.push(y); } visited++; } } return false; }
bool recurWord(string s, pointT position, Grid<char> &board, Vector<pointT> &deltas, Vector<pointT> &path) { if ( s.length() == 0 ) return true; Vector<pointT> next = successors(position, board, deltas); for (int i = 0; i < next.size(); i++) { pointT nextPt = next[i]; if ( board.getAt(nextPt.row, nextPt.col) == s[0] ){ Grid<char> copy = board; copy.setAt(nextPt.row, nextPt.col, 'f'); path.add(nextPt); if ( recurWord(s.substr(1,s.length()-1), nextPt, copy, deltas, path) ) return true; } } return false; }
int main() { GraphInfo gi; gi = readGraph("series.txt", LIST); writeGraph(gi); gi = readGraph("statesContig.txt", LIST); writeGraph(gi); printf("Successors of NC: "); int NCnum = vertexNum(gi, "NC"); int* vsucc = successors(gi->graph, NCnum); for (int i = 0; vsucc[i] != -1; i++) printf(" %s ", gi->vertnames[i]); printf("\n"); return 0; }
bool findWord(string sofar, pointT position, Grid<char> &board, Lexicon &lex, Vector<pointT> deltas, Set<string> &acc) { if( validBoggle(sofar, lex) ) { acc.add(sofar); return true; } Vector<pointT> next = successors(position, board, deltas); for (int i = 0; i < next.size(); i++) { pointT nextPt = next[i]; char ch = board.getAt(nextPt.row, nextPt.col); string prefix = sofar + ch; if ( lex.containsPrefix( prefix ) ) { Grid<char> copy = board; copy.setAt(nextPt.row, nextPt.col, 'f'); if ( findWord(prefix, nextPt, copy, lex, deltas, acc) ) return true; } } return false; }
// Sorts blocks in topological order, by following successors. // If post-dominators have been computed, it takes that into account. // Each block will be written into the Blocks array in order, and its BlockID // will be set to the index in the array. Sorting should start from the entry // block, and ID should be the total number of blocks. int BasicBlock::topologicalSort(BasicBlock** Blocks, int ID) { if (BlockID != InvalidBlockID) return ID; BlockID = 0; // mark as being visited // First sort the post-dominator, if it exists. // This gives us a topological order where post-dominators always come last. if (PostDominatorNode.Parent) ID = PostDominatorNode.Parent->topologicalSort(Blocks, ID); for (auto &B : successors()) { if (B.get()) ID = B->topologicalSort(Blocks, ID); } // set ID and update block array in place. // We may lose pointers to unreachable blocks. assert(ID > 0); BlockID = --ID; Blocks[BlockID] = this; return ID; }
void dfaPrefixClose(DFA *a) { unsigned i; int *queue = (int *) mem_alloc(sizeof(int) * a->ns); int queueused = 0, next = 0; predalloc = (int *) mem_alloc(sizeof(int) * a->ns); predused = (int *) mem_alloc(sizeof(int) * a->ns); preds = (int **) mem_alloc(sizeof(int *) * a->ns); for (i = 0; i < a->ns; i++) { predalloc[i] = predused[i] = 0; preds[i] = 0; } /* find predecessor sets and initialize queue with final states */ for (i = 0; i < a->ns; i++) { current_state = i; successors(a->bddm, a->q[i]); if (a->f[i] == 1) queue[queueused++] = i; } /* color */ while (next < queueused) { for (i = 0; i < predused[queue[next]]; i++) if (a->f[preds[queue[next]][i]] != 1) { a->f[preds[queue[next]][i]] = 1; queue[queueused++] = preds[queue[next]][i]; } next++; } for (i = 0; i < a->ns; i++) mem_free(preds[i]); mem_free(preds); mem_free(predused); mem_free(predalloc); mem_free(queue); }
void PFLTraceBuilder::handle_two_succ_bb(PFLTraceBuilder::bb_t *bb) { assert(bb != NULL); //std::cout << "TRACE: Esamino il BB: " << bb->getId() << std::endl; bb_t* next = bb->getProperty< bb_t* >(jit::TraceBuilder<PFLCFG>::next_prop_name); std::list< PFLCFG::GraphNode* > successors(bb->getSuccessors()); MIRONode* insn = bb->getCode().back(); //std::cout << "Ultima istruzione: "; //insn->printNode(std::cout, true); //std::cout << std::endl; if( ((StmtMIRONode*)insn)->Kind != STMT_JUMP && ((StmtMIRONode*)insn)->Kind != STMT_JUMP_FIELD) return; //uint16_t jt = LBL_OPERAND(insn->Operands[0].Op)->Label; uint16_t jt = ((JumpMIRONode*)insn)->getTrueTarget(); successors.remove(this->cfg.getBBById(jt)->getNode()); uint16_t jf = successors.front()->NodeInfo->getId(); if(!next || (next->getId() != jt && next->getId() != jf)) { //x86_Asm_JMP_Label(bb->getCode(), jf); JumpMIRONode *new_j = new JumpMIRONode(bb->getId(), cfg.getBBById(jf)->getStartLabel()); //bb->getCode().pop_back(); new_j->setOpcode(JUMPW); bb->getCode().push_back(new_j); return; } MIRONode *jump_node = insn->getKid(0); if (jump_node->getOpcode() == JUMPW) return; if (jt == next->getId()) { //std::cout << "Vecchio nodo: " << std::endl; //insn->printNode(std::cout,false); //std::cout << std::endl; ((JumpMIRONode*)insn)->swapTargets(); //FIXME //assert(1 == 0 && "Not implemented yet"); switch(jump_node->getOpcode()) { case JCMPEQ: jump_node->setOpcode(JCMPNEQ); break; case JCMPNEQ: jump_node->setOpcode(JCMPEQ); break; case JCMPG: jump_node->setOpcode(JCMPLE); break; case JCMPGE: jump_node->setOpcode(JCMPL); break; case JCMPL: jump_node->setOpcode(JCMPGE); break; case JCMPLE: jump_node->setOpcode(JCMPG); break; case JCMPG_S: jump_node->setOpcode(JCMPLE_S); break; case JCMPGE_S: jump_node->setOpcode(JCMPL_S); break; case JCMPL_S: jump_node->setOpcode(JCMPGE_S); break; case JCMPLE_S: jump_node->setOpcode(JCMPG_S); break; case JFLDEQ: jump_node->setOpcode(JFLDNEQ); break; case JFLDNEQ: jump_node->setOpcode(JFLDEQ); break; case JFLDGT: jump_node->setOpcode(JFLDLT); break; case JFLDLT: jump_node->setOpcode(JFLDGT); break; default: break; } //std::cout << "Nuovo nodo: " << std::endl; //insn->printNode(std::cout,false); //std::cout << std::endl; } //else bb is followed by is false target so it's correct return; }
void BasicBlock::dumpFooter(PrintStream& out) const { if (successors().size()) out.print(" Successors: ", listDump(successors()), "\n"); }
void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { int numblocks = _methodBlocks->num_blocks(); int stkSize = _method->max_stack(); int numLocals = _method->max_locals(); StateInfo state; int datacount = (numblocks + 1) * (stkSize + numLocals); int datasize = datacount * sizeof(ArgumentMap); StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo)); ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); ArgumentMap *dp = statedata; state._vars = dp; dp += numLocals; state._stack = dp; dp += stkSize; state._initialized = false; state._max_stack = stkSize; for (int i = 0; i < numblocks; i++) { blockstates[i]._vars = dp; dp += numLocals; blockstates[i]._stack = dp; dp += stkSize; blockstates[i]._initialized = false; blockstates[i]._stack_height = 0; blockstates[i]._max_stack = stkSize; } GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL); GrowableArray<ciBlock *> successors(arena, 4, 0, NULL); _methodBlocks->clear_processed(); // initialize block 0 state from method signature ArgumentMap allVars; // all oop arguments to method ciSignature* sig = method()->signature(); int j = 0; if (!method()->is_static()) { // record information for "this" blockstates[0]._vars[j].set(j); allVars.add(j); j++; } for (int i = 0; i < sig->count(); i++) { ciType* t = sig->type_at(i); if (!t->is_primitive_type()) { blockstates[0]._vars[j].set(j); allVars.add(j); } j += t->size(); } blockstates[0]._initialized = true; assert(j == _arg_size, "just checking"); ArgumentMap unknown_map; unknown_map.add_unknown(); worklist.push(_methodBlocks->block_containing(0)); while(worklist.length() > 0) { ciBlock *blk = worklist.pop(); StateInfo *blkState = blockstates+blk->index(); if (blk->is_handler() || blk->is_ret_target()) { // for an exception handler or a target of a ret instruction, we assume the worst case, // that any variable or stack slot could contain any argument for (int i = 0; i < numLocals; i++) { state._vars[i] = allVars; } if (blk->is_handler()) { state._stack_height = 1; } else { state._stack_height = blkState->_stack_height; } for (int i = 0; i < state._stack_height; i++) { state._stack[i] = allVars; } } else { for (int i = 0; i < numLocals; i++) { state._vars[i] = blkState->_vars[i]; } for (int i = 0; i < blkState->_stack_height; i++) { state._stack[i] = blkState->_stack[i]; } state._stack_height = blkState->_stack_height; } iterate_one_block(blk, state, successors); // if this block has any exception handlers, push them // onto successor list if (blk->has_handler()) { DEBUG_ONLY(int handler_count = 0;) int blk_start = blk->start_bci(); int blk_end = blk->limit_bci(); for (int i = 0; i < numblocks; i++) { ciBlock *b = _methodBlocks->block(i); if (b->is_handler()) { int ex_start = b->ex_start_bci(); int ex_end = b->ex_limit_bci(); if ((ex_start >= blk_start && ex_start < blk_end) || (ex_end > blk_start && ex_end <= blk_end)) { successors.push(b); } DEBUG_ONLY(handler_count++;) } }
HOT successor_container fill_queue_recursive(group & g, successor_container const & successors_from_parent, size_t previous_activation_limit) { assert (g.has_synth_children()); typedef server_node_list::reverse_iterator r_iterator; successor_container successors(successors_from_parent); size_t children = g.child_count(); sequential_child_list sequential_children; sequential_children.reserve(g.child_synth_count); for (r_iterator it = g.child_nodes.rbegin(); it != g.child_nodes.rend(); ++it) { server_node & node = *it; if (node.is_synth()) { r_iterator end_of_node = it; --end_of_node; // one element behind the last std::size_t node_count = 1; // we fill the child nodes in reverse order to an array for(;;) { sequential_children.push_back(&*it); ++it; if (it == g.child_nodes.rend()) break; // we found the beginning of this group if (!it->is_synth()) break; // we hit a child group, later we may want to add it's nodes, too? ++node_count; } --it; // we iterated one element too far, so we need to go back to the previous element assert(sequential_children.size() == node_count); auto seq_it = sequential_children.rbegin(); int activation_limit = get_previous_activation_count(it, g.child_nodes.rend(), previous_activation_limit); thread_queue_item * q_item = q->allocate_queue_item(queue_node(std::move(queue_node_data(static_cast<abstract_synth*>(*seq_it++))), node_count), successors, activation_limit); queue_node & q_node = q_item->get_job(); // now we can add all nodes sequentially for(;seq_it != sequential_children.rend(); ++seq_it) q_node.add_node(static_cast<abstract_synth*>(*seq_it)); sequential_children.clear(); assert(q_node.size() == node_count); /* advance successor list */ successors = successor_container(1); successors[0] = q_item; if (activation_limit == 0) q->add_initially_runnable(q_item); children -= node_count; } else { abstract_group & grp = static_cast<abstract_group&>(node); if (grp.has_synth_children()) { int activation_limit = get_previous_activation_count(it, g.child_nodes.rend(), previous_activation_limit); successors = fill_queue_recursive(grp, successors, activation_limit); } children -= 1; } } assert(children == 0); return successors; }
void MemorySSAUpdater::fixupDefs(const SmallVectorImpl<MemoryAccess *> &Vars) { SmallPtrSet<const BasicBlock *, 8> Seen; SmallVector<const BasicBlock *, 16> Worklist; for (auto *NewDef : Vars) { // First, see if there is a local def after the operand. auto *Defs = MSSA->getWritableBlockDefs(NewDef->getBlock()); auto DefIter = NewDef->getDefsIterator(); // If there is a local def after us, we only have to rename that. if (++DefIter != Defs->end()) { cast<MemoryDef>(DefIter)->setDefiningAccess(NewDef); continue; } // Otherwise, we need to search down through the CFG. // For each of our successors, handle it directly if their is a phi, or // place on the fixup worklist. for (const auto *S : successors(NewDef->getBlock())) { if (auto *MP = MSSA->getMemoryAccess(S)) setMemoryPhiValueForBlock(MP, NewDef->getBlock(), NewDef); else Worklist.push_back(S); } while (!Worklist.empty()) { const BasicBlock *FixupBlock = Worklist.back(); Worklist.pop_back(); // Get the first def in the block that isn't a phi node. if (auto *Defs = MSSA->getWritableBlockDefs(FixupBlock)) { auto *FirstDef = &*Defs->begin(); // The loop above and below should have taken care of phi nodes assert(!isa<MemoryPhi>(FirstDef) && "Should have already handled phi nodes!"); // We are now this def's defining access, make sure we actually dominate // it assert(MSSA->dominates(NewDef, FirstDef) && "Should have dominated the new access"); // This may insert new phi nodes, because we are not guaranteed the // block we are processing has a single pred, and depending where the // store was inserted, it may require phi nodes below it. cast<MemoryDef>(FirstDef)->setDefiningAccess(getPreviousDef(FirstDef)); return; } // We didn't find a def, so we must continue. for (const auto *S : successors(FixupBlock)) { // If there is a phi node, handle it. // Otherwise, put the block on the worklist if (auto *MP = MSSA->getMemoryAccess(S)) setMemoryPhiValueForBlock(MP, FixupBlock, NewDef); else { // If we cycle, we should have ended up at a phi node that we already // processed. FIXME: Double check this if (!Seen.insert(S).second) continue; Worklist.push_back(S); } } } } }
void PFLTraceBuilder::handle_one_succ_bb(PFLTraceBuilder::bb_t *bb) { assert(bb != NULL); // std::cout << "TRACE: Esamino il BB: " << bb->getId() << std::endl; bb_t* next = bb->getProperty< bb_t* >(next_prop_name); std::list< PFLCFG::GraphNode* > successors(bb->getSuccessors()); bb_t *target = successors.front()->NodeInfo; if(bb->getCode().size() == 0 || ! bb->getCode().back()->isJump()) { //empty BB should be eliminated from the cfg!!! //for now emit a jump to the target if necessary if(cfg.getExitBB() == target) return; if(!next || next->getId() != target->getId()) { // std::cerr << "BB ID: " << bb->getId() << "Code Size = 0" << std::endl; //assert(1 == 0 && "This should not happen"); JumpMIRONode *new_j = new JumpMIRONode(bb->getId(), cfg.getBBById(target->getId())->getStartLabel()); //bb->getCode().pop_back(); new_j->setOpcode(JUMPW); bb->getCode().push_back(new_j); } } else { MIRONode* insn = bb->getCode().back(); //std::cout << "Ultima istruzione: "; //insn->printNode(std::cout, true); //std::cout << std::endl; uint16_t opcode; if(insn->getKid(0)) opcode = insn->getKid(0)->getOpcode(); else opcode = insn->getOpcode(); //if not followed by next bb in emission if(!next || next->getId() != target->getId()) { //if has not explicit jump if(opcode != JUMP && opcode != JUMPW) { //add the jump JumpMIRONode *new_j = new JumpMIRONode(bb->getId(), cfg.getBBById(target->getId())->getStartLabel()); //bb->getCode().pop_back(); new_j->setOpcode(JUMPW); bb->getCode().push_back(new_j); } } else { //we can remove last useless jump if(opcode == JUMP || opcode == JUMPW) { bb->getCode().pop_back(); delete insn; } } } return; }