void LowerEmAsyncify::FindContextVariables(AsyncCallEntry & Entry) { BasicBlock *AfterCallBlock = Entry.AfterCallBlock; Function & F = *AfterCallBlock->getParent(); // Create a new entry block as if in the callback function // theck check variables that no longer properly dominate their uses BasicBlock *EntryBlock = BasicBlock::Create(TheModule->getContext(), "", &F, &F.getEntryBlock()); BranchInst::Create(AfterCallBlock, EntryBlock); DominatorTreeWrapperPass DTW; DTW.runOnFunction(F); DominatorTree& DT = DTW.getDomTree(); // These blocks may be using some values defined at or before AsyncCallBlock BasicBlockSet Ramifications = FindReachableBlocksFrom(AfterCallBlock); SmallPtrSet<Value*, 256> ContextVariables; Values Pending; // Examine the instructions, find all variables that we need to store in the context for (BasicBlockSet::iterator RI = Ramifications.begin(), RE = Ramifications.end(); RI != RE; ++RI) { for (BasicBlock::iterator I = (*RI)->begin(), E = (*RI)->end(); I != E; ++I) { for (unsigned i = 0, NumOperands = I->getNumOperands(); i < NumOperands; ++i) { Value *O = I->getOperand(i); if (Instruction *Inst = dyn_cast<Instruction>(O)) { if (Inst == Entry.AsyncCallInst) continue; // for the original async call, we will load directly from async return value if (ContextVariables.count(Inst) != 0) continue; // already examined if (!DT.dominates(Inst, I->getOperandUse(i))) { // `I` is using `Inst`, yet `Inst` does not dominate `I` if we arrive directly at AfterCallBlock // so we need to save `Inst` in the context ContextVariables.insert(Inst); Pending.push_back(Inst); } } else if (Argument *Arg = dyn_cast<Argument>(O)) { // count() should be as fast/slow as insert, so just insert here ContextVariables.insert(Arg); } } } } // restore F EntryBlock->eraseFromParent(); Entry.ContextVariables.clear(); Entry.ContextVariables.reserve(ContextVariables.size()); for (SmallPtrSet<Value*, 256>::iterator I = ContextVariables.begin(), E = ContextVariables.end(); I != E; ++I) { Entry.ContextVariables.push_back(*I); } }