bool PAEval::runOnFunction(Function &F) { SetVector<Value *> Values; for (auto &Arg : F.args()) insertIfNamed(Values, &Arg); for (auto I = inst_begin(F), E = inst_end(F); I != E; ++I) { insertIfNamed(Values, &*I); for (auto &Op : I->operands()) insertIfNamed(Values, Op); } ProvenanceAnalysis PA; PA.setAA(&getAnalysis<AliasAnalysis>()); const DataLayout &DL = F.getParent()->getDataLayout(); for (Value *V1 : Values) { StringRef NameV1 = getName(V1); for (Value *V2 : Values) { StringRef NameV2 = getName(V2); if (NameV1 >= NameV2) continue; errs() << NameV1 << " and " << NameV2; if (PA.related(V1, V2, DL)) errs() << " are related.\n"; else errs() << " are not related.\n"; } } return false; }
/// Test whether the given instruction can result in a reference count /// modification (positive or negative) for the pointer's object. bool llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, InstructionClass Class) { switch (Class) { case IC_Autorelease: case IC_AutoreleaseRV: case IC_IntrinsicUser: case IC_User: // These operations never directly modify a reference count. return false; default: break; } ImmutableCallSite CS = static_cast<const Value *>(Inst); assert(CS && "Only calls can alter reference counts!"); // See if AliasAnalysis can help us with the call. AliasAnalysis::ModRefBehavior MRB = PA.getAA()->getModRefBehavior(CS); if (AliasAnalysis::onlyReadsMemory(MRB)) return false; if (AliasAnalysis::onlyAccessesArgPointees(MRB)) { for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) { const Value *Op = *I; if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) return true; } return false; } // Assume the worst. return true; }
/// Test whether the given instruction can "use" the given pointer's object in a /// way that requires the reference count to be positive. bool llvm::objcarc::CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, InstructionClass Class) { // IC_Call operations (as opposed to IC_CallOrUser) never "use" objc pointers. if (Class == IC_Call) return false; // Consider various instructions which may have pointer arguments which are // not "uses". if (const ICmpInst *ICI = dyn_cast<ICmpInst>(Inst)) { // Comparing a pointer with null, or any other constant, isn't really a use, // because we don't care what the pointer points to, or about the values // of any other dynamic reference-counted pointers. if (!IsPotentialRetainableObjPtr(ICI->getOperand(1), *PA.getAA())) return false; } else if (ImmutableCallSite CS = static_cast<const Value *>(Inst)) { // For calls, just check the arguments (and not the callee operand). for (ImmutableCallSite::arg_iterator OI = CS.arg_begin(), OE = CS.arg_end(); OI != OE; ++OI) { const Value *Op = *OI; if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) return true; } return false; } else if (const StoreInst *SI = dyn_cast<StoreInst>(Inst)) { // Special-case stores, because we don't care about the stored value, just // the store address. const Value *Op = GetUnderlyingObjCPtr(SI->getPointerOperand()); // If we can't tell what the underlying object was, assume there is a // dependence. return IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Op, Ptr); } // Check each operand for a match. for (User::const_op_iterator OI = Inst->op_begin(), OE = Inst->op_end(); OI != OE; ++OI) { const Value *Op = *OI; if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) return true; } return false; }