PtrState.cpp 15 KB

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