bool PrintPass::visit(BasicBlock *bb) { #if 0 INFO("---\n"); for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) INFO(" <- BB:%i (%s)\n", BasicBlock::get(ei.getNode())->getId(), ei.getEdge()->typeStr()); #endif INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount()); if (bb->idom()) INFO("idom = BB:%i, ", bb->idom()->getId()); INFO("df = { "); for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next()) INFO("BB:%i ", BasicBlock::get(df)->getId()); INFO("}\n"); for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) INFO(" -> BB:%i (%s)\n", BasicBlock::get(ei.getNode())->getId(), ei.getEdge()->typeStr()); return true; }
void DominatorTree::buildDFS(Graph::Node *node) { SEMI(node->tag) = node->tag; for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next()) { if (SEMI(ei.getNode()->tag) < 0) { buildDFS(ei.getNode()); PARENT(ei.getNode()->tag) = node->tag; } } }
void search(Graph::Node *node, const bool preorder, const int sequence) { if (preorder) nodes[count++] = node; for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next()) if (ei.getNode()->visit(sequence)) search(ei.getNode(), preorder, sequence); if (!preorder) nodes[count++] = node; }
unsigned int BasicBlock::initiatesSimpleConditional() const { Graph::Node *out[2]; int n; Graph::Edge::Type eR; if (cfg.outgoingCount() != 2) // -> if and -> else/endif return false; n = 0; for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next()) out[n++] = ei.getNode(); eR = out[1]->outgoing().getType(); // IF block is out edge to the right if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK) return 0x2; if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence return 0x0; // do they reconverge immediately ? if (out[1]->outgoing().getNode() == out[0]) return 0x1; if (out[0]->outgoingCount() == 1) if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode()) return 0x3; return 0x0; }
void search(Graph::Node *node, const int sequence) { Stack bb, cross; bb.push(node); while (bb.getSize()) { node = reinterpret_cast<Graph::Node *>(bb.pop().u.p); assert(node); if (!node->visit(sequence)) continue; node->tag = 0; for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next()) { switch (ei.getType()) { case Graph::Edge::TREE: case Graph::Edge::FORWARD: case Graph::Edge::DUMMY: if (++(ei.getNode()->tag) == ei.getNode()->incidentCountFwd()) bb.push(ei.getNode()); break; case Graph::Edge::BACK: continue; case Graph::Edge::CROSS: if (++(ei.getNode()->tag) == 1) cross.push(ei.getNode()); break; default: assert(!"unknown edge kind in CFG"); break; } } nodes[count++] = node; if (bb.getSize() == 0) cross.moveTo(bb); } }
void DominatorTree::build() { DLList *bucket = new DLList[count]; Node *nv, *nw; int p, u, v, w; buildDFS(cfg->getRoot()); for (w = count - 1; w >= 1; --w) { nw = vert[w]; assert(nw->tag == w); for (Graph::EdgeIterator ei = nw->incident(); !ei.end(); ei.next()) { nv = ei.getNode(); v = nv->tag; u = eval(v); if (SEMI(u) < SEMI(w)) SEMI(w) = SEMI(u); } p = PARENT(w); bucket[SEMI(w)].insert(nw); link(p, w); for (DLList::Iterator it = bucket[p].iterator(); !it.end(); it.erase()) { v = reinterpret_cast<Node *>(it.get())->tag; u = eval(v); DOM(v) = (SEMI(u) < SEMI(v)) ? u : p; } } for (w = 1; w < count; ++w) { if (DOM(w) != SEMI(w)) DOM(w) = DOM(DOM(w)); } DOM(0) = 0; insert(&BasicBlock::get(cfg->getRoot())->dom); do { p = 0; for (v = 1; v < count; ++v) { nw = &BasicBlock::get(vert[DOM(v)])->dom;; nv = &BasicBlock::get(vert[v])->dom; if (nw->getGraph() && !nv->getGraph()) { ++p; nw->attach(nv, Graph::Edge::TREE); } } } while (p); delete[] bucket; }
// liveIn(bb) = usedBeforeAssigned(bb) U (liveOut(bb) - assigned(bb)) void Function::buildLiveSetsPreSSA(BasicBlock *bb, const int seq) { Function *f = bb->getFunction(); BitSet usedBeforeAssigned(allLValues.getSize(), true); BitSet assigned(allLValues.getSize(), true); bb->liveSet.allocate(allLValues.getSize(), false); int n = 0; for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { BasicBlock *out = BasicBlock::get(ei.getNode()); if (out == bb) continue; if (out->cfg.visit(seq)) buildLiveSetsPreSSA(out, seq); if (!n++) bb->liveSet = out->liveSet; else bb->liveSet |= out->liveSet; } if (!n && !bb->liveSet.marker) bb->liveSet.fill(0); bb->liveSet.marker = true; for (Instruction *i = bb->getEntry(); i; i = i->next) { for (int s = 0; i->srcExists(s); ++s) if (i->getSrc(s)->asLValue() && !assigned.test(i->getSrc(s)->id)) usedBeforeAssigned.set(i->getSrc(s)->id); for (int d = 0; i->defExists(d); ++d) assigned.set(i->getDef(d)->id); } if (bb == BasicBlock::get(f->cfgExit)) { for (std::deque<ValueRef>::iterator it = f->outs.begin(); it != f->outs.end(); ++it) { if (!assigned.test(it->get()->id)) usedBeforeAssigned.set(it->get()->id); } } bb->liveSet.andNot(assigned); bb->liveSet |= usedBeforeAssigned; }
void Function::printCFGraph(const char *filePath) { FILE *out = fopen(filePath, "a"); if (!out) { ERROR("failed to open file: %s\n", filePath); return; } INFO("printing control flow graph to: %s\n", filePath); fprintf(out, "digraph G {\n"); for (IteratorRef it = cfg.iteratorDFS(); !it->end(); it->next()) { BasicBlock *bb = BasicBlock::get( reinterpret_cast<Graph::Node *>(it->get())); int idA = bb->getId(); for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { int idB = BasicBlock::get(ei.getNode())->getId(); switch (ei.getType()) { case Graph::Edge::TREE: fprintf(out, "\t%i -> %i;\n", idA, idB); break; case Graph::Edge::FORWARD: fprintf(out, "\t%i -> %i [color=green];\n", idA, idB); break; case Graph::Edge::CROSS: fprintf(out, "\t%i -> %i [color=red];\n", idA, idB); break; case Graph::Edge::BACK: fprintf(out, "\t%i -> %i;\n", idA, idB); break; case Graph::Edge::DUMMY: fprintf(out, "\t%i -> %i [style=dotted];\n", idA, idB); break; default: assert(0); break; } } } fprintf(out, "}\n"); fclose(out); }
BasicBlock * BasicBlock::clone(ClonePolicy<Function>& pol) const { BasicBlock *bb = new BasicBlock(pol.context()); pol.set(this, bb); for (Instruction *i = getFirst(); i; i = i->next) bb->insertTail(i->clone(pol)); pol.context()->cfg.insert(&bb->cfg); for (Graph::EdgeIterator it = cfg.outgoing(); !it.end(); it.next()) { BasicBlock *obb = BasicBlock::get(it.getNode()); bb->cfg.attach(&pol.get(obb)->cfg, it.getType()); } return bb; }
void Function::buildDefSetsPreSSA(BasicBlock *bb, const int seq) { bb->defSet.allocate(allLValues.getSize(), !bb->liveSet.marker); bb->liveSet.marker = true; for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) { BasicBlock *in = BasicBlock::get(ei.getNode()); if (in->cfg.visit(seq)) buildDefSetsPreSSA(in, seq); bb->defSet |= in->defSet; } for (Instruction *i = bb->getEntry(); i; i = i->next) { for (int d = 0; i->defExists(d); ++d) bb->defSet.set(i->getDef(d)->id); } }
// Go through BBs in dominance order, create new values for each definition, // and replace all sources with their current new values. // // NOTE: The values generated for function inputs/outputs have no connection // to their corresponding outputs/inputs in other functions. Only allocation // of physical registers will establish this connection. // void RenamePass::search(BasicBlock *bb) { LValue *lval, *ssa; int d, s; const Target *targ = prog->getTarget(); // Put current definitions for function inputs values on the stack. // They can be used before any redefinitions are pushed. if (bb == BasicBlock::get(func->cfg.getRoot())) { for (std::deque<ValueDef>::iterator it = func->ins.begin(); it != func->ins.end(); ++it) { lval = it->get()->asLValue(); assert(lval); ssa = new_LValue(func, targ->nativeFile(lval->reg.file)); ssa->reg.size = lval->reg.size; ssa->reg.data.id = lval->reg.data.id; it->setSSA(ssa); stack[lval->id].push(ssa); } } for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { // PHI sources get definitions from the passes through the incident BBs, // so skip them here. if (stmt->op != OP_PHI) { for (s = 0; stmt->srcExists(s); ++s) { lval = stmt->getSrc(s)->asLValue(); if (!lval) continue; // Values on the stack created in previously visited blocks, and // function inputs, will be valid because they dominate this one. lval = getStackTop(lval); if (!lval) lval = mkUndefined(stmt->getSrc(s)); stmt->setSrc(s, lval); } } for (d = 0; stmt->defExists(d); ++d) { lval = stmt->def(d).get()->asLValue(); assert(lval); stmt->def(d).setSSA( new_LValue(func, targ->nativeFile(lval->reg.file))); stmt->def(d).get()->reg.size = lval->reg.size; stmt->def(d).get()->reg.data.id = lval->reg.data.id; stack[lval->id].push(stmt->def(d).get()); } } // Update sources of PHI ops corresponding to this BB in outgoing BBs. for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) { Instruction *phi; int p = 0; BasicBlock *sb = BasicBlock::get(ei.getNode()); // which predecessor of sb is bb ? for (Graph::EdgeIterator ei = sb->cfg.incident(); !ei.end(); ei.next()) { if (ei.getNode() == &bb->cfg) break; ++p; } assert(p < sb->cfg.incidentCount()); for (phi = sb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) { lval = getStackTop(phi->getSrc(p)); if (!lval) lval = mkUndefined(phi->getSrc(p)); phi->setSrc(p, lval); } } // Visit the BBs we dominate. for (Graph::EdgeIterator ei = bb->dom.outgoing(); !ei.end(); ei.next()) search(BasicBlock::get(ei.getNode())); // Update function outputs to the last definitions of their pre-SSA values. // I hope they're unique, i.e. that we get PHIs for all of them ... if (bb == BasicBlock::get(func->cfgExit)) { for (std::deque<ValueRef>::iterator it = func->outs.begin(); it != func->outs.end(); ++it) { lval = it->get()->asLValue(); if (!lval) continue; lval = getStackTop(lval); if (!lval) lval = mkUndefined(it->get()); it->set(lval); } } // Pop the values we created in this block from the stack because we will // return to blocks that we do not dominate. for (Instruction *stmt = bb->getFirst(); stmt; stmt = stmt->next) { if (stmt->op == OP_NOP) continue; for (d = 0; stmt->defExists(d); ++d) stack[stmt->def(d).preSSA()->id].pop(); } }