void reflowTypes(Block* const changed, const BlockList& blocks) { assert(isRPOSorted(blocks)); auto it = rpoIteratorTo(blocks, changed); assert(it != blocks.end()); for (; it != blocks.end(); ++it) { FTRACE(5, "reflowTypes: visiting block {}\n", (*it)->id()); for (auto& inst : **it) visitInstruction(&inst); } }
void cloneToBlock(const BlockList& rpoBlocks, IRFactory& irFactory, Block::iterator const first, Block::iterator const last, Block* const target) { assert(isRPOSorted(rpoBlocks)); StateVector<SSATmp,SSATmp*> rewriteMap(irFactory, nullptr); auto rewriteSources = [&] (IRInstruction* inst) { for (int i = 0; i < inst->numSrcs(); ++i) { if (auto newTmp = rewriteMap[inst->src(i)]) { FTRACE(5, " rewrite: {} -> {}\n", inst->src(i)->toString(), newTmp->toString()); inst->setSrc(i, newTmp); } } }; auto targetIt = target->skipHeader(); for (auto it = first; it != last; ++it) { assert(!it->isControlFlow()); FTRACE(5, "cloneToBlock({}): {}\n", target->id(), it->toString()); auto const newInst = irFactory.cloneInstruction(&*it); if (auto const numDests = newInst->numDsts()) { for (int i = 0; i < numDests; ++i) { FTRACE(5, " add rewrite: {} -> {}\n", it->dst(i)->toString(), newInst->dst(i)->toString()); rewriteMap[it->dst(i)] = newInst->dst(i); } } target->insert(targetIt, newInst); targetIt = ++target->iteratorTo(newInst); } auto it = rpoIteratorTo(rpoBlocks, target); for (; it != rpoBlocks.end(); ++it) { FTRACE(5, "cloneToBlock: rewriting block {}\n", (*it)->id()); for (auto& inst : **it) { FTRACE(5, " rewriting {}\n", inst.toString()); rewriteSources(&inst); } } }
/* * Find the immediate dominator of each block using Cooper, Harvey, and * Kennedy's "A Simple, Fast Dominance Algorithm", returned as a vector * of postorder ids, indexed by postorder id. */ IdomVector findDominators(const BlockList& blocks) { assert(isRPOSorted(blocks)); // Calculate immediate dominators with the iterative two-finger algorithm. // When it terminates, idom[post-id] will contain the post-id of the // immediate dominator of each block. idom[start] will be -1. This is // the general algorithm but it will only loop twice for loop-free graphs. auto const num_blocks = blocks.size(); IdomVector idom(num_blocks, -1); auto start = blocks.begin(); int start_id = (*start)->postId(); idom[start_id] = start_id; start++; for (bool changed = true; changed; ) { changed = false; // for each block after start, in reverse postorder for (auto it = start; it != blocks.end(); it++) { Block* block = *it; int b = block->postId(); // new_idom = any already-processed predecessor auto edge_it = block->preds().begin(); int new_idom = edge_it->from()->postId(); while (idom[new_idom] == -1) new_idom = (++edge_it)->from()->postId(); // for all other already-processed predecessors p of b for (auto& edge : block->preds()) { auto p = edge.from()->postId(); if (p != new_idom && idom[p] != -1) { // find earliest common predecessor of p and new_idom // (higher postIds are earlier in flow and in dom-tree). int b1 = p, b2 = new_idom; do { while (b1 < b2) b1 = idom[b1]; while (b2 < b1) b2 = idom[b2]; } while (b1 != b2); new_idom = b1; } } if (idom[b] != new_idom) { idom[b] = new_idom; changed = true; } } } idom[start_id] = -1; // start has no idom. return idom; }
/* * Find the immediate dominator of each block using Cooper, Harvey, and * Kennedy's "A Simple, Fast Dominance Algorithm", returned as a vector * of Block*, indexed by block. IdomVector[b] == nullptr if b has no * dominator. This is the case for the entry block and any blocks not * reachable from the entry block. */ IdomVector findDominators(const IRUnit& unit, const BlockList& blocks) { assert(isRPOSorted(blocks)); // Calculate immediate dominators with the iterative two-finger algorithm. // When it terminates, idom[post-id] will contain the post-id of the // immediate dominator of each block. idom[start] will be -1. This is // the general algorithm but it will only loop twice for loop-free graphs. IdomVector idom(unit, nullptr); auto start = blocks.begin(); auto entry = *start; idom[entry] = entry; start++; for (bool changed = true; changed; ) { changed = false; // for each block after start, in reverse postorder for (auto it = start; it != blocks.end(); it++) { Block* block = *it; // p1 = any already-processed predecessor auto predIter = block->preds().begin(); auto predEnd = block->preds().end(); auto p1 = predIter->from(); while (!idom[p1]) p1 = (++predIter)->from(); // for all other already-processed predecessors p2 of block for (++predIter; predIter != predEnd; ++predIter) { auto p2 = predIter->from(); if (p2 == p1 || !idom[p2]) continue; // find earliest common predecessor of p1 and p2 // (higher postIds are earlier in flow and in dom-tree). do { while (p1->postId() < p2->postId()) p1 = idom[p1]; while (p2->postId() < p1->postId()) p2 = idom[p2]; } while (p1 != p2); } if (idom[block] != p1) { idom[block] = p1; changed = true; } } } idom[entry] = nullptr; // entry has no dominator. return idom; }
void reflowTypes(Block* const changed, const BlockList& blocks) { assert(isRPOSorted(blocks)); auto retypeDst = [&] (IRInstruction* inst, int num) { auto ssa = inst->dst(num); /* * The type of a tmp defined by DefLabel is the union of the * types of the tmps at each incoming Jmp. */ if (inst->op() == DefLabel) { Type type = Type::Bottom; inst->block()->forEachSrc(num, [&](IRInstruction*, SSATmp* tmp) { type = Type::unionOf(type, tmp->type()); }); ssa->setType(type); return; } ssa->setType(outputType(inst, num)); }; auto visit = [&] (IRInstruction* inst) { for (int i = 0; i < inst->numDsts(); ++i) { auto const ssa = inst->dst(i); auto const oldType = ssa->type(); retypeDst(inst, i); if (!ssa->type().equals(oldType)) { FTRACE(5, "reflowTypes: retyped {} in {}\n", oldType.toString(), inst->toString()); } } }; auto it = rpoIteratorTo(blocks, changed); assert(it != blocks.end()); for (; it != blocks.end(); ++it) { FTRACE(5, "reflowTypes: visiting block {}\n", (*it)->id()); for (auto& inst : **it) visit(&inst); } }