static bool isAddressTaken(Value* V) { //Find the users for the value to see if it was assigned. for (Value::const_use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { User *U = I->getUser(); if(isa<StoreInst>(U)) return true; if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) { if(U->use_empty()) continue; if(isa<GlobalAlias>(U)) { if(isAddressTaken(U)) return true; } else { if (Constant *C = dyn_cast<Constant>(U)) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { if (CE->getOpcode() == Instruction::BitCast) { return isAddressTaken(CE); } } } return true; } // FIXME: Can be more robust here for weak aliases that // are never used } else { llvm::CallSite CS(cast<Instruction>(U)); if (!CS.isCallee(&*I)) return true; } } return false; }
bool SPEscapes(Function &F, const Argument *sp_arg) { // We monotonically accumulate the set of values that hold a pointer based on Sp // INVARIANT: an Instruction in the work list never defines a Value that is already in SpPointers std::set<const Value*> SpPointers; SpPointers.insert(sp_arg); // Initialize the worklist to all of the instructions using the Sp std::set<const Instruction*> WorkList; for (Value::const_use_iterator UI = sp_arg->use_begin(), UE = sp_arg->use_end(); UI != UE; ++UI) WorkList.insert(cast<Instruction>(UI->getUser())); while (!WorkList.empty()) { // Get an element from the worklist const Instruction *I = *WorkList.begin(); WorkList.erase(WorkList.begin()); // Switch on the kind of instruction to decide whether this instruction should add to SpPointers // // NB: it is safe to say "load" never adds to SpPointers, since we terminate the // fixed point process immediately if we ever detect that a SpPointer escapes. // // NB: The only calls we see in GHC-generated code will be unsafe foreign calls // or tail calls. In either case we can safely assume no escape. if (const StoreInst *SI = dyn_cast<StoreInst>(I)) { // Check for escape: if (SpPointers.find(SI->getValueOperand()) != SpPointers.end()) { return true; } continue; #if 0 } else if (AtomicCmpXchgInst *ACXI = dyn_cast<AtomicCmpXchgInst>(I)) { // Check for escape: if (SpPointers.find(ACXI->getNewValOperand()) != SpPointers.end()) { return true; } continue; } else if (AtomicRMWInst *ARMWI = dyn_cast<AtomicRMWInst>(I)) { // Check for escape: if (SpPointers.find(ARMWI->getValOperand()) != SpPointers.end()) { return true; } continue; #endif } else if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) { if (SpPointers.find(GEPI->getPointerOperand()) == SpPointers.end()) { continue; } } else if (const SelectInst *SI = dyn_cast<SelectInst>(I)) { if ((SpPointers.find(SI->getTrueValue()) == SpPointers.end()) && (SpPointers.find(SI->getFalseValue()) == SpPointers.end())) { continue; } } else if (isa<PHINode>(I)) { if (!SomeOperandIsSPPointer(SpPointers, I)) continue; } else if (isa<BinaryOperator>(I)) { if (!SomeOperandIsSPPointer(SpPointers, I)) continue; } else if (isa<CastInst>(I)) { if (!SomeOperandIsSPPointer(SpPointers, I)) continue; } else { // Assume all other instructions do not define new SpPointers or avenues for escape. continue; } // We fall through to here if this instruction defines a new SpPointer: // add all the use sites to the work list. SpPointers.insert(I); for (Value::const_use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) { // There is nothing more to do if we have already decided that this defines a SpPointer if (SpPointers.find(*UI) == SpPointers.end()) { WorkList.insert(cast<Instruction>(*UI)); } } } return false; }