bool is_tmp_usable(const IdomVector& idoms, const SSATmp* tmp, const Block* where) { if (tmp->inst()->is(DefConst)) return true; auto const definingBlock = findDefiningBlock(tmp, idoms); if (!definingBlock) return false; return dominates(definingBlock, where, idoms); }
/* * Build the CFG, then the dominator tree, then use it to validate SSA. * 1. Each src must be defined by some other instruction, and each dst must * be defined by the current instruction. * 2. Each src must be defined earlier in the same block or in a dominator. * 3. Each dst must not be previously defined. * 4. Treat tmps defined by DefConst as always defined. * 5. Each predecessor of a reachable block must be reachable (deleted * blocks must not have out-edges to reachable blocks). * 6. The entry block must not have any predecessors. * 7. The entry block starts with a DefFP instruction. */ bool checkCfg(const IRUnit& unit) { auto const blocksIds = rpoSortCfgWithIds(unit); auto const& blocks = blocksIds.blocks; jit::hash_set<const Edge*> edges; // Entry block can't have predecessors. always_assert(unit.entry()->numPreds() == 0); // Entry block starts with DefFP always_assert(!unit.entry()->empty() && unit.entry()->begin()->op() == DefFP); // Check valid successor/predecessor edges. for (Block* b : blocks) { auto checkEdge = [&] (const Edge* e) { always_assert(e->from() == b); edges.insert(e); for (auto& p : e->to()->preds()) if (&p == e) return; always_assert(false); // did not find edge. }; checkBlock(b); if (auto *e = b->nextEdge()) checkEdge(e); if (auto *e = b->takenEdge()) checkEdge(e); } for (Block* b : blocks) { for (auto const &e : b->preds()) { always_assert(&e == e.inst()->takenEdge() || &e == e.inst()->nextEdge()); always_assert(e.to() == b); } } // Visit every instruction and make sure their sources are defined in a block // that dominates the block containing the instruction. auto const idoms = findDominators(unit, blocksIds); forEachInst(blocks, [&] (const IRInstruction* inst) { for (auto src : inst->srcs()) { if (src->inst()->is(DefConst)) continue; auto const dom = findDefiningBlock(src); always_assert_flog( dom && dominates(dom, inst->block(), idoms), "src '{}' in '{}' came from '{}', which is not a " "DefConst and is not defined at this use site", src->toString(), inst->toString(), src->inst()->toString() ); } }); return true; }