bool splitCriticalEdges(IRUnit& unit) { FTRACE(2, "splitting critical edges\n"); auto modified = removeUnreachable(unit); auto const startBlocks = unit.numBlocks(); for (auto* block : unit.main()->blocks()) { splitCriticalEdge(unit, block->takenEdge()); splitCriticalEdge(unit, block->nextEdge()); } return modified || unit.numBlocks() != startBlocks; }
bool splitCriticalEdges(IRUnit& unit) { FTRACE(2, "splitting critical edges\n"); auto modified = removeUnreachable(unit); if (modified) reflowTypes(unit); auto const startBlocks = unit.numBlocks(); // Try to split outgoing edges of each reachable block. This is safe in // a postorder walk since we visit blocks after visiting successors. postorderWalk(unit, [&](Block* b) { splitCriticalEdge(unit, b->takenEdge()); splitCriticalEdge(unit, b->nextEdge()); }); return modified || unit.numBlocks() != startBlocks; }
bool splitCriticalEdges(IRUnit& unit) { FTRACE(2, "splitting critical edges\n"); auto modified = removeUnreachable(unit); if (modified) reflowTypes(unit); auto const startBlocks = unit.numBlocks(); std::unordered_set<Block*> newCatches; std::unordered_set<Block*> oldCatches; // Try to split outgoing edges of each reachable block. This is safe in // a postorder walk since we visit blocks after visiting successors. postorderWalk(unit, [&](Block* b) { auto bnew = splitCriticalEdge(unit, b->takenEdge()); splitCriticalEdge(unit, b->nextEdge()); assertx(!b->next() || !b->next()->isCatch()); if (bnew && b->taken()->isCatch()) { newCatches.emplace(bnew); oldCatches.emplace(b->taken()); } }); for (auto b : newCatches) { auto bc = b->next()->begin(); assertx(bc->is(BeginCatch)); b->prepend(unit.gen(BeginCatch, bc->bcctx())); } for (auto b : oldCatches) { auto bc = b->begin(); assertx(bc->is(BeginCatch)); b->erase(bc); } return modified || unit.numBlocks() != startBlocks; }
bool PhiElimination::eliminatePhiNodes( IRFunction *function, BasicBlock *block) { if (!block->numOfInstrs() || !block->front()->is_phi_node()) return false; splitCriticalEdge(function, block); for (auto iter = block->instr_begin(); iter != block->instr_end(); ++iter) { Instruction *instr = *iter; if (!instr->is_phi_node()) break; unsigned to = instr->getOutputReg().getRegisterNum(); // Now loop over all of the incoming arguments, // changing them to copy into the destReg register // in the corresponding predecessor basic block. for (auto op = instr->op_begin(); op != instr->op_end(); ++op) { Value *OPV = op->get_value(); if (OPV->is_undef()) continue; assert(!OPV->is_value()); Instruction *opI = static_cast<Instruction*>(OPV); BasicBlock *opBlock = findEdge(opI->get_parent(), block); assert(opBlock); // Figure out where to insert the copy, which is at the end of the // predecessor basic block, but before any terminator/branch // instructions... BasicBlock::instr_iterator I = opBlock->instr_end(); if (I == opBlock->instr_begin()) assert(0 && "Not allow empty block."); --I; // because split ensure use this reg must be safe. IRContext::insertAfter<Assign>( I, to, opI->getOutputReg().getRegisterNum()); } // Unlink the Phi node from the basic block. // instr->erase_from_parent(); // jump at CodeGen } return true; }