PtrState.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. //===--- PtrState.cpp -----------------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "PtrState.h"
  10. #include "DependencyAnalysis.h"
  11. #include "ObjCARC.h"
  12. #include "llvm/Support/Debug.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. using namespace llvm;
  15. using namespace llvm::objcarc;
  16. #define DEBUG_TYPE "objc-arc-ptr-state"
  17. //===----------------------------------------------------------------------===//
  18. // Utility
  19. //===----------------------------------------------------------------------===//
  20. raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
  21. switch (S) {
  22. case S_None:
  23. return OS << "S_None";
  24. case S_Retain:
  25. return OS << "S_Retain";
  26. case S_CanRelease:
  27. return OS << "S_CanRelease";
  28. case S_Use:
  29. return OS << "S_Use";
  30. case S_Release:
  31. return OS << "S_Release";
  32. case S_MovableRelease:
  33. return OS << "S_MovableRelease";
  34. case S_Stop:
  35. return OS << "S_Stop";
  36. }
  37. llvm_unreachable("Unknown sequence type.");
  38. }
  39. //===----------------------------------------------------------------------===//
  40. // Sequence
  41. //===----------------------------------------------------------------------===//
  42. static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
  43. // The easy cases.
  44. if (A == B)
  45. return A;
  46. if (A == S_None || B == S_None)
  47. return S_None;
  48. if (A > B)
  49. std::swap(A, B);
  50. if (TopDown) {
  51. // Choose the side which is further along in the sequence.
  52. if ((A == S_Retain || A == S_CanRelease) &&
  53. (B == S_CanRelease || B == S_Use))
  54. return B;
  55. } else {
  56. // Choose the side which is further along in the sequence.
  57. if ((A == S_Use || A == S_CanRelease) &&
  58. (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
  59. return A;
  60. // If both sides are releases, choose the more conservative one.
  61. if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
  62. return A;
  63. if (A == S_Release && B == S_MovableRelease)
  64. return A;
  65. }
  66. return S_None;
  67. }
  68. //===----------------------------------------------------------------------===//
  69. // RRInfo
  70. //===----------------------------------------------------------------------===//
  71. void RRInfo::clear() {
  72. KnownSafe = false;
  73. IsTailCallRelease = false;
  74. ReleaseMetadata = nullptr;
  75. Calls.clear();
  76. ReverseInsertPts.clear();
  77. CFGHazardAfflicted = false;
  78. }
  79. bool RRInfo::Merge(const RRInfo &Other) {
  80. // Conservatively merge the ReleaseMetadata information.
  81. if (ReleaseMetadata != Other.ReleaseMetadata)
  82. ReleaseMetadata = nullptr;
  83. // Conservatively merge the boolean state.
  84. KnownSafe &= Other.KnownSafe;
  85. IsTailCallRelease &= Other.IsTailCallRelease;
  86. CFGHazardAfflicted |= Other.CFGHazardAfflicted;
  87. // Merge the call sets.
  88. Calls.insert(Other.Calls.begin(), Other.Calls.end());
  89. // Merge the insert point sets. If there are any differences,
  90. // that makes this a partial merge.
  91. bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
  92. for (Instruction *Inst : Other.ReverseInsertPts)
  93. Partial |= ReverseInsertPts.insert(Inst).second;
  94. return Partial;
  95. }
  96. //===----------------------------------------------------------------------===//
  97. // PtrState
  98. //===----------------------------------------------------------------------===//
  99. void PtrState::SetKnownPositiveRefCount() {
  100. DEBUG(dbgs() << " Setting Known Positive.\n");
  101. KnownPositiveRefCount = true;
  102. }
  103. void PtrState::ClearKnownPositiveRefCount() {
  104. DEBUG(dbgs() << " Clearing Known Positive.\n");
  105. KnownPositiveRefCount = false;
  106. }
  107. void PtrState::SetSeq(Sequence NewSeq) {
  108. DEBUG(dbgs() << " Old: " << GetSeq() << "; New: " << NewSeq << "\n");
  109. Seq = NewSeq;
  110. }
  111. void PtrState::ResetSequenceProgress(Sequence NewSeq) {
  112. DEBUG(dbgs() << " Resetting sequence progress.\n");
  113. SetSeq(NewSeq);
  114. Partial = false;
  115. RRI.clear();
  116. }
  117. void PtrState::Merge(const PtrState &Other, bool TopDown) {
  118. Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
  119. KnownPositiveRefCount &= Other.KnownPositiveRefCount;
  120. // If we're not in a sequence (anymore), drop all associated state.
  121. if (Seq == S_None) {
  122. Partial = false;
  123. RRI.clear();
  124. } else if (Partial || Other.Partial) {
  125. // If we're doing a merge on a path that's previously seen a partial
  126. // merge, conservatively drop the sequence, to avoid doing partial
  127. // RR elimination. If the branch predicates for the two merge differ,
  128. // mixing them is unsafe.
  129. ClearSequenceProgress();
  130. } else {
  131. // Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
  132. // point, we know that currently we are not partial. Stash whether or not
  133. // the merge operation caused us to undergo a partial merging of reverse
  134. // insertion points.
  135. Partial = RRI.Merge(Other.RRI);
  136. }
  137. }
  138. //===----------------------------------------------------------------------===//
  139. // BottomUpPtrState
  140. //===----------------------------------------------------------------------===//
  141. bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
  142. // If we see two releases in a row on the same pointer. If so, make
  143. // a note, and we'll cicle back to revisit it after we've
  144. // hopefully eliminated the second release, which may allow us to
  145. // eliminate the first release too.
  146. // Theoretically we could implement removal of nested retain+release
  147. // pairs by making PtrState hold a stack of states, but this is
  148. // simple and avoids adding overhead for the non-nested case.
  149. bool NestingDetected = false;
  150. if (GetSeq() == S_Release || GetSeq() == S_MovableRelease) {
  151. DEBUG(dbgs() << " Found nested releases (i.e. a release pair)\n");
  152. NestingDetected = true;
  153. }
  154. MDNode *ReleaseMetadata =
  155. I->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
  156. Sequence NewSeq = ReleaseMetadata ? S_MovableRelease : S_Release;
  157. ResetSequenceProgress(NewSeq);
  158. SetReleaseMetadata(ReleaseMetadata);
  159. SetKnownSafe(HasKnownPositiveRefCount());
  160. SetTailCallRelease(cast<CallInst>(I)->isTailCall());
  161. InsertCall(I);
  162. SetKnownPositiveRefCount();
  163. return NestingDetected;
  164. }
  165. bool BottomUpPtrState::MatchWithRetain() {
  166. SetKnownPositiveRefCount();
  167. Sequence OldSeq = GetSeq();
  168. switch (OldSeq) {
  169. case S_Stop:
  170. case S_Release:
  171. case S_MovableRelease:
  172. case S_Use:
  173. // If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
  174. // imprecise release, clear our reverse insertion points.
  175. if (OldSeq != S_Use || IsTrackingImpreciseReleases())
  176. ClearReverseInsertPts();
  177. // FALL THROUGH
  178. case S_CanRelease:
  179. return true;
  180. case S_None:
  181. return false;
  182. case S_Retain:
  183. llvm_unreachable("bottom-up pointer in retain state!");
  184. }
  185. llvm_unreachable("Sequence unknown enum value");
  186. }
  187. bool BottomUpPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
  188. const Value *Ptr,
  189. ProvenanceAnalysis &PA,
  190. ARCInstKind Class) {
  191. Sequence S = GetSeq();
  192. // Check for possible releases.
  193. if (!CanAlterRefCount(Inst, Ptr, PA, Class))
  194. return false;
  195. DEBUG(dbgs() << " CanAlterRefCount: Seq: " << S << "; " << *Ptr
  196. << "\n");
  197. switch (S) {
  198. case S_Use:
  199. SetSeq(S_CanRelease);
  200. return true;
  201. case S_CanRelease:
  202. case S_Release:
  203. case S_MovableRelease:
  204. case S_Stop:
  205. case S_None:
  206. return false;
  207. case S_Retain:
  208. llvm_unreachable("bottom-up pointer in retain state!");
  209. }
  210. llvm_unreachable("Sequence unknown enum value");
  211. }
  212. void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,
  213. const Value *Ptr,
  214. ProvenanceAnalysis &PA,
  215. ARCInstKind Class) {
  216. // Check for possible direct uses.
  217. switch (GetSeq()) {
  218. case S_Release:
  219. case S_MovableRelease:
  220. if (CanUse(Inst, Ptr, PA, Class)) {
  221. DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; " << *Ptr
  222. << "\n");
  223. assert(!HasReverseInsertPts());
  224. // If this is an invoke instruction, we're scanning it as part of
  225. // one of its successor blocks, since we can't insert code after it
  226. // in its own block, and we don't want to split critical edges.
  227. if (isa<InvokeInst>(Inst))
  228. InsertReverseInsertPt(BB->getFirstInsertionPt());
  229. else
  230. InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
  231. SetSeq(S_Use);
  232. } else if (Seq == S_Release && IsUser(Class)) {
  233. DEBUG(dbgs() << " PreciseReleaseUse: Seq: " << GetSeq() << "; "
  234. << *Ptr << "\n");
  235. // Non-movable releases depend on any possible objc pointer use.
  236. SetSeq(S_Stop);
  237. assert(!HasReverseInsertPts());
  238. // As above; handle invoke specially.
  239. if (isa<InvokeInst>(Inst))
  240. InsertReverseInsertPt(BB->getFirstInsertionPt());
  241. else
  242. InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
  243. }
  244. break;
  245. case S_Stop:
  246. if (CanUse(Inst, Ptr, PA, Class)) {
  247. DEBUG(dbgs() << " PreciseStopUse: Seq: " << GetSeq() << "; "
  248. << *Ptr << "\n");
  249. SetSeq(S_Use);
  250. }
  251. break;
  252. case S_CanRelease:
  253. case S_Use:
  254. case S_None:
  255. break;
  256. case S_Retain:
  257. llvm_unreachable("bottom-up pointer in retain state!");
  258. }
  259. }
  260. //===----------------------------------------------------------------------===//
  261. // TopDownPtrState
  262. //===----------------------------------------------------------------------===//
  263. bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
  264. bool NestingDetected = false;
  265. // Don't do retain+release tracking for ARCInstKind::RetainRV, because
  266. // it's
  267. // better to let it remain as the first instruction after a call.
  268. if (Kind != ARCInstKind::RetainRV) {
  269. // If we see two retains in a row on the same pointer. If so, make
  270. // a note, and we'll cicle back to revisit it after we've
  271. // hopefully eliminated the second retain, which may allow us to
  272. // eliminate the first retain too.
  273. // Theoretically we could implement removal of nested retain+release
  274. // pairs by making PtrState hold a stack of states, but this is
  275. // simple and avoids adding overhead for the non-nested case.
  276. if (GetSeq() == S_Retain)
  277. NestingDetected = true;
  278. ResetSequenceProgress(S_Retain);
  279. SetKnownSafe(HasKnownPositiveRefCount());
  280. InsertCall(I);
  281. }
  282. SetKnownPositiveRefCount();
  283. return NestingDetected;
  284. }
  285. bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
  286. Instruction *Release) {
  287. ClearKnownPositiveRefCount();
  288. Sequence OldSeq = GetSeq();
  289. MDNode *ReleaseMetadata =
  290. Release->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
  291. switch (OldSeq) {
  292. case S_Retain:
  293. case S_CanRelease:
  294. if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
  295. ClearReverseInsertPts();
  296. // FALL THROUGH
  297. case S_Use:
  298. SetReleaseMetadata(ReleaseMetadata);
  299. SetTailCallRelease(cast<CallInst>(Release)->isTailCall());
  300. return true;
  301. case S_None:
  302. return false;
  303. case S_Stop:
  304. case S_Release:
  305. case S_MovableRelease:
  306. llvm_unreachable("top-down pointer in bottom up state!");
  307. }
  308. llvm_unreachable("Sequence unknown enum value");
  309. }
  310. bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
  311. const Value *Ptr,
  312. ProvenanceAnalysis &PA,
  313. ARCInstKind Class) {
  314. // Check for possible releases.
  315. if (!CanAlterRefCount(Inst, Ptr, PA, Class))
  316. return false;
  317. DEBUG(dbgs() << " CanAlterRefCount: Seq: " << GetSeq() << "; " << *Ptr
  318. << "\n");
  319. ClearKnownPositiveRefCount();
  320. switch (GetSeq()) {
  321. case S_Retain:
  322. SetSeq(S_CanRelease);
  323. assert(!HasReverseInsertPts());
  324. InsertReverseInsertPt(Inst);
  325. // One call can't cause a transition from S_Retain to S_CanRelease
  326. // and S_CanRelease to S_Use. If we've made the first transition,
  327. // we're done.
  328. return true;
  329. case S_Use:
  330. case S_CanRelease:
  331. case S_None:
  332. return false;
  333. case S_Stop:
  334. case S_Release:
  335. case S_MovableRelease:
  336. llvm_unreachable("top-down pointer in release state!");
  337. }
  338. llvm_unreachable("covered switch is not covered!?");
  339. }
  340. void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
  341. ProvenanceAnalysis &PA,
  342. ARCInstKind Class) {
  343. // Check for possible direct uses.
  344. switch (GetSeq()) {
  345. case S_CanRelease:
  346. if (!CanUse(Inst, Ptr, PA, Class))
  347. return;
  348. DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; " << *Ptr
  349. << "\n");
  350. SetSeq(S_Use);
  351. return;
  352. case S_Retain:
  353. case S_Use:
  354. case S_None:
  355. return;
  356. case S_Stop:
  357. case S_Release:
  358. case S_MovableRelease:
  359. llvm_unreachable("top-down pointer in release state!");
  360. }
  361. }