KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(0) {}
void clear();
-
+
bool IsTrackingImpreciseReleases() {
return ReleaseMetadata != 0;
}
void SetSeq(Sequence NewSeq) {
DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
- Seq = NewSeq;
+ Seq = NewSeq;
}
Sequence GetSeq() const {
bool NestingDetected = false;
InstructionClass Class = GetInstructionClass(Inst);
const Value *Arg = 0;
-
+
DEBUG(dbgs() << "Class: " << Class << "\n");
-
+
switch (Class) {
case IC_Release: {
Arg = GetObjCArg(Inst);
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
- ANNOTATE_BOTTOMUP(Inst, Arg, OldSeq, S.GetSeq());
+ ANNOTATE_BOTTOMUP(Inst, Arg, OldSeq, S.GetSeq());
// A retain moving bottom up can be a use.
break;
}
MapVector<Value *, RRInfo> &Retains) {
DEBUG(dbgs() << "\n== ObjCARCOpt::VisitBottomUp ==\n");
-
+
bool NestingDetected = false;
BBState &MyStates = BBStates[BB];
PtrState &S = MyStates.getPtrTopDownState(Arg);
S.ClearKnownPositiveRefCount();
-
+
Sequence OldSeq = S.GetSeq();
-
+
MDNode *ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind);
-
+
switch (OldSeq) {
case S_Retain:
case S_CanRelease:
// Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanAlterRefCount: Seq: " << Seq << "; " << *Ptr
- << "\n");
+ << "\n");
S.ClearKnownPositiveRefCount();
switch (Seq) {
case S_Retain:
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
SmallVectorImpl<Instruction *> &DeadInsts,
- Module *M) {
+ Module *M) {
Type *ArgTy = Arg->getType();
Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext()));
-
+
DEBUG(dbgs() << "== ObjCARCOpt::MoveCalls ==\n");
-
+
// Insert the new retain and release calls.
for (SmallPtrSet<Instruction *, 2>::const_iterator
PI = ReleasesToMove.ReverseInsertPts.begin(),
DeadInsts.push_back(OrigRelease);
DEBUG(dbgs() << "Deleting release: " << *OrigRelease << "\n");
}
-
+
}
bool
/// Weak pointer optimizations.
void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeWeakCalls ==\n");
-
+
// First, do memdep-style RLE and S2L optimizations. We can't use memdep
// itself because it uses AliasAnalysis and we need to do provenance
// queries instead.
BB, Autorelease, DepInsts, Visited, PA);
if (DepInsts.size() != 1)
return 0;
-
+
CallInst *Retain =
dyn_cast_or_null<CallInst>(*DepInsts.begin());
-
+
// Check that we found a retain with the same argument.
if (!Retain ||
!IsRetain(GetBasicInstructionClass(Retain)) ||
GetObjCArg(Retain) != Arg) {
return 0;
}
-
+
return Retain;
}
BB, Ret, DepInsts, V, PA);
if (DepInsts.size() != 1)
return 0;
-
+
CallInst *Autorelease =
dyn_cast_or_null<CallInst>(*DepInsts.begin());
if (!Autorelease)
return 0;
if (GetObjCArg(Autorelease) != Arg)
return 0;
-
+
return Autorelease;
}
void ObjCARCOpt::OptimizeReturns(Function &F) {
if (!F.getReturnType()->isPointerTy())
return;
-
+
DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeReturns ==\n");
-
+
SmallPtrSet<Instruction *, 4> DependingInstructions;
SmallPtrSet<const BasicBlock *, 4> Visited;
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
if (!Ret)
continue;
-
+
const Value *Arg = StripPointerCastsAndObjCCalls(Ret->getOperand(0));
-
+
// Look for an ``autorelease'' instruction that is a predecssor of Ret and
// dependent on Arg such that there are no instructions dependent on Arg
// that need a positive ref count in between the autorelease and Ret.
if (Autorelease) {
DependingInstructions.clear();
Visited.clear();
-
+
CallInst *Retain =
FindPredecessorRetainWithSafePath(Arg, BB, Autorelease,
DependingInstructions, Visited, PA);
if (Retain) {
DependingInstructions.clear();
Visited.clear();
-
+
// Check that there is nothing that can affect the reference count
// between the retain and the call. Note that Retain need not be in BB.
if (HasSafePathToPredecessorCall(Arg, Retain, DependingInstructions,
}
}
}
-
+
DependingInstructions.clear();
Visited.clear();
}