bool AliasAnalysis::canApplyDecrementRefCount(FullApplySite FAS, SILValue Ptr) { // Treat applications of @noreturn functions as decrementing ref counts. This // causes the apply to become a sink barrier for ref count increments. if (FAS.getCallee().getType().getAs<SILFunctionType>()->isNoReturn()) return true; /// If the pointer cannot escape to the function we are done. if (!EA->canEscapeTo(Ptr, FAS)) return false; SideEffectAnalysis::FunctionEffects ApplyEffects; SEA->getEffects(ApplyEffects, FAS); auto &GlobalEffects = ApplyEffects.getGlobalEffects(); if (ApplyEffects.mayReadRC() || GlobalEffects.mayRelease()) return true; /// The function has no unidentified releases, so let's look at the arguments // in detail. for (unsigned Idx = 0, End = FAS.getNumArguments(); Idx < End; ++Idx) { auto &ArgEffect = ApplyEffects.getParameterEffects()[Idx]; if (ArgEffect.mayRelease()) { // The function may release this argument, so check if the pointer can // escape to it. if (EA->canEscapeToValue(Ptr, FAS.getArgument(Idx))) return true; } } return false; }
/// Returns true if the \p MayWrites set contains any memory writes which may /// alias with any memory which is read by \p AI. static bool mayWriteTo(AliasAnalysis *AA, SideEffectAnalysis *SEA, WriteSet &MayWrites, ApplyInst *AI) { SideEffectAnalysis::FunctionEffects E; SEA->getEffects(E, AI); assert(E.getMemBehavior(RetainObserveKind::IgnoreRetains) <= SILInstruction::MemoryBehavior::MayRead && "apply should only read from memory"); if (E.getGlobalEffects().mayRead() && !MayWrites.empty()) { // We don't know which memory is read in the callee. Therefore we bail if // there are any writes in the loop. return true; } for (unsigned Idx = 0, End = AI->getNumArguments(); Idx < End; ++Idx) { auto &ArgEffect = E.getParameterEffects()[Idx]; if (!ArgEffect.mayRead()) continue; SILValue Arg = AI->getArgument(Idx); // Check if the memory addressed by the argument may alias any writes. for (auto *W : MayWrites) { if (AA->mayWriteToMemory(W, Arg)) { DEBUG(llvm::dbgs() << " mayWriteTo\n" << *W << " to " << *AI << "\n"); return true; } } } return false; }