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