blob: b6c48529de43ac346adc1ea5e450fe5e6f4e4b96 [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;
271 } else {
272 InsertAfter = std::next(Inst->getIterator());
273 }
274 InsertReverseInsertPt(&*InsertAfter);
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000275 };
276
Michael Gottesman16e6a202015-03-06 02:07:12 +0000277 // Check for possible direct uses.
278 switch (GetSeq()) {
279 case S_Release:
280 case S_MovableRelease:
281 if (CanUse(Inst, Ptr, PA, Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000282 LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
283 << *Ptr << "\n");
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000284 SetSeqAndInsertReverseInsertPt(S_Use);
Michael Gottesman16e6a202015-03-06 02:07:12 +0000285 } else if (Seq == S_Release && IsUser(Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000286 LLVM_DEBUG(dbgs() << " PreciseReleaseUse: Seq: " << GetSeq()
287 << "; " << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000288 // Non-movable releases depend on any possible objc pointer use.
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000289 SetSeqAndInsertReverseInsertPt(S_Stop);
290 } else if (const auto *Call = getreturnRVOperand(*Inst, Class)) {
291 if (CanUse(Call, Ptr, PA, GetBasicARCInstKind(Call))) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000292 LLVM_DEBUG(dbgs() << " ReleaseUse: Seq: " << GetSeq() << "; "
293 << *Ptr << "\n");
Akira Hatanaka6fdcb3c2017-04-29 00:23:11 +0000294 SetSeqAndInsertReverseInsertPt(S_Stop);
295 }
Michael Gottesman16e6a202015-03-06 02:07:12 +0000296 }
297 break;
298 case S_Stop:
299 if (CanUse(Inst, Ptr, PA, Class)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000300 LLVM_DEBUG(dbgs() << " PreciseStopUse: Seq: " << GetSeq()
301 << "; " << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000302 SetSeq(S_Use);
303 }
304 break;
305 case S_CanRelease:
306 case S_Use:
307 case S_None:
308 break;
309 case S_Retain:
310 llvm_unreachable("bottom-up pointer in retain state!");
311 }
312}
313
314//===----------------------------------------------------------------------===//
315// TopDownPtrState
316//===----------------------------------------------------------------------===//
317
Michael Gottesman4eae3962015-03-06 00:34:39 +0000318bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
319 bool NestingDetected = false;
320 // Don't do retain+release tracking for ARCInstKind::RetainRV, because
321 // it's
322 // better to let it remain as the first instruction after a call.
323 if (Kind != ARCInstKind::RetainRV) {
324 // If we see two retains in a row on the same pointer. If so, make
325 // a note, and we'll cicle back to revisit it after we've
326 // hopefully eliminated the second retain, which may allow us to
327 // eliminate the first retain too.
328 // Theoretically we could implement removal of nested retain+release
329 // pairs by making PtrState hold a stack of states, but this is
330 // simple and avoids adding overhead for the non-nested case.
331 if (GetSeq() == S_Retain)
332 NestingDetected = true;
333
334 ResetSequenceProgress(S_Retain);
335 SetKnownSafe(HasKnownPositiveRefCount());
336 InsertCall(I);
337 }
338
339 SetKnownPositiveRefCount();
340 return NestingDetected;
341}
Michael Gottesman60805962015-03-06 00:34:42 +0000342
343bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
344 Instruction *Release) {
345 ClearKnownPositiveRefCount();
346
347 Sequence OldSeq = GetSeq();
348
Michael Gottesman65cb7372015-03-16 07:02:27 +0000349 MDNode *ReleaseMetadata =
350 Release->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
Michael Gottesman60805962015-03-06 00:34:42 +0000351
352 switch (OldSeq) {
353 case S_Retain:
354 case S_CanRelease:
355 if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
356 ClearReverseInsertPts();
Justin Bognercd1d5aa2016-08-17 20:30:52 +0000357 LLVM_FALLTHROUGH;
Michael Gottesman60805962015-03-06 00:34:42 +0000358 case S_Use:
359 SetReleaseMetadata(ReleaseMetadata);
360 SetTailCallRelease(cast<CallInst>(Release)->isTailCall());
361 return true;
362 case S_None:
363 return false;
364 case S_Stop:
365 case S_Release:
366 case S_MovableRelease:
367 llvm_unreachable("top-down pointer in bottom up state!");
368 }
Yaron Keren322bdad2015-03-06 07:49:14 +0000369 llvm_unreachable("Sequence unknown enum value");
Michael Gottesman60805962015-03-06 00:34:42 +0000370}
Michael Gottesman16e6a202015-03-06 02:07:12 +0000371
372bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
373 const Value *Ptr,
374 ProvenanceAnalysis &PA,
375 ARCInstKind Class) {
Akira Hatanaka490397f2017-04-25 04:06:35 +0000376 // Check for possible releases. Treat clang.arc.use as a releasing instruction
377 // to prevent sinking a retain past it.
378 if (!CanAlterRefCount(Inst, Ptr, PA, Class) &&
379 Class != ARCInstKind::IntrinsicUser)
Michael Gottesman16e6a202015-03-06 02:07:12 +0000380 return false;
381
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000382 LLVM_DEBUG(dbgs() << " CanAlterRefCount: Seq: " << GetSeq() << "; "
383 << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000384 ClearKnownPositiveRefCount();
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000385 switch (GetSeq()) {
Michael Gottesman16e6a202015-03-06 02:07:12 +0000386 case S_Retain:
387 SetSeq(S_CanRelease);
388 assert(!HasReverseInsertPts());
389 InsertReverseInsertPt(Inst);
390
391 // One call can't cause a transition from S_Retain to S_CanRelease
392 // and S_CanRelease to S_Use. If we've made the first transition,
393 // we're done.
394 return true;
395 case S_Use:
396 case S_CanRelease:
397 case S_None:
398 return false;
399 case S_Stop:
400 case S_Release:
401 case S_MovableRelease:
402 llvm_unreachable("top-down pointer in release state!");
403 }
404 llvm_unreachable("covered switch is not covered!?");
405}
406
407void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
408 ProvenanceAnalysis &PA,
409 ARCInstKind Class) {
410 // Check for possible direct uses.
411 switch (GetSeq()) {
412 case S_CanRelease:
413 if (!CanUse(Inst, Ptr, PA, Class))
414 return;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000415 LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
416 << *Ptr << "\n");
Michael Gottesman16e6a202015-03-06 02:07:12 +0000417 SetSeq(S_Use);
418 return;
419 case S_Retain:
420 case S_Use:
421 case S_None:
422 return;
423 case S_Stop:
424 case S_Release:
425 case S_MovableRelease:
426 llvm_unreachable("top-down pointer in release state!");
427 }
428}