bool swift:: mayGuaranteedUseValue(SILInstruction *User, SILValue Ptr, AliasAnalysis *AA) { // Only full apply sites can require a guaranteed lifetime. If we don't have // one, bail. if (!isa<FullApplySite>(User)) return false; FullApplySite FAS(User); // Ok, we have a full apply site. If the apply has no arguments, we don't need // to worry about any guaranteed parameters. if (!FAS.getNumArguments()) return false; // Ok, we have an apply site with arguments. Look at the function type and // iterate through the function parameters. If any of the parameters are // guaranteed, attempt to prove that the passed in parameter cannot alias // Ptr. If we fail, return true. CanSILFunctionType FType = FAS.getSubstCalleeType(); auto Params = FType->getParameters(); for (unsigned i : indices(Params)) { if (!Params[i].isGuaranteed()) continue; SILValue Op = FAS.getArgument(i); for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) if (!AA->isNoAlias(Op, SILValue(Ptr.getDef(), i))) return true; } // Ok, we were able to prove that all arguments to the apply that were // guaranteed do not alias Ptr. Return false. return false; }
static bool canApplyDecrementRefCount(OperandValueArrayRef Ops, SILValue Ptr, AliasAnalysis *AA) { // Ok, this apply *MAY* decrement ref counts. Now our strategy is to attempt // to use properties of the pointer, the function's arguments, and the // function itself to prove that the pointer cannot have its ref count // affected by the applied function. // TODO: Put in function property check section here when we get access to // such information. // First make sure that the underlying object of ptr is a local object which // does not escape. This prevents the apply from indirectly via the global // affecting the reference count of the pointer. if (!isNonEscapingLocalObject(getUnderlyingObject(Ptr))) return true; // Now that we know that the function can not affect the pointer indirectly, // make sure that the apply can not affect the pointer directly via the // applies arguments by proving that the pointer can not alias any of the // functions arguments. for (auto Op : Ops) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (!AA->isNoAlias(Op, SILValue(Ptr.getDef(), i))) return true; } } // Success! The apply inst can not affect the reference count of ptr! return false; }
bool swift::mayUseValue(SILInstruction *User, SILValue Ptr, AliasAnalysis *AA) { // If Inst is an instruction that we know can never use values with reference // semantics, return true. if (canNeverUseValues(User)) return false; // If the user is a load or a store and we can prove that it does not access // the object then return true. // Notice that we need to check all of the values of the object. if (isa<StoreInst>(User)) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (AA->mayWriteToMemory(User, SILValue(Ptr.getDef(), i))) return true; } return false; } if (isa<LoadInst>(User) ) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (AA->mayReadFromMemory(User, SILValue(Ptr.getDef(), i))) return true; } return false; } // If we have a terminator instruction, see if it can use ptr. This currently // means that we first show that TI cannot indirectly use Ptr and then use // alias analysis on the arguments. if (auto *TI = dyn_cast<TermInst>(User)) return canTerminatorUseValue(TI, Ptr, AA); // TODO: If we add in alias analysis support here for apply inst, we will need // to check that the pointer does not escape. // Otherwise, assume that Inst can use Target. return true; }