bool isAllocCall(const llvm::CallInst* CI) { if (!CI) return false; llvm::Function* Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration()) return false; return isAllocCall(Callee->getName()); }
bool EscapeAnalysis::runOnFunction(Function& F) { return false; // This analysis is currently broken and not maintained if (VERBOSITY("opt") >= 1) outs() << "Running escape analysis on " << F.getName() << '\n'; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { CallInst* alloc = dyn_cast<CallInst>(&*inst_it); if (!alloc || !isAllocCall(alloc)) continue; ChainInfo* chain = new ChainInfo(alloc); chains.push_back(chain); if (VERBOSITY("opt") >= 2) { errs() << "Found chain " << chain << " starting at " << *alloc; } // Calculating derived pointers, and finding escape points { // Instructions in the queue to be visited: std::deque<Instruction*> queue; // Instructions we've fully visited: std::unordered_set<Instruction*> checked; queue.push_back(alloc); while (queue.size()) { Instruction* next = queue.back(); queue.pop_back(); if (checked.count(next)) continue; checked.insert(next); for (User* user : next->users()) { if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(user)) { queue.push_back(gep); chain->derived.insert(gep); chain_by_pointer[gep] = chain; continue; } if (CastInst* bc = dyn_cast<CastInst>(user)) { queue.push_back(bc); chain->derived.insert(bc); chain_by_pointer[bc] = chain; continue; } if (PHINode* phi = dyn_cast<PHINode>(user)) { queue.push_back(phi); chain->derived.insert(phi); chain_by_pointer[phi] = chain; continue; } if (isa<LoadInst>(user)) { continue; } if (ReturnInst* ret = dyn_cast<ReturnInst>(user)) { if (VERBOSITY() >= 2) errs() << "Not dead; used here: " << *ret << '\n'; chain->escape_points.insert(ret); continue; } if (StoreInst* si = dyn_cast<StoreInst>(user)) { if (si->getPointerOperand() == next) { } else { assert(si->getValueOperand() == next); if (VERBOSITY() >= 2) errs() << "Escapes here: " << *si << '\n'; chain->escape_points.insert(si); } continue; } if (llvm::isa<CallInst>(user) || llvm::isa<InvokeInst>(user)) { if (VERBOSITY() >= 2) errs() << "Escapes here: " << *user << '\n'; chain->escape_points.insert(dyn_cast<Instruction>(user)); continue; } user->dump(); RELEASE_ASSERT(0, ""); } } } // Calculating BB-level escape-ness { std::deque<const BasicBlock*> queue; for (const auto I : chain->escape_points) { chain->bb_escapes[I->getParent()] = BBPartialEscape; queue.insert(queue.end(), succ_begin(I->getParent()), succ_end(I->getParent())); } while (queue.size()) { const BasicBlock* bb = queue.back(); queue.pop_back(); if (chain->bb_escapes[bb] == BBFullEscape) continue; chain->bb_escapes[bb] = BBFullEscape; queue.insert(queue.end(), succ_begin(bb), succ_end(bb)); } for (BasicBlock& bb : F) { if (chain->bb_escapes.count(&bb) == 0) chain->bb_escapes[&bb] = BBNoEscape; // outs() << bb.getName() << ' ' << chain->bb_escapes[&bb] << '\n'; } } } return false; }