27 #define DEBUG_TYPE "objc-arc-opts"
45 using namespace llvm::objcarc;
53 template<
class KeyT,
class ValueT>
59 typedef std::vector<std::pair<KeyT, ValueT> > VectorTy;
64 typedef typename VectorTy::iterator iterator;
65 typedef typename VectorTy::const_iterator const_iterator;
67 iterator
end() {
return Vector.
end(); }
68 const_iterator
begin()
const {
return Vector.
begin(); }
69 const_iterator
end()
const {
return Vector.
end(); }
73 assert(Vector.size() >= Map.size());
74 for (
typename MapTy::const_iterator
I = Map.begin(), E = Map.end();
76 assert(
I->second < Vector.size());
77 assert(Vector[
I->second].first ==
I->first);
79 for (
typename VectorTy::const_iterator
I = Vector.begin(),
80 E = Vector.end();
I != E; ++
I)
82 (Map.count(
I->first) &&
83 Map[
I->first] == size_t(
I - Vector.begin())));
87 ValueT &operator[](
const KeyT &Arg) {
88 std::pair<typename MapTy::iterator, bool> Pair =
89 Map.insert(std::make_pair(Arg,
size_t(0)));
91 size_t Num = Vector.size();
92 Pair.first->second = Num;
93 Vector.push_back(std::make_pair(Arg, ValueT()));
94 return Vector[Num].second;
96 return Vector[Pair.first->second].second;
99 std::pair<iterator, bool>
100 insert(
const std::pair<KeyT, ValueT> &InsertPair) {
101 std::pair<typename MapTy::iterator, bool> Pair =
102 Map.insert(std::make_pair(InsertPair.first,
size_t(0)));
104 size_t Num = Vector.size();
105 Pair.first->second = Num;
106 Vector.push_back(InsertPair);
107 return std::make_pair(Vector.begin() + Num,
true);
109 return std::make_pair(Vector.begin() + Pair.first->second,
false);
112 iterator find(
const KeyT &Key) {
113 typename MapTy::iterator It = Map.find(Key);
114 if (It == Map.end())
return Vector.end();
115 return Vector.begin() + It->second;
118 const_iterator find(
const KeyT &Key)
const {
119 typename MapTy::const_iterator It = Map.find(Key);
120 if (It == Map.end())
return Vector.end();
121 return Vector.begin() + It->second;
127 void blot(
const KeyT &Key) {
128 typename MapTy::iterator It = Map.find(Key);
129 if (It == Map.end())
return;
130 Vector[It->second].first =
KeyT();
150 if (
const BitCastInst *BC = dyn_cast<BitCastInst>(Arg))
153 if (GEP->hasAllZeroIndices())
157 cast<CallInst>(Arg)->getArgOperand(0));
190 if (isa<AllocaInst>(P))
196 if (
const SelectInst *SI = dyn_cast<const SelectInst>(P)) {
202 if (
const PHINode *PN = dyn_cast<const PHINode>(P)) {
203 for (
unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
204 Worklist.
push_back(PN->getIncomingValue(i));
207 }
while (!Worklist.
empty());
256 STATISTIC(NumNoops,
"Number of no-op objc calls eliminated");
257 STATISTIC(NumPartialNoops,
"Number of partially no-op objc calls eliminated");
258 STATISTIC(NumAutoreleases,
"Number of autoreleases converted to releases");
259 STATISTIC(NumRets,
"Number of return value forwarding "
260 "retain+autoreleases eliminated");
261 STATISTIC(NumRRs,
"Number of retain+release paths eliminated");
262 STATISTIC(NumPeeps,
"Number of calls peephole-optimized");
265 "Number of retains before optimization");
267 "Number of releases before optimization");
269 "Number of retains after optimization");
271 "Number of releases after optimization");
294 return OS <<
"S_None";
296 return OS <<
"S_Retain";
298 return OS <<
"S_CanRelease";
300 return OS <<
"S_Use";
302 return OS <<
"S_Release";
303 case S_MovableRelease:
304 return OS <<
"S_MovableRelease";
306 return OS <<
"S_Stop";
316 if (A == S_None || B == S_None)
322 if ((A == S_Retain || A == S_CanRelease) &&
323 (B == S_CanRelease || B == S_Use))
327 if ((A == S_Use || A == S_CanRelease) &&
328 (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
331 if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
333 if (A == S_Release && B == S_MovableRelease)
360 bool IsTailCallRelease;
376 bool CFGHazardAfflicted;
379 KnownSafe(
false), IsTailCallRelease(
false), ReleaseMetadata(0),
380 CFGHazardAfflicted(
false) {}
386 bool Merge(
const RRInfo &Other);
391 void RRInfo::clear() {
393 IsTailCallRelease =
false;
396 ReverseInsertPts.clear();
397 CFGHazardAfflicted =
false;
400 bool RRInfo::Merge(
const RRInfo &Other) {
402 if (ReleaseMetadata != Other.ReleaseMetadata)
406 KnownSafe &= Other.KnownSafe;
407 IsTailCallRelease &= Other.IsTailCallRelease;
408 CFGHazardAfflicted |= Other.CFGHazardAfflicted;
411 Calls.insert(Other.Calls.begin(), Other.Calls.end());
415 bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
417 I = Other.ReverseInsertPts.begin(),
418 E = Other.ReverseInsertPts.end();
I != E; ++
I)
419 Partial |= ReverseInsertPts.insert(*
I);
428 bool KnownPositiveRefCount;
441 PtrState() : KnownPositiveRefCount(
false), Partial(
false),
445 bool IsKnownSafe()
const {
446 return RRI.KnownSafe;
449 void SetKnownSafe(
const bool NewValue) {
450 RRI.KnownSafe = NewValue;
453 bool IsTailCallRelease()
const {
454 return RRI.IsTailCallRelease;
457 void SetTailCallRelease(
const bool NewValue) {
458 RRI.IsTailCallRelease = NewValue;
461 bool IsTrackingImpreciseReleases()
const {
462 return RRI.ReleaseMetadata != 0;
465 const MDNode *GetReleaseMetadata()
const {
466 return RRI.ReleaseMetadata;
469 void SetReleaseMetadata(
MDNode *NewValue) {
470 RRI.ReleaseMetadata = NewValue;
473 bool IsCFGHazardAfflicted()
const {
474 return RRI.CFGHazardAfflicted;
477 void SetCFGHazardAfflicted(
const bool NewValue) {
478 RRI.CFGHazardAfflicted = NewValue;
481 void SetKnownPositiveRefCount() {
482 DEBUG(
dbgs() <<
"Setting Known Positive.\n");
483 KnownPositiveRefCount =
true;
486 void ClearKnownPositiveRefCount() {
487 DEBUG(
dbgs() <<
"Clearing Known Positive.\n");
488 KnownPositiveRefCount =
false;
491 bool HasKnownPositiveRefCount()
const {
492 return KnownPositiveRefCount;
496 DEBUG(
dbgs() <<
"Old: " << Seq <<
"; New: " << NewSeq <<
"\n");
504 void ClearSequenceProgress() {
505 ResetSequenceProgress(S_None);
508 void ResetSequenceProgress(
Sequence NewSeq) {
509 DEBUG(
dbgs() <<
"Resetting sequence progress.\n");
515 void Merge(
const PtrState &Other,
bool TopDown);
522 RRI.ReverseInsertPts.insert(I);
525 void ClearReverseInsertPts() {
526 RRI.ReverseInsertPts.clear();
529 bool HasReverseInsertPts()
const {
530 return !RRI.ReverseInsertPts.empty();
533 const RRInfo &GetRRInfo()
const {
540 PtrState::Merge(
const PtrState &Other,
bool TopDown) {
541 Seq =
MergeSeqs(Seq, Other.Seq, TopDown);
542 KnownPositiveRefCount &= Other.KnownPositiveRefCount;
548 }
else if (Partial || Other.Partial) {
553 ClearSequenceProgress();
559 Partial = RRI.Merge(Other.RRI);
568 unsigned TopDownPathCount;
571 unsigned BottomUpPathCount;
582 MapTy PerPtrBottomUp;
592 static const unsigned OverflowOccurredValue;
594 BBState() : TopDownPathCount(0), BottomUpPathCount(0) { }
596 typedef MapTy::iterator ptr_iterator;
597 typedef MapTy::const_iterator ptr_const_iterator;
599 ptr_iterator top_down_ptr_begin() {
return PerPtrTopDown.begin(); }
600 ptr_iterator top_down_ptr_end() {
return PerPtrTopDown.end(); }
601 ptr_const_iterator top_down_ptr_begin()
const {
602 return PerPtrTopDown.begin();
604 ptr_const_iterator top_down_ptr_end()
const {
605 return PerPtrTopDown.end();
608 ptr_iterator bottom_up_ptr_begin() {
return PerPtrBottomUp.begin(); }
609 ptr_iterator bottom_up_ptr_end() {
return PerPtrBottomUp.end(); }
610 ptr_const_iterator bottom_up_ptr_begin()
const {
611 return PerPtrBottomUp.begin();
613 ptr_const_iterator bottom_up_ptr_end()
const {
614 return PerPtrBottomUp.end();
619 void SetAsEntry() { TopDownPathCount = 1; }
623 void SetAsExit() { BottomUpPathCount = 1; }
628 PtrState &getPtrTopDownState(
const Value *Arg) {
629 return PerPtrTopDown[Arg];
635 PtrState &getPtrBottomUpState(
const Value *Arg) {
636 return PerPtrBottomUp[Arg];
641 ptr_iterator findPtrBottomUpState(
const Value *Arg) {
642 return PerPtrBottomUp.find(Arg);
645 void clearBottomUpPointers() {
646 PerPtrBottomUp.clear();
649 void clearTopDownPointers() {
650 PerPtrTopDown.clear();
653 void InitFromPred(
const BBState &Other);
654 void InitFromSucc(
const BBState &Other);
655 void MergePred(
const BBState &Other);
656 void MergeSucc(
const BBState &Other);
664 bool GetAllPathCountWithOverflow(
unsigned &PathCount)
const {
665 if (TopDownPathCount == OverflowOccurredValue ||
666 BottomUpPathCount == OverflowOccurredValue)
668 unsigned long long Product =
669 (
unsigned long long)TopDownPathCount*BottomUpPathCount;
672 return (Product >> 32) ||
673 ((PathCount = Product) == OverflowOccurredValue);
678 edge_iterator
pred_begin()
const {
return Preds.begin(); }
679 edge_iterator
pred_end()
const {
return Preds.end(); }
680 edge_iterator
succ_begin()
const {
return Succs.begin(); }
681 edge_iterator
succ_end()
const {
return Succs.end(); }
683 void addSucc(
BasicBlock *Succ) { Succs.push_back(Succ); }
684 void addPred(
BasicBlock *Pred) { Preds.push_back(Pred); }
686 bool isExit()
const {
return Succs.empty(); }
689 const unsigned BBState::OverflowOccurredValue = 0xffffffff;
692 void BBState::InitFromPred(
const BBState &Other) {
693 PerPtrTopDown = Other.PerPtrTopDown;
694 TopDownPathCount = Other.TopDownPathCount;
697 void BBState::InitFromSucc(
const BBState &Other) {
698 PerPtrBottomUp = Other.PerPtrBottomUp;
699 BottomUpPathCount = Other.BottomUpPathCount;
704 void BBState::MergePred(
const BBState &Other) {
705 if (TopDownPathCount == OverflowOccurredValue)
710 TopDownPathCount += Other.TopDownPathCount;
715 if (TopDownPathCount == OverflowOccurredValue) {
716 clearTopDownPointers();
722 if (TopDownPathCount < Other.TopDownPathCount) {
723 TopDownPathCount = OverflowOccurredValue;
724 clearTopDownPointers();
731 for (ptr_const_iterator
MI = Other.top_down_ptr_begin(),
732 ME = Other.top_down_ptr_end();
MI != ME; ++
MI) {
733 std::pair<ptr_iterator, bool> Pair = PerPtrTopDown.insert(*
MI);
734 Pair.first->second.Merge(Pair.second ? PtrState() :
MI->second,
740 for (ptr_iterator
MI = top_down_ptr_begin(),
741 ME = top_down_ptr_end();
MI != ME; ++
MI)
742 if (Other.PerPtrTopDown.find(
MI->first) == Other.PerPtrTopDown.end())
743 MI->second.Merge(PtrState(),
true);
748 void BBState::MergeSucc(
const BBState &Other) {
749 if (BottomUpPathCount == OverflowOccurredValue)
754 BottomUpPathCount += Other.BottomUpPathCount;
759 if (BottomUpPathCount == OverflowOccurredValue) {
760 clearBottomUpPointers();
766 if (BottomUpPathCount < Other.BottomUpPathCount) {
767 BottomUpPathCount = OverflowOccurredValue;
768 clearBottomUpPointers();
775 for (ptr_const_iterator
MI = Other.bottom_up_ptr_begin(),
776 ME = Other.bottom_up_ptr_end();
MI != ME; ++
MI) {
777 std::pair<ptr_iterator, bool> Pair = PerPtrBottomUp.insert(*
MI);
778 Pair.first->second.Merge(Pair.second ? PtrState() :
MI->second,
784 for (ptr_iterator
MI = bottom_up_ptr_begin(),
785 ME = bottom_up_ptr_end();
MI != ME; ++
MI)
786 if (Other.PerPtrBottomUp.find(
MI->first) == Other.PerPtrBottomUp.end())
787 MI->second.Merge(PtrState(),
false);
793 #define ARC_ANNOTATIONS
799 #ifdef ARC_ANNOTATIONS
806 cl::desc(
"Enable emission of arc data flow analysis "
810 cl::desc(
"Disable check for cfg hazards when "
815 cl::desc(
"filter out all data flow annotations "
816 "but those that apply to the given "
817 "target llvm identifier."));
830 if (
Instruction *Inst = dyn_cast<Instruction>(Ptr)) {
832 if (!(Node = Inst->getMetadata(NodeId))) {
842 os <<
"(" << Inst->getParent()->getParent()->getName() <<
",%"
843 << Inst->getName() <<
")";
846 Inst->setMetadata(NodeId,
MDNode::get(Inst->getContext(),Hash));
850 "An ARCAnnotationProvenanceSourceMDKind can only have 1 operand.");
853 }
else if (
Argument *Arg = dyn_cast<Argument>(Ptr)) {
856 os <<
"(" << Arg->getParent()->
getName() <<
",%" << Arg->
getName()
887 Value *tmp[3] = {PtrSourceMDNodeID,
912 Type *Params[] = {I8XX, I8XX};
923 Value *ActualPtrName = Builder.CreateGlobalStringPtr(Tmp,
926 cast<Constant>(ActualPtrName), Tmp);
932 Value *ActualPtrName = Builder.CreateGlobalStringPtr(SeqStr,
935 cast<Constant>(ActualPtrName), SeqStr);
938 Builder.CreateCall2(Callee, PtrName, S);
955 Type *Params[] = {I8XX, I8XX};
969 cast<Constant>(ActualPtrName), Tmp);
978 cast<Constant>(ActualPtrName), SeqStr);
1025 #define ANNOTATE_BOTTOMUP(inst, ptr, old, new) \
1026 GenerateARCAnnotation(ARCAnnotationBottomUpMDKind, \
1027 ARCAnnotationProvenanceSourceMDKind, (inst), \
1028 const_cast<Value*>(ptr), (old), (new))
1031 #define ANNOTATE_TOPDOWN(inst, ptr, old, new) \
1032 GenerateARCAnnotation(ARCAnnotationTopDownMDKind, \
1033 ARCAnnotationProvenanceSourceMDKind, (inst), \
1034 const_cast<Value*>(ptr), (old), (new))
1036 #define ANNOTATE_BB(_states, _bb, _name, _type, _direction) \
1038 if (EnableARCAnnotations) { \
1039 for(BBState::ptr_const_iterator I = (_states)._direction##_ptr_begin(), \
1040 E = (_states)._direction##_ptr_end(); I != E; ++I) { \
1041 Value *Ptr = const_cast<Value*>(I->first); \
1042 Sequence Seq = I->second.GetSeq(); \
1043 GenerateARCBB ## _type ## Annotation(_name, (_bb), Ptr, Seq); \
1048 #define ANNOTATE_BOTTOMUP_BBSTART(_states, _basicblock) \
1049 ANNOTATE_BB(_states, _basicblock, "llvm.arc.annotation.bottomup.bbstart", \
1050 Entrance, bottom_up)
1051 #define ANNOTATE_BOTTOMUP_BBEND(_states, _basicblock) \
1052 ANNOTATE_BB(_states, _basicblock, "llvm.arc.annotation.bottomup.bbend", \
1053 Terminator, bottom_up)
1054 #define ANNOTATE_TOPDOWN_BBSTART(_states, _basicblock) \
1055 ANNOTATE_BB(_states, _basicblock, "llvm.arc.annotation.topdown.bbstart", \
1057 #define ANNOTATE_TOPDOWN_BBEND(_states, _basicblock) \
1058 ANNOTATE_BB(_states, _basicblock, "llvm.arc.annotation.topdown.bbend", \
1059 Terminator, top_down)
1061 #else // !ARC_ANNOTATION
1063 #define ANNOTATE_BOTTOMUP(inst, ptr, old, new)
1064 #define ANNOTATE_TOPDOWN(inst, ptr, old, new)
1065 #define ANNOTATE_BOTTOMUP_BBSTART(states, basicblock)
1066 #define ANNOTATE_BOTTOMUP_BBEND(states, basicblock)
1067 #define ANNOTATE_TOPDOWN_BBSTART(states, basicblock)
1068 #define ANNOTATE_TOPDOWN_BBEND(states, basicblock)
1069 #endif // !ARC_ANNOTATION
1086 unsigned UsedInThisFunction;
1089 unsigned ImpreciseReleaseMDKind;
1092 unsigned CopyOnEscapeMDKind;
1095 unsigned NoObjCARCExceptionsMDKind;
1097 #ifdef ARC_ANNOTATIONS
1099 unsigned ARCAnnotationBottomUpMDKind;
1101 unsigned ARCAnnotationTopDownMDKind;
1103 unsigned ARCAnnotationProvenanceSourceMDKind;
1104 #endif // ARC_ANNOATIONS
1109 void OptimizeIndividualCalls(
Function &F);
1111 void CheckForCFGHazards(
const BasicBlock *BB,
1113 BBState &MyStates)
const;
1132 void MoveCalls(
Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove,
1145 RRInfo &RetainsToMove,
1146 RRInfo &ReleasesToMove,
1149 bool &AnyPairsCompletelyEliminated);
1156 void OptimizeWeakCalls(
Function &F);
1158 bool OptimizeSequences(
Function &F);
1163 void GatherStatistics(
Function &F,
bool AfterOptimization =
false);
1167 virtual bool doInitialization(
Module &M);
1168 virtual bool runOnFunction(
Function &F);
1169 virtual void releaseMemory();
1181 "objc-arc",
"ObjC ARC optimization",
false,
false)
1187 return new ObjCARCOpt();
1190 void ObjCARCOpt::getAnalysisUsage(
AnalysisUsage &AU)
const {
1210 if (&*I == RetainRV)
1214 if (II->getNormalDest() == RetainRVParent) {
1217 if (&*I == RetainRV)
1233 DEBUG(
dbgs() <<
"Erasing autoreleaseRV,retainRV pair: " << *I <<
"\n"
1234 <<
"Erasing " << *RetainRV <<
"\n");
1246 DEBUG(
dbgs() <<
"Transforming objc_retainAutoreleasedReturnValue => "
1247 "objc_retain since the operand is not a return value.\n"
1248 "Old = " << *RetainRV <<
"\n");
1251 cast<CallInst>(RetainRV)->setCalledFunction(NewDecl);
1253 DEBUG(
dbgs() <<
"New = " << *RetainRV <<
"\n");
1271 const User *I = *UI;
1274 if (isa<BitCastInst>(I))
1277 }
while (!Users.
empty());
1282 DEBUG(
dbgs() <<
"Transforming objc_autoreleaseReturnValue => "
1283 "objc_autorelease since its operand is not used as a return "
1285 "Old = " << *AutoreleaseRV <<
"\n");
1287 CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV);
1293 DEBUG(
dbgs() <<
"New: " << *AutoreleaseRV <<
"\n");
1299 void ObjCARCOpt::OptimizeIndividualCalls(
Function &F) {
1300 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::OptimizeIndividualCalls ==\n");
1302 UsedInThisFunction = 0;
1310 DEBUG(
dbgs() <<
"Visiting: Class: " << Class <<
"; " << *Inst <<
"\n");
1326 DEBUG(
dbgs() <<
"Erasing no-op cast: " << *Inst <<
"\n");
1336 CallInst *CI = cast<CallInst>(Inst);
1344 DEBUG(
dbgs() <<
"A null pointer-to-weak-pointer is undefined behavior."
1345 "\nOld = " << *CI <<
"\nNew = " << *NewValue <<
"\n");
1354 CallInst *CI = cast<CallInst>(Inst);
1364 DEBUG(
dbgs() <<
"A null pointer-to-weak-pointer is undefined behavior."
1365 "\nOld = " << *CI <<
"\nNew = " << *NewValue <<
"\n");
1374 if (OptimizeRetainRVCall(F, Inst))
1378 OptimizeAutoreleaseRVCall(F, Inst, Class);
1399 DEBUG(
dbgs() <<
"Replacing autorelease{,RV}(x) with objc_release(x) "
1400 "since x is otherwise unused.\nOld: " << *Call <<
"\nNew: "
1401 << *NewCall <<
"\n");
1413 DEBUG(
dbgs() <<
"Adding tail keyword to function since it can never be "
1414 "passed stack args: " << *Inst <<
"\n");
1415 cast<CallInst>(Inst)->setTailCall();
1422 DEBUG(
dbgs() <<
"Removing tail keyword from function: " << *Inst <<
1424 cast<CallInst>(Inst)->setTailCall(
false);
1430 DEBUG(
dbgs() <<
"Found no throw class. Setting nounwind on: " << *Inst
1432 cast<CallInst>(Inst)->setDoesNotThrow();
1436 UsedInThisFunction |= 1 <<
Class;
1446 DEBUG(
dbgs() <<
"ARC calls with null are no-ops. Erasing: " << *Inst
1454 UsedInThisFunction |= 1 <<
Class;
1462 Worklist.
push_back(std::make_pair(Inst, Arg));
1464 std::pair<Instruction *, const Value *> Pair = Worklist.
pop_back_val();
1473 bool HasNull =
false;
1474 bool HasCriticalEdges =
false;
1481 .getNumSuccessors() != 1) {
1482 HasCriticalEdges =
true;
1487 if (!HasCriticalEdges && HasNull) {
1503 DependingInstructions, Visited, PA);
1509 DependingInstructions, Visited, PA);
1522 if (DependingInstructions.size() == 1 &&
1523 *DependingInstructions.begin() == PN) {
1527 CallInst *CInst = cast<CallInst>(Inst);
1536 if (Op->getType() != ParamTy)
1543 "And inserting clone at " << *InsertPos <<
"\n");
1544 Worklist.
push_back(std::make_pair(Clone, Incoming));
1548 DEBUG(
dbgs() <<
"Erasing: " << *CInst <<
"\n");
1553 }
while (!Worklist.
empty());
1560 const bool SuccSRRIKnownSafe,
1562 bool &SomeSuccHasSame,
1563 bool &AllSuccsHaveSame,
1564 bool &NotAllSeqEqualButKnownSafe,
1565 bool &ShouldContinue) {
1567 case S_CanRelease: {
1568 if (!S.IsKnownSafe() && !SuccSRRIKnownSafe) {
1569 S.ClearSequenceProgress();
1572 S.SetCFGHazardAfflicted(
true);
1573 ShouldContinue =
true;
1577 SomeSuccHasSame =
true;
1581 case S_MovableRelease:
1582 if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)
1583 AllSuccsHaveSame =
false;
1585 NotAllSeqEqualButKnownSafe =
true;
1598 const bool SuccSRRIKnownSafe,
1600 bool &SomeSuccHasSame,
1601 bool &AllSuccsHaveSame,
1602 bool &NotAllSeqEqualButKnownSafe) {
1605 SomeSuccHasSame =
true;
1609 case S_MovableRelease:
1611 if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)
1612 AllSuccsHaveSame =
false;
1614 NotAllSeqEqualButKnownSafe =
true;
1627 ObjCARCOpt::CheckForCFGHazards(
const BasicBlock *BB,
1629 BBState &MyStates)
const {
1632 for (BBState::ptr_iterator I = MyStates.top_down_ptr_begin(),
1633 E = MyStates.top_down_ptr_end(); I != E; ++
I) {
1634 PtrState &S = I->second;
1635 const Sequence Seq = I->second.GetSeq();
1643 assert((Seq == S_Retain || Seq == S_CanRelease || Seq == S_Use) &&
1644 "Unknown top down sequence state.");
1646 const Value *Arg = I->first;
1648 bool SomeSuccHasSame =
false;
1649 bool AllSuccsHaveSame =
true;
1650 bool NotAllSeqEqualButKnownSafe =
false;
1654 for (; SI != SE; ++SI) {
1659 assert(BBI != BBStates.
end());
1660 const PtrState &SuccS = BBI->second.getPtrBottomUpState(Arg);
1661 const Sequence SuccSSeq = SuccS.GetSeq();
1668 if (SuccSSeq == S_None) {
1669 S.ClearSequenceProgress();
1675 const bool SuccSRRIKnownSafe = SuccS.IsKnownSafe();
1679 switch(S.GetSeq()) {
1681 bool ShouldContinue =
false;
1683 AllSuccsHaveSame, NotAllSeqEqualButKnownSafe,
1689 case S_CanRelease: {
1691 SomeSuccHasSame, AllSuccsHaveSame,
1692 NotAllSeqEqualButKnownSafe);
1699 case S_MovableRelease:
1707 if (SomeSuccHasSame && !AllSuccsHaveSame) {
1708 S.ClearSequenceProgress();
1709 }
else if (NotAllSeqEqualButKnownSafe) {
1714 S.SetCFGHazardAfflicted(
true);
1720 ObjCARCOpt::VisitInstructionBottomUp(
Instruction *Inst,
1723 BBState &MyStates) {
1724 bool NestingDetected =
false;
1726 const Value *Arg = 0;
1728 DEBUG(
dbgs() <<
"Class: " << Class <<
"\n");
1734 PtrState &S = MyStates.getPtrBottomUpState(Arg);
1743 if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease) {
1744 DEBUG(
dbgs() <<
"Found nested releases (i.e. a release pair)\n");
1745 NestingDetected =
true;
1749 Sequence NewSeq = ReleaseMetadata ? S_MovableRelease : S_Release;
1751 S.ResetSequenceProgress(NewSeq);
1752 S.SetReleaseMetadata(ReleaseMetadata);
1753 S.SetKnownSafe(S.HasKnownPositiveRefCount());
1754 S.SetTailCallRelease(cast<CallInst>(Inst)->isTailCall());
1756 S.SetKnownPositiveRefCount();
1768 PtrState &S = MyStates.getPtrBottomUpState(Arg);
1769 S.SetKnownPositiveRefCount();
1775 case S_MovableRelease:
1779 if (OldSeq != S_Use || S.IsTrackingImpreciseReleases())
1780 S.ClearReverseInsertPts();
1786 Retains[Inst] = S.GetRRInfo();
1787 S.ClearSequenceProgress();
1800 MyStates.clearBottomUpPointers();
1801 return NestingDetected;
1805 return NestingDetected;
1819 if (
StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
1821 BBState::ptr_iterator I = MyStates.findPtrBottomUpState(
1823 if (I != MyStates.bottom_up_ptr_end())
1824 MultiOwnersSet.insert(I->first);
1834 for (BBState::ptr_iterator
MI = MyStates.bottom_up_ptr_begin(),
1835 ME = MyStates.bottom_up_ptr_end();
MI != ME; ++
MI) {
1839 PtrState &S =
MI->second;
1844 DEBUG(
dbgs() <<
"CanAlterRefCount: Seq: " << Seq <<
"; " << *Ptr
1846 S.ClearKnownPositiveRefCount();
1849 S.SetSeq(S_CanRelease);
1854 case S_MovableRelease:
1866 case S_MovableRelease:
1867 if (
CanUse(Inst, Ptr, PA, Class)) {
1868 DEBUG(
dbgs() <<
"CanUse: Seq: " << Seq <<
"; " << *Ptr
1870 assert(!S.HasReverseInsertPts());
1874 if (isa<InvokeInst>(Inst))
1880 }
else if (Seq == S_Release &&
IsUser(Class)) {
1881 DEBUG(
dbgs() <<
"PreciseReleaseUse: Seq: " << Seq <<
"; " << *Ptr
1886 assert(!S.HasReverseInsertPts());
1888 if (isa<InvokeInst>(Inst))
1895 if (
CanUse(Inst, Ptr, PA, Class)) {
1896 DEBUG(
dbgs() <<
"PreciseStopUse: Seq: " << Seq <<
"; " << *Ptr
1911 return NestingDetected;
1919 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::VisitBottomUp ==\n");
1921 bool NestingDetected =
false;
1922 BBState &MyStates = BBStates[BB];
1926 BBState::edge_iterator SI(MyStates.succ_begin()),
1927 SE(MyStates.succ_end());
1931 assert(I != BBStates.
end());
1932 MyStates.InitFromSucc(I->second);
1934 for (; SI != SE; ++SI) {
1936 I = BBStates.
find(Succ);
1937 assert(I != BBStates.
end());
1938 MyStates.MergeSucc(I->second);
1951 if (isa<InvokeInst>(Inst))
1954 DEBUG(
dbgs() <<
"Visiting " << *Inst <<
"\n");
1956 NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);
1962 for (BBState::edge_iterator PI(MyStates.pred_begin()),
1963 PE(MyStates.pred_end()); PI != PE; ++PI) {
1966 NestingDetected |= VisitInstructionBottomUp(II, BB, Retains, MyStates);
1973 return NestingDetected;
1977 ObjCARCOpt::VisitInstructionTopDown(
Instruction *Inst,
1979 BBState &MyStates) {
1980 bool NestingDetected =
false;
1982 const Value *Arg = 0;
1994 PtrState &S = MyStates.getPtrTopDownState(Arg);
2006 if (S.GetSeq() == S_Retain)
2007 NestingDetected =
true;
2010 S.ResetSequenceProgress(S_Retain);
2011 S.SetKnownSafe(S.HasKnownPositiveRefCount());
2015 S.SetKnownPositiveRefCount();
2024 PtrState &S = MyStates.getPtrTopDownState(Arg);
2025 S.ClearKnownPositiveRefCount();
2034 if (OldSeq == S_Retain || ReleaseMetadata != 0)
2035 S.ClearReverseInsertPts();
2038 S.SetReleaseMetadata(ReleaseMetadata);
2039 S.SetTailCallRelease(cast<CallInst>(Inst)->isTailCall());
2040 Releases[Inst] = S.GetRRInfo();
2042 S.ClearSequenceProgress();
2048 case S_MovableRelease:
2055 MyStates.clearTopDownPointers();
2056 return NestingDetected;
2060 return NestingDetected;
2067 for (BBState::ptr_iterator
MI = MyStates.top_down_ptr_begin(),
2068 ME = MyStates.top_down_ptr_end();
MI != ME; ++
MI) {
2072 PtrState &S =
MI->second;
2077 DEBUG(
dbgs() <<
"CanAlterRefCount: Seq: " << Seq <<
"; " << *Ptr
2079 S.ClearKnownPositiveRefCount();
2082 S.SetSeq(S_CanRelease);
2084 assert(!S.HasReverseInsertPts());
2085 S.InsertReverseInsertPt(Inst);
2097 case S_MovableRelease:
2105 if (
CanUse(Inst, Ptr, PA, Class)) {
2106 DEBUG(
dbgs() <<
"CanUse: Seq: " << Seq <<
"; " << *Ptr
2118 case S_MovableRelease:
2123 return NestingDetected;
2130 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::VisitTopDown ==\n");
2131 bool NestingDetected =
false;
2132 BBState &MyStates = BBStates[BB];
2136 BBState::edge_iterator PI(MyStates.pred_begin()),
2137 PE(MyStates.pred_end());
2141 assert(I != BBStates.
end());
2142 MyStates.InitFromPred(I->second);
2144 for (; PI != PE; ++PI) {
2146 I = BBStates.
find(Pred);
2147 assert(I != BBStates.
end());
2148 MyStates.MergePred(I->second);
2160 DEBUG(
dbgs() <<
"Visiting " << *Inst <<
"\n");
2162 NestingDetected |= VisitInstructionTopDown(Inst, Releases, MyStates);
2169 #ifdef ARC_ANNOTATIONS
2172 CheckForCFGHazards(BB, BBStates, MyStates);
2173 return NestingDetected;
2180 unsigned NoObjCARCExceptionsMDKind,
2192 BBState &MyStates = BBStates[EntryBB];
2193 MyStates.SetAsEntry();
2204 while (SuccStack.
back().second != SE) {
2206 if (Visited.
insert(SuccBB)) {
2209 BBStates[CurrBB].addSucc(SuccBB);
2210 BBState &SuccStates = BBStates[SuccBB];
2211 SuccStates.addPred(CurrBB);
2216 if (!OnStack.
count(SuccBB)) {
2217 BBStates[CurrBB].addSucc(SuccBB);
2218 BBStates[SuccBB].addPred(CurrBB);
2221 OnStack.
erase(CurrBB);
2224 }
while (!SuccStack.
empty());
2234 BBState &MyStates = BBStates[ExitBB];
2235 if (!MyStates.isExit())
2238 MyStates.SetAsExit();
2240 PredStack.
push_back(std::make_pair(ExitBB, MyStates.pred_begin()));
2242 while (!PredStack.
empty()) {
2243 reverse_dfs_next_succ:
2244 BBState::edge_iterator PE = BBStates[PredStack.
back().first].pred_end();
2245 while (PredStack.
back().second != PE) {
2247 if (Visited.
insert(BB)) {
2249 goto reverse_dfs_next_succ;
2272 NoObjCARCExceptionsMDKind,
2276 bool BottomUpNestingDetected =
false;
2278 ReverseCFGPostOrder.
rbegin(), E = ReverseCFGPostOrder.
rend();
2280 BottomUpNestingDetected |= VisitBottomUp(*I, BBStates, Retains);
2283 bool TopDownNestingDetected =
false;
2287 TopDownNestingDetected |= VisitTopDown(*I, BBStates, Releases);
2289 return TopDownNestingDetected && BottomUpNestingDetected;
2293 void ObjCARCOpt::MoveCalls(
Value *Arg,
2294 RRInfo &RetainsToMove,
2295 RRInfo &ReleasesToMove,
2303 DEBUG(
dbgs() <<
"== ObjCARCOpt::MoveCalls ==\n");
2307 PI = ReleasesToMove.ReverseInsertPts.begin(),
2308 PE = ReleasesToMove.ReverseInsertPts.end(); PI != PE; ++PI) {
2310 Value *MyArg = ArgTy == ParamTy ? Arg :
2317 DEBUG(
dbgs() <<
"Inserting new Retain: " << *Call <<
"\n"
2318 "At insertion point: " << *InsertPt <<
"\n");
2321 PI = RetainsToMove.ReverseInsertPts.begin(),
2322 PE = RetainsToMove.ReverseInsertPts.end(); PI != PE; ++PI) {
2324 Value *MyArg = ArgTy == ParamTy ? Arg :
2329 if (
MDNode *M = ReleasesToMove.ReleaseMetadata)
2332 if (ReleasesToMove.IsTailCallRelease)
2335 DEBUG(
dbgs() <<
"Inserting new Release: " << *Call <<
"\n"
2336 "At insertion point: " << *InsertPt <<
"\n");
2341 AI = RetainsToMove.Calls.begin(),
2342 AE = RetainsToMove.Calls.end(); AI != AE; ++AI) {
2344 Retains.blot(OrigRetain);
2346 DEBUG(
dbgs() <<
"Deleting retain: " << *OrigRetain <<
"\n");
2349 AI = ReleasesToMove.Calls.begin(),
2350 AE = ReleasesToMove.Calls.end(); AI != AE; ++AI) {
2352 Releases.
erase(OrigRelease);
2354 DEBUG(
dbgs() <<
"Deleting release: " << *OrigRelease <<
"\n");
2368 RRInfo &RetainsToMove,
2369 RRInfo &ReleasesToMove,
2372 bool &AnyPairsCompletelyEliminated) {
2376 bool KnownSafeTD =
true, KnownSafeBU =
true;
2377 bool MultipleOwners =
false;
2378 bool CFGHazardAfflicted =
false;
2384 unsigned OldDelta = 0;
2385 unsigned NewDelta = 0;
2386 unsigned OldCount = 0;
2387 unsigned NewCount = 0;
2388 bool FirstRelease =
true;
2391 NI = NewRetains.
begin(),
NE = NewRetains.
end(); NI !=
NE; ++NI) {
2393 MapVector<Value *, RRInfo>::const_iterator It = Retains.
find(NewRetain);
2394 assert(It != Retains.
end());
2395 const RRInfo &NewRetainRRI = It->second;
2396 KnownSafeTD &= NewRetainRRI.KnownSafe;
2398 MultipleOwners || MultiOwnersSet.count(
GetObjCArg(NewRetain));
2400 LI = NewRetainRRI.Calls.begin(),
2401 LE = NewRetainRRI.Calls.end();
LI !=
LE; ++
LI) {
2404 Releases.
find(NewRetainRelease);
2405 if (Jt == Releases.
end())
2407 const RRInfo &NewRetainReleaseRRI = Jt->second;
2414 if (!NewRetainReleaseRRI.Calls.count(NewRetain))
2417 if (ReleasesToMove.Calls.insert(NewRetainRelease)) {
2421 const BBState &NRRBBState = BBStates[NewRetainRelease->
getParent()];
2422 unsigned PathCount = BBState::OverflowOccurredValue;
2423 if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
2425 assert(PathCount != BBState::OverflowOccurredValue &&
2426 "PathCount at this point can not be "
2427 "OverflowOccurredValue.");
2428 OldDelta -= PathCount;
2432 ReleasesToMove.ReleaseMetadata =
2433 NewRetainReleaseRRI.ReleaseMetadata;
2434 ReleasesToMove.IsTailCallRelease =
2435 NewRetainReleaseRRI.IsTailCallRelease;
2436 FirstRelease =
false;
2438 if (ReleasesToMove.ReleaseMetadata !=
2439 NewRetainReleaseRRI.ReleaseMetadata)
2440 ReleasesToMove.ReleaseMetadata = 0;
2441 if (ReleasesToMove.IsTailCallRelease !=
2442 NewRetainReleaseRRI.IsTailCallRelease)
2443 ReleasesToMove.IsTailCallRelease =
false;
2449 RI = NewRetainReleaseRRI.ReverseInsertPts.begin(),
2450 RE = NewRetainReleaseRRI.ReverseInsertPts.end();
2453 if (ReleasesToMove.ReverseInsertPts.insert(RIP)) {
2456 const BBState &RIPBBState = BBStates[RIP->
getParent()];
2457 PathCount = BBState::OverflowOccurredValue;
2458 if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
2460 assert(PathCount != BBState::OverflowOccurredValue &&
2461 "PathCount at this point can not be "
2462 "OverflowOccurredValue.");
2463 NewDelta -= PathCount;
2466 NewReleases.
push_back(NewRetainRelease);
2471 if (NewReleases.
empty())
break;
2475 NI = NewReleases.
begin(),
NE = NewReleases.
end(); NI !=
NE; ++NI) {
2478 Releases.
find(NewRelease);
2479 assert(It != Releases.
end());
2480 const RRInfo &NewReleaseRRI = It->second;
2481 KnownSafeBU &= NewReleaseRRI.KnownSafe;
2482 CFGHazardAfflicted |= NewReleaseRRI.CFGHazardAfflicted;
2484 LI = NewReleaseRRI.Calls.begin(),
2485 LE = NewReleaseRRI.Calls.end();
LI !=
LE; ++
LI) {
2487 MapVector<Value *, RRInfo>::const_iterator Jt =
2488 Retains.
find(NewReleaseRetain);
2489 if (Jt == Retains.
end())
2491 const RRInfo &NewReleaseRetainRRI = Jt->second;
2498 if (!NewReleaseRetainRRI.Calls.count(NewRelease))
2501 if (RetainsToMove.Calls.insert(NewReleaseRetain)) {
2504 const BBState &NRRBBState = BBStates[NewReleaseRetain->
getParent()];
2505 unsigned PathCount = BBState::OverflowOccurredValue;
2506 if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
2508 assert(PathCount != BBState::OverflowOccurredValue &&
2509 "PathCount at this point can not be "
2510 "OverflowOccurredValue.");
2511 OldDelta += PathCount;
2512 OldCount += PathCount;
2517 RI = NewReleaseRetainRRI.ReverseInsertPts.begin(),
2518 RE = NewReleaseRetainRRI.ReverseInsertPts.end();
2521 if (RetainsToMove.ReverseInsertPts.insert(RIP)) {
2524 const BBState &RIPBBState = BBStates[RIP->
getParent()];
2526 PathCount = BBState::OverflowOccurredValue;
2527 if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
2529 assert(PathCount != BBState::OverflowOccurredValue &&
2530 "PathCount at this point can not be "
2531 "OverflowOccurredValue.");
2532 NewDelta += PathCount;
2533 NewCount += PathCount;
2540 NewReleases.
clear();
2541 if (NewRetains.
empty())
break;
2547 bool UnconditionallySafe = (KnownSafeTD && KnownSafeBU) ||
2548 ((KnownSafeTD || KnownSafeBU) && !MultipleOwners);
2549 if (UnconditionallySafe) {
2550 RetainsToMove.ReverseInsertPts.clear();
2551 ReleasesToMove.ReverseInsertPts.clear();
2564 const bool WillPerformCodeMotion = RetainsToMove.ReverseInsertPts.size() ||
2565 ReleasesToMove.ReverseInsertPts.size();
2566 if (CFGHazardAfflicted && WillPerformCodeMotion)
2578 #ifdef ARC_ANNOTATIONS
2582 #endif // ARC_ANNOTATIONS
2585 assert(OldCount != 0 &&
"Unreachable code?");
2586 NumRRs += OldCount - NewCount;
2588 AnyPairsCompletelyEliminated = NewCount == 0;
2602 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::PerformCodePlacement ==\n");
2604 bool AnyPairsCompletelyEliminated =
false;
2605 RRInfo RetainsToMove;
2606 RRInfo ReleasesToMove;
2612 for (MapVector<Value *, RRInfo>::const_iterator I = Retains.
begin(),
2613 E = Retains.
end(); I != E; ++
I) {
2614 Value *V = I->first;
2619 DEBUG(
dbgs() <<
"Visiting: " << *Retain <<
"\n");
2626 bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
2630 if (
const LoadInst *
LI = dyn_cast<LoadInst>(Arg))
2632 dyn_cast<GlobalVariable>(
2634 if (GV->isConstant())
2640 bool PerformMoveCalls =
2641 ConnectTDBUTraversals(BBStates, Retains, Releases, M, NewRetains,
2642 NewReleases, DeadInsts, RetainsToMove,
2643 ReleasesToMove, Arg, KnownSafe,
2644 AnyPairsCompletelyEliminated);
2646 if (PerformMoveCalls) {
2649 MoveCalls(Arg, RetainsToMove, ReleasesToMove,
2650 Retains, Releases, DeadInsts, M);
2654 NewReleases.
clear();
2656 RetainsToMove.clear();
2657 ReleasesToMove.clear();
2662 while (!DeadInsts.
empty())
2665 return AnyPairsCompletelyEliminated;
2669 void ObjCARCOpt::OptimizeWeakCalls(
Function &F) {
2670 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::OptimizeWeakCalls ==\n");
2678 DEBUG(
dbgs() <<
"Visiting: " << *Inst <<
"\n");
2701 switch (EarlierClass) {
2706 CallInst *Call = cast<CallInst>(Inst);
2707 CallInst *EarlierCall = cast<CallInst>(EarlierInst);
2709 Value *EarlierArg = EarlierCall->getArgOperand(0);
2710 switch (PA.getAA()->alias(Arg, EarlierArg)) {
2735 CallInst *Call = cast<CallInst>(Inst);
2736 CallInst *EarlierCall = cast<CallInst>(EarlierInst);
2738 Value *EarlierArg = EarlierCall->getArgOperand(0);
2739 switch (PA.getAA()->alias(Arg, EarlierArg)) {
2787 CallInst *Call = cast<CallInst>(Inst);
2789 if (
AllocaInst *Alloca = dyn_cast<AllocaInst>(Arg)) {
2791 UE = Alloca->use_end(); UI != UE; ++UI) {
2792 const Instruction *UserInst = cast<Instruction>(*UI);
2804 UE = Alloca->use_end(); UI != UE; ) {
2805 CallInst *UserInst = cast<CallInst>(*UI++);
2820 Alloca->eraseFromParent();
2828 bool ObjCARCOpt::OptimizeSequences(
Function &F) {
2841 bool NestingDetected = Visit(F, BBStates, Retains, Releases);
2844 bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains,
2849 MultiOwnersSet.clear();
2851 return AnyPairsCompletelyEliminated && NestingDetected;
2863 DepInsts, Visited, PA);
2864 if (DepInsts.size() != 1)
2868 dyn_cast_or_null<CallInst>(*DepInsts.begin());
2871 if (!Call || Arg != Call)
2892 BB, Autorelease, DepInsts, Visited, PA);
2893 if (DepInsts.
size() != 1)
2897 dyn_cast_or_null<CallInst>(*DepInsts.
begin());
2919 BB, Ret, DepInsts, V, PA);
2920 if (DepInsts.
size() != 1)
2924 dyn_cast_or_null<CallInst>(*DepInsts.
begin());
2944 void ObjCARCOpt::OptimizeReturns(
Function &F) {
2948 DEBUG(
dbgs() <<
"\n== ObjCARCOpt::OptimizeReturns ==\n");
2956 DEBUG(
dbgs() <<
"Visiting: " << *Ret <<
"\n");
2968 DependingInstructions, Visited,
2970 DependingInstructions.
clear();
2978 DependingInstructions, Visited, PA);
2979 DependingInstructions.
clear();
2988 DependingInstructions,
2990 DependingInstructions.
clear();
2993 if (!HasSafePathToCall)
2999 DEBUG(
dbgs() <<
"Erasing: " << *Retain <<
"\nErasing: "
3000 << *Autorelease <<
"\n");
3008 ObjCARCOpt::GatherStatistics(
Function &F,
bool AfterOptimization) {
3010 AfterOptimization? NumRetainsAfterOpt : NumRetainsBeforeOpt;
3012 AfterOptimization? NumReleasesAfterOpt : NumReleasesBeforeOpt;
3030 bool ObjCARCOpt::doInitialization(
Module &M) {
3040 ImpreciseReleaseMDKind =
3042 CopyOnEscapeMDKind =
3044 NoObjCARCExceptionsMDKind =
3046 #ifdef ARC_ANNOTATIONS
3047 ARCAnnotationBottomUpMDKind =
3049 ARCAnnotationTopDownMDKind =
3051 ARCAnnotationProvenanceSourceMDKind =
3053 #endif // ARC_ANNOTATIONS
3065 bool ObjCARCOpt::runOnFunction(
Function &F) {
3075 DEBUG(
dbgs() <<
"<<< ObjCARCOpt: Visiting Function: " << F.
getName() <<
" >>>"
3078 PA.setAA(&getAnalysis<AliasAnalysis>());
3082 GatherStatistics(F,
false);
3091 OptimizeIndividualCalls(F);
3101 OptimizeWeakCalls(F);
3104 if (UsedInThisFunction & ((1 <<
IC_Retain) |
3110 while (OptimizeSequences(F)) {}
3120 GatherStatistics(F,
true);
3129 void ObjCARCOpt::releaseMemory() {
BBIty & getBasicBlockIterator()
void push_back(const T &Elt)
const_iterator end(StringRef path)
Get end iterator over path.
Pointers differ, but pointees overlap.
static PassRegistry * getPassRegistry()
LLVM Argument representation.
BIty & getInstructionIterator()
objc_retainedObject, etc.
#define ANNOTATE_BOTTOMUP_BBSTART(_states, _basicblock)
const Instruction & back() const
static CallInst * FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB, ReturnInst *Ret, SmallPtrSet< Instruction *, 4 > &DepInsts, SmallPtrSet< const BasicBlock *, 4 > &V, ProvenanceAnalysis &PA)
The main container class for the LLVM Intermediate Representation.
static MDString * get(LLVMContext &Context, StringRef Str)
static Value * GetObjCArg(Value *Inst)
Assuming the given instruction is one of the special calls such as objc_retain or objc_release...
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getNumOperands() const
getNumOperands - Return number of MDNode operands.
static bool IsUser(InstructionClass Class)
Test if the given class is a kind of user.
static InstructionClass GetBasicInstructionClass(const Value *V)
Determine which objc runtime call instruction class V belongs to.
objc_storeWeak (primitive)
static bool IsNoopOnNull(InstructionClass Class)
Test if the given class represents instructions which do nothing if passed a null pointer...
static std::string SequenceToString(Sequence A)
#define ANNOTATE_TOPDOWN_BBSTART(_states, _basicblock)
const_iterator begin(StringRef path)
Get begin iterator over path.
Type * getReturnType() const
const Function * getParent() const
Return the enclosing method, or null if none.
raw_ostream & operator<<(raw_ostream &OS, const InstructionClass Class)
MDNode - a tuple of other values.
void initializeObjCARCOptPass(PassRegistry &)
iv Induction Variable Users
const GlobalVariable * getGlobalVariable(StringRef Name, bool AllowInternal=false) const
static bool IsForwarding(InstructionClass Class)
Test if the given class represents instructions which return their argument verbatim.
LoopInfoBase< BlockT, LoopT > * LI
static MDNode * get(LLVMContext &Context, ArrayRef< Value * > Vals)
static Constant * getNullValue(Type *Ty)
StringRef getName() const
Value * getOperand(unsigned i) const LLVM_READONLY
getOperand - Return specified operand.
#define ANNOTATE_BOTTOMUP_BBEND(_states, _basicblock)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static bool HasSafePathToPredecessorCall(const Value *Arg, Instruction *Retain, SmallPtrSet< Instruction *, 4 > &DepInsts, SmallPtrSet< const BasicBlock *, 4 > &Visited, ProvenanceAnalysis &PA)
inst_iterator inst_begin(Function *F)
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
static const Value * StripPointerCastsAndObjCCalls(const Value *V)
This is a wrapper around Value::stripPointerCasts which also knows how to look through objc_retain an...
#define llvm_unreachable(msg)
STATISTIC(NumNoops,"Number of no-op objc calls eliminated")
InstructionClass GetInstructionClass(const Value *V)
Determine what kind of construct V is.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
ID
LLVM Calling Convention Representation.
Instruction * clone() const
Interval::succ_iterator succ_begin(Interval *I)
static void GenerateARCBBEntranceAnnotation(const char *Name, BasicBlock *BB, Value *Ptr, Sequence Seq)
LLVMContext & getContext() const
getContext - Return the LLVMContext in which this type was uniqued.
bool count(PtrType Ptr) const
count - Return true if the specified pointer is in the set.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
bool EnableARCOpts
A handy option to enable/disable all ARC Optimizations.
This class represents a no-op cast from one type to another.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
void replaceAllUsesWith(Value *V)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
#define ANNOTATE_BOTTOMUP(inst, ptr, old, new)
iterator find(const KeyT &Key)
void FindDependencies(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, SmallPtrSet< Instruction *, 4 > &DependingInstructions, SmallPtrSet< const BasicBlock *, 4 > &Visited, ProvenanceAnalysis &PA)
static MDString * SequenceToMDString(LLVMContext &Context, Sequence A)
static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown)
unsigned getNumIncomingValues() const
Interval::succ_iterator succ_end(Interval *I)
This is a simple alias analysis implementation that uses knowledge of ARC constructs to answer querie...
static cl::opt< std::string > ARCAnnotationTargetIdentifier("objc-arc-annotation-target-identifier", cl::init(""), cl::desc("filter out all data flow annotations ""but those that apply to the given ""target llvm identifier."))
initializer< Ty > init(const Ty &Val)
friend const_iterator end(StringRef path)
Get end iterator over path.
Value * CreateGlobalStringPtr(StringRef Str, const Twine &Name="")
Same as CreateGlobalString, but return a pointer with "i8*" type instead of a pointer to array of i8...
#define ANNOTATE_TOPDOWN_BBEND(_states, _basicblock)
SuccIterator< TerminatorInst *, BasicBlock > succ_iterator
static cl::opt< bool > EnableARCAnnotations("enable-objc-arc-annotations", cl::init(false), cl::desc("Enable emission of arc data flow analysis ""annotations"))
Enable/disable ARC sequence annotations.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
void insertBefore(Instruction *InsertPos)
LLVM Basic Block Representation.
bool CanAlterRefCount(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, InstructionClass Class)
LLVM Constant Representation.
objc_destroyWeak (derived)
static MDString * AppendMDNodeToSourcePtr(unsigned NodeId, Value *Ptr)
Interval::pred_iterator pred_begin(Interval *I)
static Type * getVoidTy(LLVMContext &C)
BasicBlock * getIncomingBlock(unsigned i) const
ItTy next(ItTy it, Dist n)
static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq, const bool SuccSRRIKnownSafe, PtrState &S, bool &SomeSuccHasSame, bool &AllSuccsHaveSame, bool &NotAllSeqEqualButKnownSafe)
#define LLVM_ATTRIBUTE_UNUSED
InstructionClass
A simple classification for instructions.
static bool IsNoopInstruction(const Instruction *I)
unsigned getMDKindID(StringRef Name) const
getMDKindID - Return a unique non-zero ID for the specified metadata kind.
Value * getOperand(unsigned i) const
Interval::pred_iterator pred_end(Interval *I)
static const Value * FindSingleUseIdentifiedObject(const Value *Arg)
This is similar to StripPointerCastsAndObjCCalls but it stops as soon as it finds a value with multip...
static bool IsObjCIdentifiedObject(const Value *V)
Return true if this value refers to a distinct and identifiable object.
static void CheckForUseCFGHazard(const Sequence SuccSSeq, const bool SuccSRRIKnownSafe, PtrState &S, bool &SomeSuccHasSame, bool &AllSuccsHaveSame, bool &NotAllSeqEqualButKnownSafe, bool &ShouldContinue)
INITIALIZE_PASS_BEGIN(ObjCARCOpt,"objc-arc","ObjC ARC optimization", false, false) INITIALIZE_PASS_END(ObjCARCOpt
#define ANNOTATE_TOPDOWN(inst, ptr, old, new)
void setTailCall(bool isTC=true)
static UndefValue * get(Type *T)
LLVMContext & getContext() const
All values hold a context through their type.
void setMetadata(unsigned KindID, MDNode *Node)
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=0)
static bool AreAnyUnderlyingObjectsAnAlloca(const Value *V)
SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
static void EraseInstruction(Instruction *CI)
Erase the given instruction.
static bool IsNoThrow(InstructionClass Class)
Test if the given class represents instructions which are always safe to mark with the nounwind attri...
static PointerType * getUnqual(Type *ElementType)
Value * getIncomingValue(unsigned i) const
friend const_iterator begin(StringRef path)
Get begin iterator over path.
static bool IsNullOrUndef(const Value *V)
bool CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, InstructionClass Class)
MDNode * getMetadata(unsigned KindID) const
bool erase(const KeyT &Val)
static bool IsNeverTail(InstructionClass Class)
Test if the given class represents instructions which are never safe to mark with the "tail" keyword...
could call objc_release and/or "use" pointers
const BasicBlock & getEntryBlock() const
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Value * getArgOperand(unsigned i) const
static bool IsAutorelease(InstructionClass Class)
Test if the given class is objc_autorelease or equivalent.
static void GenerateARCAnnotation(unsigned InstMDId, unsigned PtrMDId, Instruction *Inst, Value *Ptr, Sequence OldSeq, Sequence NewSeq)
Pass * createObjCARCOptPass()
objc_autoreleaseReturnValue
bool equals(StringRef RHS) const
objc ObjC ARC optimization
void setCalledFunction(Value *Fn)
setCalledFunction - Set the function called.
static CallInst * FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB, Instruction *Autorelease, SmallPtrSet< Instruction *, 4 > &DepInsts, SmallPtrSet< const BasicBlock *, 4 > &Visited, ProvenanceAnalysis &PA)
ImmutableCallSite - establish a view to a call site for examination.
void setArgOperand(unsigned i, Value *v)
objc_retainAutoreleasedReturnValue
Rename collisions when linking (static functions).
static void AppendMDNodeToInstForPtr(unsigned NodeId, Instruction *Inst, Value *Ptr, MDString *PtrSourceMDNodeID, Sequence OldSeq, Sequence NewSeq)
CallInst * CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
reverse_iterator rbegin()
LLVM Value Representation.
ItTy prior(ItTy it, Dist n)
static bool IsRetain(InstructionClass Class)
Test if the given class is objc_retain or equivalent.
This is similar to BasicAliasAnalysis, and it uses many of the same techniques, except it uses specia...
objc_loadWeakRetained (primitive)
inst_iterator inst_end(Function *F)
static void ComputePostOrders(Function &F, SmallVectorImpl< BasicBlock * > &PostOrder, SmallVectorImpl< BasicBlock * > &ReverseCFGPostOrder, unsigned NoObjCARCExceptionsMDKind, DenseMap< const BasicBlock *, BBState > &BBStates)
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static const Value * GetUnderlyingObjCPtr(const Value *V)
This is a wrapper around getUnderlyingObject which also knows how to look through objc_retain and obj...
static bool IsAlwaysTail(InstructionClass Class)
Test if the given class represents instructions which are always safe to mark with the "tail" keyword...
iterator find(const KeyT &Val)
static IntegerType * getInt8Ty(LLVMContext &C)
bool AreStatisticsEnabled()
Check if statistics are enabled.
const BasicBlock * getParent() const
static bool ModuleHasARC(const Module &M)
Test if the given module looks interesting to run ARC optimization on.
LLVMContext & getContext() const
static cl::opt< bool > DisableCheckForCFGHazards("disable-objc-arc-checkforcfghazards", cl::init(false), cl::desc("Disable check for cfg hazards when ""annotating"))
static void GenerateARCBBTerminatorAnnotation(const char *Name, BasicBlock *BB, Value *Ptr, Sequence Seq)