blob: 8a7b6a74fae2fdf3308adf21aa271c7016169938 [file] [log] [blame]
Eugene Zelenko57bd5a02017-10-27 01:09:08 +00001//===- PtrState.cpp -------------------------------------------------------===//
Michael Gottesman68b91db2015-03-05 23:29:03 +00002//
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
10#include "PtrState.h"
Michael Gottesman16e6a202015-03-06 02:07:12 +000011#include "DependencyAnalysis.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000012#include "ObjCARC.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000013#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
14#include "llvm/Analysis/ObjCARCInstKind.h"
15#include "llvm/IR/BasicBlock.h"
16#include "llvm/IR/Instruction.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/Value.h"
19#include "llvm/Support/Casting.h"
20#include "llvm/Support/Compiler.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000021#include "llvm/Support/Debug.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000022#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000023#include "llvm/Support/raw_ostream.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000024#include <cassert>
25#include <iterator>
26#include <utility>
Michael Gottesman68b91db2015-03-05 23:29:03 +000027
28using namespace llvm;
29using namespace llvm::objcarc;
30
Benjamin Kramer799003b2015-03-23 19:32:43 +000031#define DEBUG_TYPE "objc-arc-ptr-state"
32
Michael Gottesman16e6a202015-03-06 02:07:12 +000033//===----------------------------------------------------------------------===//
34// Utility
35//===----------------------------------------------------------------------===//
36
Michael Gottesmand45907b2015-03-05 23:57:07 +000037raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
Michael Gottesman68b91db2015-03-05 23:29:03 +000038 switch (S) {
39 case S_None:
40 return OS << "S_None";
41 case S_Retain:
42 return OS << "S_Retain";
43 case S_CanRelease:
44 return OS << "S_CanRelease";
45 case S_Use:
46 return OS << "S_Use";
47 case S_Release:
48 return OS << "S_Release";
49 case S_MovableRelease:
50 return OS << "S_MovableRelease";
51 case S_Stop:
52 return OS << "S_Stop";
53 }
54 llvm_unreachable("Unknown sequence type.");
55}
56
Michael Gottesman16e6a202015-03-06 02:07:12 +000057//===----------------------------------------------------------------------===//
58// Sequence
59//===----------------------------------------------------------------------===//
60
Michael Gottesman68b91db2015-03-05 23:29:03 +000061static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
62 // The easy cases.
63 if (A == B)
64 return A;
65 if (A == S_None || B == S_None)
66 return S_None;
67
68 if (A > B)
69 std::swap(A, B);
70 if (TopDown) {
71 // Choose the side which is further along in the sequence.
72 if ((A == S_Retain || A == S_CanRelease) &&
73 (B == S_CanRelease || B == S_Use))
74 return B;
75 } else {
76 // Choose the side which is further along in the sequence.
77 if ((A == S_Use || A == S_CanRelease) &&
78 (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
79 return A;
80 // If both sides are releases, choose the more conservative one.
81 if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
82 return A;
83 if (A == S_Release && B == S_MovableRelease)
84 return A;
85 }
86
87 return S_None;
88}
89
Michael Gottesman16e6a202015-03-06 02:07:12 +000090//===----------------------------------------------------------------------===//
91// RRInfo
92//===----------------------------------------------------------------------===//
93
Michael Gottesman68b91db2015-03-05 23:29:03 +000094void RRInfo::clear() {
95 KnownSafe = false;
96 IsTailCallRelease = false;
97 ReleaseMetadata = nullptr;
98 Calls.clear();
99 ReverseInsertPts.clear();
100 CFGHazardAfflicted = false;
101}
102
103bool RRInfo::Merge(const RRInfo &Other) {
104 // Conservatively merge the ReleaseMetadata information.
105 if (ReleaseMetadata != Other.ReleaseMetadata)
106 ReleaseMetadata = nullptr;
107
108 // Conservatively merge the boolean state.
109 KnownSafe &= Other.KnownSafe;
110 IsTailCallRelease &= Other.IsTailCallRelease;
111 CFGHazardAfflicted |= Other.CFGHazardAfflicted;
112
113 // Merge the call sets.
114 Calls.insert(Other.Calls.begin(), Other.Calls.end());
115
116 // Merge the insert point sets. If there are any differences,
117 // that makes this a partial merge.
118 bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
119 for (Instruction *Inst : Other.ReverseInsertPts)
120 Partial |= ReverseInsertPts.insert(Inst).second;
121 return Partial;
122}
123
Michael Gottesman16e6a202015-03-06 02:07:12 +0000124//===----------------------------------------------------------------------===//
125// PtrState
126//===----------------------------------------------------------------------===//
127
Michael Gottesmand45907b2015-03-05 23:57:07 +0000128void PtrState::SetKnownPositiveRefCount() {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000129 LLVM_DEBUG(dbgs() << " Setting Known Positive.\n");
Michael Gottesmand45907b2015-03-05 23:57:07 +0000130 KnownPositiveRefCount = true;
131}
132
133void PtrState::ClearKnownPositiveRefCount() {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000134 LLVM_DEBUG(dbgs() << " Clearing Known Positive.\n");
Michael Gottesmand45907b2015-03-05 23:57:07 +0000135 KnownPositiveRefCount = false;
136}
137
138void PtrState::SetSeq(Sequence NewSeq) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000139 LLVM_DEBUG(dbgs() << " Old: " << GetSeq() << "; New: " << NewSeq
140 << "\n");
Michael Gottesmand45907b2015-03-05 23:57:07 +0000141 Seq = NewSeq;
142}
143
144void PtrState::ResetSequenceProgress(Sequence NewSeq) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000145 LLVM_DEBUG(dbgs() << " Resetting sequence progress.\n");
Michael Gottesmand45907b2015-03-05 23:57:07 +0000146 SetSeq(NewSeq);
147 Partial = false;
148 RRI.clear();
149}
150
Michael Gottesman68b91db2015-03-05 23:29:03 +0000151void PtrState::Merge(const PtrState &Other, bool TopDown) {
152 Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
153 KnownPositiveRefCount &= Other.KnownPositiveRefCount;
154
155 // If we're not in a sequence (anymore), drop all associated state.
156 if (Seq == S_None) {
157 Partial = false;
158 RRI.clear();
159 } else if (Partial || Other.Partial) {
160 // If we're doing a merge on a path that's previously seen a partial
161 // merge, conservatively drop the sequence, to avoid doing partial
162 // RR elimination. If the branch predicates for the two merge differ,
163 // mixing them is unsafe.
164 ClearSequenceProgress();
165 } else {
166 // Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
167 // point, we know that currently we are not partial. Stash whether or not
168 // the merge operation caused us to undergo a partial merging of reverse
169 // insertion points.
170 Partial = RRI.Merge(Other.RRI);
171 }
172}
Michael Gottesman4eae3962015-03-06 00:34:39 +0000173
Michael Gottesman16e6a202015-03-06 02:07:12 +0000174//===----------------------------------------------------------------------===//
175// BottomUpPtrState
176//===----------------------------------------------------------------------===//
177
Michael Gottesman4eae3962015-03-06 00:34:39 +0000178bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
179 // If we see two releases in a row on the same pointer. If so, make
180 // a note, and we'll cicle back to revisit it after we've
181 // hopefully eliminated the second release, which may allow us to
182 // eliminate the first release too.
183 // Theoretically we could implement removal of nested retain+release
184 // pairs by making PtrState hold a stack of states, but this is
185 // simple and avoids adding overhead for the non-nested case.
186 bool NestingDetected = false;
187 if (GetSeq() == S_Release || GetSeq() == S_MovableRelease) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000188 LLVM_DEBUG(
189 dbgs() << " Found nested releases (i.e. a release pair)\n");
Michael Gottesman4eae3962015-03-06 00:34:39 +0000190 NestingDetected = true;
191 }
192
Michael Gottesman65cb7372015-03-16 07:02:27 +0000193 MDNode *ReleaseMetadata =
194 I->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
Michael Gottesman4eae3962015-03-06 00:34:39 +0000195 Sequence NewSeq = ReleaseMetadata ? S_MovableRelease : S_Release;
196 ResetSequenceProgress(NewSeq);
197 SetReleaseMetadata(ReleaseMetadata);
198 SetKnownSafe(HasKnownPositiveRefCount());
199 SetTailCallRelease(cast<CallInst>(I)->isTailCall());
200 InsertCall(I);
201 SetKnownPositiveRefCount();
202 return NestingDetected;
203}
204
Michael Gottesman60805962015-03-06 00:34:42 +0000205bool BottomUpPtrState::MatchWithRetain() {
206 SetKnownPositiveRefCount();
207
208 Sequence OldSeq = GetSeq();
209 switch (OldSeq) {
210 case S_Stop:
211 case S_Release:
212 case S_MovableRelease:
213 case S_Use:
214 // If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
215 // imprecise release, clear our reverse insertion points.
216 if (OldSeq != S_Use || IsTrackingImpreciseReleases())
217 ClearReverseInsertPts();
Justin Bognercd1d5aa2016-08-17 20:30:52 +0000218 LLVM_FALLTHROUGH;
Michael Gottesman60805962015-03-06 00:34:42 +0000219 case S_CanRelease:
220 return true;
221 case S_None:
222 return false;
223 case S_Retain:
224 llvm_unreachable("bottom-up pointer in retain state!");
225 }
Yaron Keren322bdad2015-03-06 07:49:14 +0000226 llvm_unreachable("Sequence unknown enum value");
Michael Gottesman60805962015-03-06 00:34:42 +0000227}
228
Michael Gottesman16e6a202015-03-06 02:07:12 +0000229bool BottomUpPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
230 const Value *Ptr,
231 ProvenanceAnalysis &PA,
232 ARCInstKind Class) {
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000233 Sequence S = GetSeq();
Michael Gottesman16e6a202015-03-06 02:07:12 +0000234
235 // Check for possible releases.
236 if (!CanAlterRefCount(Inst, Ptr, PA, Class))
237 return false;
238
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000239 LLVM_DEBUG(dbgs() << " CanAlterRefCount: Seq: " << S << "; "
240 << *Ptr << "\n");
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000241 switch (S) {
Michael Gottesman16e6a202015-03-06 02:07:12 +0000242 case S_Use:
243 SetSeq(S_CanRelease);
244 return true;
245 case S_CanRelease:
246 case S_Release:
247 case S_MovableRelease:
248 case S_Stop:
249 case S_None:
250 return false;
251 case S_Retain:
252 llvm_unreachable("bottom-up pointer in retain state!");
253 }
Yaron Keren322bdad2015-03-06 07:49:14 +0000254 llvm_unreachable("Sequence unknown enum value");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000255}
256
257void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,
258 const Value *Ptr,
259 ProvenanceAnalysis &PA,
260 ARCInstKind Class) {
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000261 auto SetSeqAndInsertReverseInsertPt = [&](Sequence NewSeq){
262 assert(!HasReverseInsertPts());
263 SetSeq(NewSeq);
264 // If this is an invoke instruction, we're scanning it as part of
265 // one of its successor blocks, since we can't insert code after it
266 // in its own block, and we don't want to split critical edges.
Saleem Abdulrasool619b3262017-10-24 00:09:10 +0000267 BasicBlock::iterator InsertAfter;
268 if (isa<InvokeInst>(Inst)) {
269 const auto IP = BB->getFirstInsertionPt();
270 InsertAfter = IP == BB->end() ? std::prev(BB->end()) : IP;
Shoaib Meenai074728a2018-05-16 04:52:18 +0000271 if (isa<CatchSwitchInst>(InsertAfter))
272 // A catchswitch must be the only non-phi instruction in its basic
273 // block, so attempting to insert an instruction into such a block would
274 // produce invalid IR.
275 SetCFGHazardAfflicted(true);
Saleem Abdulrasool619b3262017-10-24 00:09:10 +0000276 } else {
277 InsertAfter = std::next(Inst->getIterator());
278 }
279 InsertReverseInsertPt(&*InsertAfter);
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000280 };
281
Michael Gottesman16e6a202015-03-06 02:07:12 +0000282 // Check for possible direct uses.
283 switch (GetSeq()) {
284 case S_Release:
285 case S_MovableRelease:
286 if (CanUse(Inst, Ptr, PA, Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000287 LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
288 << *Ptr << "\n");
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000289 SetSeqAndInsertReverseInsertPt(S_Use);
Michael Gottesman16e6a202015-03-06 02:07:12 +0000290 } else if (Seq == S_Release && IsUser(Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000291 LLVM_DEBUG(dbgs() << " PreciseReleaseUse: Seq: " << GetSeq()
292 << "; " << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000293 // Non-movable releases depend on any possible objc pointer use.
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000294 SetSeqAndInsertReverseInsertPt(S_Stop);
295 } else if (const auto *Call = getreturnRVOperand(*Inst, Class)) {
296 if (CanUse(Call, Ptr, PA, GetBasicARCInstKind(Call))) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000297 LLVM_DEBUG(dbgs() << " ReleaseUse: Seq: " << GetSeq() << "; "
298 << *Ptr << "\n");
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000299 SetSeqAndInsertReverseInsertPt(S_Stop);
300 }
Michael Gottesman16e6a202015-03-06 02:07:12 +0000301 }
302 break;
303 case S_Stop:
304 if (CanUse(Inst, Ptr, PA, Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000305 LLVM_DEBUG(dbgs() << " PreciseStopUse: Seq: " << GetSeq()
306 << "; " << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000307 SetSeq(S_Use);
308 }
309 break;
310 case S_CanRelease:
311 case S_Use:
312 case S_None:
313 break;
314 case S_Retain:
315 llvm_unreachable("bottom-up pointer in retain state!");
316 }
317}
318
319//===----------------------------------------------------------------------===//
320// TopDownPtrState
321//===----------------------------------------------------------------------===//
322
Michael Gottesman4eae3962015-03-06 00:34:39 +0000323bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
324 bool NestingDetected = false;
325 // Don't do retain+release tracking for ARCInstKind::RetainRV, because
326 // it's
327 // better to let it remain as the first instruction after a call.
328 if (Kind != ARCInstKind::RetainRV) {
329 // If we see two retains in a row on the same pointer. If so, make
330 // a note, and we'll cicle back to revisit it after we've
331 // hopefully eliminated the second retain, which may allow us to
332 // eliminate the first retain too.
333 // Theoretically we could implement removal of nested retain+release
334 // pairs by making PtrState hold a stack of states, but this is
335 // simple and avoids adding overhead for the non-nested case.
336 if (GetSeq() == S_Retain)
337 NestingDetected = true;
338
339 ResetSequenceProgress(S_Retain);
340 SetKnownSafe(HasKnownPositiveRefCount());
341 InsertCall(I);
342 }
343
344 SetKnownPositiveRefCount();
345 return NestingDetected;
346}
Michael Gottesman60805962015-03-06 00:34:42 +0000347
348bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
349 Instruction *Release) {
350 ClearKnownPositiveRefCount();
351
352 Sequence OldSeq = GetSeq();
353
Michael Gottesman65cb7372015-03-16 07:02:27 +0000354 MDNode *ReleaseMetadata =
355 Release->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
Michael Gottesman60805962015-03-06 00:34:42 +0000356
357 switch (OldSeq) {
358 case S_Retain:
359 case S_CanRelease:
360 if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
361 ClearReverseInsertPts();
Justin Bognercd1d5aa2016-08-17 20:30:52 +0000362 LLVM_FALLTHROUGH;
Michael Gottesman60805962015-03-06 00:34:42 +0000363 case S_Use:
364 SetReleaseMetadata(ReleaseMetadata);
365 SetTailCallRelease(cast<CallInst>(Release)->isTailCall());
366 return true;
367 case S_None:
368 return false;
369 case S_Stop:
370 case S_Release:
371 case S_MovableRelease:
372 llvm_unreachable("top-down pointer in bottom up state!");
373 }
Yaron Keren322bdad2015-03-06 07:49:14 +0000374 llvm_unreachable("Sequence unknown enum value");
Michael Gottesman60805962015-03-06 00:34:42 +0000375}
Michael Gottesman16e6a202015-03-06 02:07:12 +0000376
377bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
378 const Value *Ptr,
379 ProvenanceAnalysis &PA,
380 ARCInstKind Class) {
Akira Hatanaka490397f2017-04-25 04:06:35 +0000381 // Check for possible releases. Treat clang.arc.use as a releasing instruction
382 // to prevent sinking a retain past it.
383 if (!CanAlterRefCount(Inst, Ptr, PA, Class) &&
384 Class != ARCInstKind::IntrinsicUser)
Michael Gottesman16e6a202015-03-06 02:07:12 +0000385 return false;
386
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000387 LLVM_DEBUG(dbgs() << " CanAlterRefCount: Seq: " << GetSeq() << "; "
388 << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000389 ClearKnownPositiveRefCount();
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000390 switch (GetSeq()) {
Michael Gottesman16e6a202015-03-06 02:07:12 +0000391 case S_Retain:
392 SetSeq(S_CanRelease);
393 assert(!HasReverseInsertPts());
394 InsertReverseInsertPt(Inst);
395
396 // One call can't cause a transition from S_Retain to S_CanRelease
397 // and S_CanRelease to S_Use. If we've made the first transition,
398 // we're done.
399 return true;
400 case S_Use:
401 case S_CanRelease:
402 case S_None:
403 return false;
404 case S_Stop:
405 case S_Release:
406 case S_MovableRelease:
407 llvm_unreachable("top-down pointer in release state!");
408 }
409 llvm_unreachable("covered switch is not covered!?");
410}
411
412void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
413 ProvenanceAnalysis &PA,
414 ARCInstKind Class) {
415 // Check for possible direct uses.
416 switch (GetSeq()) {
417 case S_CanRelease:
418 if (!CanUse(Inst, Ptr, PA, Class))
419 return;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000420 LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
421 << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000422 SetSeq(S_Use);
423 return;
424 case S_Retain:
425 case S_Use:
426 case S_None:
427 return;
428 case S_Stop:
429 case S_Release:
430 case S_MovableRelease:
431 llvm_unreachable("top-down pointer in release state!");
432 }
433}