157bd5a02SEugene Zelenko //===- PtrState.cpp -------------------------------------------------------===//
268b91dbfSMichael Gottesman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668b91dbfSMichael Gottesman //
768b91dbfSMichael Gottesman //===----------------------------------------------------------------------===//
868b91dbfSMichael Gottesman
968b91dbfSMichael Gottesman #include "PtrState.h"
1016e6a205SMichael Gottesman #include "DependencyAnalysis.h"
11799003bfSBenjamin Kramer #include "ObjCARC.h"
1257bd5a02SEugene Zelenko #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
1357bd5a02SEugene Zelenko #include "llvm/Analysis/ObjCARCInstKind.h"
14*dca57379SAkira Hatanaka #include "llvm/Analysis/ObjCARCUtil.h"
1557bd5a02SEugene Zelenko #include "llvm/IR/BasicBlock.h"
1657bd5a02SEugene Zelenko #include "llvm/IR/Instruction.h"
1757bd5a02SEugene Zelenko #include "llvm/IR/Instructions.h"
1857bd5a02SEugene Zelenko #include "llvm/IR/Value.h"
1957bd5a02SEugene Zelenko #include "llvm/Support/Casting.h"
2057bd5a02SEugene Zelenko #include "llvm/Support/Compiler.h"
21799003bfSBenjamin Kramer #include "llvm/Support/Debug.h"
2257bd5a02SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
23799003bfSBenjamin Kramer #include "llvm/Support/raw_ostream.h"
2457bd5a02SEugene Zelenko #include <cassert>
2557bd5a02SEugene Zelenko #include <iterator>
2657bd5a02SEugene Zelenko #include <utility>
2768b91dbfSMichael Gottesman
2868b91dbfSMichael Gottesman using namespace llvm;
2968b91dbfSMichael Gottesman using namespace llvm::objcarc;
3068b91dbfSMichael Gottesman
31799003bfSBenjamin Kramer #define DEBUG_TYPE "objc-arc-ptr-state"
32799003bfSBenjamin Kramer
3316e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
3416e6a205SMichael Gottesman // Utility
3516e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
3616e6a205SMichael Gottesman
operator <<(raw_ostream & OS,const Sequence S)37d45907bdSMichael Gottesman raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
3868b91dbfSMichael Gottesman switch (S) {
3968b91dbfSMichael Gottesman case S_None:
4068b91dbfSMichael Gottesman return OS << "S_None";
4168b91dbfSMichael Gottesman case S_Retain:
4268b91dbfSMichael Gottesman return OS << "S_Retain";
4368b91dbfSMichael Gottesman case S_CanRelease:
4468b91dbfSMichael Gottesman return OS << "S_CanRelease";
4568b91dbfSMichael Gottesman case S_Use:
4668b91dbfSMichael Gottesman return OS << "S_Use";
4768b91dbfSMichael Gottesman case S_MovableRelease:
4868b91dbfSMichael Gottesman return OS << "S_MovableRelease";
4968b91dbfSMichael Gottesman case S_Stop:
5068b91dbfSMichael Gottesman return OS << "S_Stop";
5168b91dbfSMichael Gottesman }
5268b91dbfSMichael Gottesman llvm_unreachable("Unknown sequence type.");
5368b91dbfSMichael Gottesman }
5468b91dbfSMichael Gottesman
5516e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
5616e6a205SMichael Gottesman // Sequence
5716e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
5816e6a205SMichael Gottesman
MergeSeqs(Sequence A,Sequence B,bool TopDown)5968b91dbfSMichael Gottesman static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
6068b91dbfSMichael Gottesman // The easy cases.
6168b91dbfSMichael Gottesman if (A == B)
6268b91dbfSMichael Gottesman return A;
6368b91dbfSMichael Gottesman if (A == S_None || B == S_None)
6468b91dbfSMichael Gottesman return S_None;
6568b91dbfSMichael Gottesman
6668b91dbfSMichael Gottesman if (A > B)
6768b91dbfSMichael Gottesman std::swap(A, B);
6868b91dbfSMichael Gottesman if (TopDown) {
6968b91dbfSMichael Gottesman // Choose the side which is further along in the sequence.
7068b91dbfSMichael Gottesman if ((A == S_Retain || A == S_CanRelease) &&
7168b91dbfSMichael Gottesman (B == S_CanRelease || B == S_Use))
7268b91dbfSMichael Gottesman return B;
7368b91dbfSMichael Gottesman } else {
7468b91dbfSMichael Gottesman // Choose the side which is further along in the sequence.
7568b91dbfSMichael Gottesman if ((A == S_Use || A == S_CanRelease) &&
7632dc79c5SAkira Hatanaka (B == S_Use || B == S_Stop || B == S_MovableRelease))
7768b91dbfSMichael Gottesman return A;
7868b91dbfSMichael Gottesman // If both sides are releases, choose the more conservative one.
7932dc79c5SAkira Hatanaka if (A == S_Stop && B == S_MovableRelease)
8068b91dbfSMichael Gottesman return A;
8168b91dbfSMichael Gottesman }
8268b91dbfSMichael Gottesman
8368b91dbfSMichael Gottesman return S_None;
8468b91dbfSMichael Gottesman }
8568b91dbfSMichael Gottesman
8616e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
8716e6a205SMichael Gottesman // RRInfo
8816e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
8916e6a205SMichael Gottesman
clear()9068b91dbfSMichael Gottesman void RRInfo::clear() {
9168b91dbfSMichael Gottesman KnownSafe = false;
9268b91dbfSMichael Gottesman IsTailCallRelease = false;
9368b91dbfSMichael Gottesman ReleaseMetadata = nullptr;
9468b91dbfSMichael Gottesman Calls.clear();
9568b91dbfSMichael Gottesman ReverseInsertPts.clear();
9668b91dbfSMichael Gottesman CFGHazardAfflicted = false;
9768b91dbfSMichael Gottesman }
9868b91dbfSMichael Gottesman
Merge(const RRInfo & Other)9968b91dbfSMichael Gottesman bool RRInfo::Merge(const RRInfo &Other) {
10068b91dbfSMichael Gottesman // Conservatively merge the ReleaseMetadata information.
10168b91dbfSMichael Gottesman if (ReleaseMetadata != Other.ReleaseMetadata)
10268b91dbfSMichael Gottesman ReleaseMetadata = nullptr;
10368b91dbfSMichael Gottesman
10468b91dbfSMichael Gottesman // Conservatively merge the boolean state.
10568b91dbfSMichael Gottesman KnownSafe &= Other.KnownSafe;
10668b91dbfSMichael Gottesman IsTailCallRelease &= Other.IsTailCallRelease;
10768b91dbfSMichael Gottesman CFGHazardAfflicted |= Other.CFGHazardAfflicted;
10868b91dbfSMichael Gottesman
10968b91dbfSMichael Gottesman // Merge the call sets.
11068b91dbfSMichael Gottesman Calls.insert(Other.Calls.begin(), Other.Calls.end());
11168b91dbfSMichael Gottesman
11268b91dbfSMichael Gottesman // Merge the insert point sets. If there are any differences,
11368b91dbfSMichael Gottesman // that makes this a partial merge.
11468b91dbfSMichael Gottesman bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
11568b91dbfSMichael Gottesman for (Instruction *Inst : Other.ReverseInsertPts)
11668b91dbfSMichael Gottesman Partial |= ReverseInsertPts.insert(Inst).second;
11768b91dbfSMichael Gottesman return Partial;
11868b91dbfSMichael Gottesman }
11968b91dbfSMichael Gottesman
12016e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
12116e6a205SMichael Gottesman // PtrState
12216e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
12316e6a205SMichael Gottesman
SetKnownPositiveRefCount()124d45907bdSMichael Gottesman void PtrState::SetKnownPositiveRefCount() {
125d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Setting Known Positive.\n");
126d45907bdSMichael Gottesman KnownPositiveRefCount = true;
127d45907bdSMichael Gottesman }
128d45907bdSMichael Gottesman
ClearKnownPositiveRefCount()129d45907bdSMichael Gottesman void PtrState::ClearKnownPositiveRefCount() {
130d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Clearing Known Positive.\n");
131d45907bdSMichael Gottesman KnownPositiveRefCount = false;
132d45907bdSMichael Gottesman }
133d45907bdSMichael Gottesman
SetSeq(Sequence NewSeq)134d45907bdSMichael Gottesman void PtrState::SetSeq(Sequence NewSeq) {
135d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Old: " << GetSeq() << "; New: " << NewSeq
136d34e60caSNicola Zaghen << "\n");
137d45907bdSMichael Gottesman Seq = NewSeq;
138d45907bdSMichael Gottesman }
139d45907bdSMichael Gottesman
ResetSequenceProgress(Sequence NewSeq)140d45907bdSMichael Gottesman void PtrState::ResetSequenceProgress(Sequence NewSeq) {
141d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Resetting sequence progress.\n");
142d45907bdSMichael Gottesman SetSeq(NewSeq);
143d45907bdSMichael Gottesman Partial = false;
144d45907bdSMichael Gottesman RRI.clear();
145d45907bdSMichael Gottesman }
146d45907bdSMichael Gottesman
Merge(const PtrState & Other,bool TopDown)14768b91dbfSMichael Gottesman void PtrState::Merge(const PtrState &Other, bool TopDown) {
14868b91dbfSMichael Gottesman Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
14968b91dbfSMichael Gottesman KnownPositiveRefCount &= Other.KnownPositiveRefCount;
15068b91dbfSMichael Gottesman
15168b91dbfSMichael Gottesman // If we're not in a sequence (anymore), drop all associated state.
15268b91dbfSMichael Gottesman if (Seq == S_None) {
15368b91dbfSMichael Gottesman Partial = false;
15468b91dbfSMichael Gottesman RRI.clear();
15568b91dbfSMichael Gottesman } else if (Partial || Other.Partial) {
15668b91dbfSMichael Gottesman // If we're doing a merge on a path that's previously seen a partial
15768b91dbfSMichael Gottesman // merge, conservatively drop the sequence, to avoid doing partial
15868b91dbfSMichael Gottesman // RR elimination. If the branch predicates for the two merge differ,
15968b91dbfSMichael Gottesman // mixing them is unsafe.
16068b91dbfSMichael Gottesman ClearSequenceProgress();
16168b91dbfSMichael Gottesman } else {
16268b91dbfSMichael Gottesman // Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
16368b91dbfSMichael Gottesman // point, we know that currently we are not partial. Stash whether or not
16468b91dbfSMichael Gottesman // the merge operation caused us to undergo a partial merging of reverse
16568b91dbfSMichael Gottesman // insertion points.
16668b91dbfSMichael Gottesman Partial = RRI.Merge(Other.RRI);
16768b91dbfSMichael Gottesman }
16868b91dbfSMichael Gottesman }
1694eae396aSMichael Gottesman
17016e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
17116e6a205SMichael Gottesman // BottomUpPtrState
17216e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
17316e6a205SMichael Gottesman
InitBottomUp(ARCMDKindCache & Cache,Instruction * I)1744eae396aSMichael Gottesman bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
1754eae396aSMichael Gottesman // If we see two releases in a row on the same pointer. If so, make
1764eae396aSMichael Gottesman // a note, and we'll cicle back to revisit it after we've
1774eae396aSMichael Gottesman // hopefully eliminated the second release, which may allow us to
1784eae396aSMichael Gottesman // eliminate the first release too.
1794eae396aSMichael Gottesman // Theoretically we could implement removal of nested retain+release
1804eae396aSMichael Gottesman // pairs by making PtrState hold a stack of states, but this is
1814eae396aSMichael Gottesman // simple and avoids adding overhead for the non-nested case.
1824eae396aSMichael Gottesman bool NestingDetected = false;
18332dc79c5SAkira Hatanaka if (GetSeq() == S_MovableRelease) {
184d34e60caSNicola Zaghen LLVM_DEBUG(
185d34e60caSNicola Zaghen dbgs() << " Found nested releases (i.e. a release pair)\n");
1864eae396aSMichael Gottesman NestingDetected = true;
1874eae396aSMichael Gottesman }
1884eae396aSMichael Gottesman
18965cb7377SMichael Gottesman MDNode *ReleaseMetadata =
19065cb7377SMichael Gottesman I->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
19132dc79c5SAkira Hatanaka Sequence NewSeq = ReleaseMetadata ? S_MovableRelease : S_Stop;
1924eae396aSMichael Gottesman ResetSequenceProgress(NewSeq);
19332dc79c5SAkira Hatanaka if (NewSeq == S_Stop)
19432dc79c5SAkira Hatanaka InsertReverseInsertPt(I);
1954eae396aSMichael Gottesman SetReleaseMetadata(ReleaseMetadata);
1964eae396aSMichael Gottesman SetKnownSafe(HasKnownPositiveRefCount());
1974eae396aSMichael Gottesman SetTailCallRelease(cast<CallInst>(I)->isTailCall());
1984eae396aSMichael Gottesman InsertCall(I);
1994eae396aSMichael Gottesman SetKnownPositiveRefCount();
2004eae396aSMichael Gottesman return NestingDetected;
2014eae396aSMichael Gottesman }
2024eae396aSMichael Gottesman
MatchWithRetain()20360805963SMichael Gottesman bool BottomUpPtrState::MatchWithRetain() {
20460805963SMichael Gottesman SetKnownPositiveRefCount();
20560805963SMichael Gottesman
20660805963SMichael Gottesman Sequence OldSeq = GetSeq();
20760805963SMichael Gottesman switch (OldSeq) {
20860805963SMichael Gottesman case S_Stop:
20960805963SMichael Gottesman case S_MovableRelease:
21060805963SMichael Gottesman case S_Use:
21160805963SMichael Gottesman // If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
21260805963SMichael Gottesman // imprecise release, clear our reverse insertion points.
21360805963SMichael Gottesman if (OldSeq != S_Use || IsTrackingImpreciseReleases())
21460805963SMichael Gottesman ClearReverseInsertPts();
215cd1d5aafSJustin Bogner LLVM_FALLTHROUGH;
21660805963SMichael Gottesman case S_CanRelease:
21760805963SMichael Gottesman return true;
21860805963SMichael Gottesman case S_None:
21960805963SMichael Gottesman return false;
22060805963SMichael Gottesman case S_Retain:
22160805963SMichael Gottesman llvm_unreachable("bottom-up pointer in retain state!");
22260805963SMichael Gottesman }
223322bdad0SYaron Keren llvm_unreachable("Sequence unknown enum value");
22460805963SMichael Gottesman }
22560805963SMichael Gottesman
HandlePotentialAlterRefCount(Instruction * Inst,const Value * Ptr,ProvenanceAnalysis & PA,ARCInstKind Class)22616e6a205SMichael Gottesman bool BottomUpPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
22716e6a205SMichael Gottesman const Value *Ptr,
22816e6a205SMichael Gottesman ProvenanceAnalysis &PA,
22916e6a205SMichael Gottesman ARCInstKind Class) {
230c01ab519SMichael Gottesman Sequence S = GetSeq();
23116e6a205SMichael Gottesman
23216e6a205SMichael Gottesman // Check for possible releases.
2330231a4e5SAkira Hatanaka if (!CanDecrementRefCount(Inst, Ptr, PA, Class))
23416e6a205SMichael Gottesman return false;
23516e6a205SMichael Gottesman
236d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " CanAlterRefCount: Seq: " << S << "; "
237d34e60caSNicola Zaghen << *Ptr << "\n");
238c01ab519SMichael Gottesman switch (S) {
23916e6a205SMichael Gottesman case S_Use:
24016e6a205SMichael Gottesman SetSeq(S_CanRelease);
24116e6a205SMichael Gottesman return true;
24216e6a205SMichael Gottesman case S_CanRelease:
24316e6a205SMichael Gottesman case S_MovableRelease:
24416e6a205SMichael Gottesman case S_Stop:
24516e6a205SMichael Gottesman case S_None:
24616e6a205SMichael Gottesman return false;
24716e6a205SMichael Gottesman case S_Retain:
24816e6a205SMichael Gottesman llvm_unreachable("bottom-up pointer in retain state!");
24916e6a205SMichael Gottesman }
250322bdad0SYaron Keren llvm_unreachable("Sequence unknown enum value");
25116e6a205SMichael Gottesman }
25216e6a205SMichael Gottesman
HandlePotentialUse(BasicBlock * BB,Instruction * Inst,const Value * Ptr,ProvenanceAnalysis & PA,ARCInstKind Class)25316e6a205SMichael Gottesman void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,
25416e6a205SMichael Gottesman const Value *Ptr,
25516e6a205SMichael Gottesman ProvenanceAnalysis &PA,
25616e6a205SMichael Gottesman ARCInstKind Class) {
2576fdcb3c2SAkira Hatanaka auto SetSeqAndInsertReverseInsertPt = [&](Sequence NewSeq){
25816e6a205SMichael Gottesman assert(!HasReverseInsertPts());
2596fdcb3c2SAkira Hatanaka SetSeq(NewSeq);
26016e6a205SMichael Gottesman // If this is an invoke instruction, we're scanning it as part of
26116e6a205SMichael Gottesman // one of its successor blocks, since we can't insert code after it
26216e6a205SMichael Gottesman // in its own block, and we don't want to split critical edges.
263619b3269SSaleem Abdulrasool BasicBlock::iterator InsertAfter;
264619b3269SSaleem Abdulrasool if (isa<InvokeInst>(Inst)) {
265619b3269SSaleem Abdulrasool const auto IP = BB->getFirstInsertionPt();
266619b3269SSaleem Abdulrasool InsertAfter = IP == BB->end() ? std::prev(BB->end()) : IP;
267074728a2SShoaib Meenai if (isa<CatchSwitchInst>(InsertAfter))
268074728a2SShoaib Meenai // A catchswitch must be the only non-phi instruction in its basic
269074728a2SShoaib Meenai // block, so attempting to insert an instruction into such a block would
270074728a2SShoaib Meenai // produce invalid IR.
271074728a2SShoaib Meenai SetCFGHazardAfflicted(true);
272619b3269SSaleem Abdulrasool } else {
273619b3269SSaleem Abdulrasool InsertAfter = std::next(Inst->getIterator());
274619b3269SSaleem Abdulrasool }
27575fbb171SAkira Hatanaka
27675fbb171SAkira Hatanaka if (InsertAfter != BB->end())
27775fbb171SAkira Hatanaka InsertAfter = skipDebugIntrinsics(InsertAfter);
27875fbb171SAkira Hatanaka
279619b3269SSaleem Abdulrasool InsertReverseInsertPt(&*InsertAfter);
28019005035SAkira Hatanaka
28119005035SAkira Hatanaka // Don't insert anything between a call/invoke with operand bundle
28219005035SAkira Hatanaka // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call
28319005035SAkira Hatanaka // result.
28419005035SAkira Hatanaka if (auto *CB = dyn_cast<CallBase>(Inst))
28519005035SAkira Hatanaka if (objcarc::hasAttachedCallOpBundle(CB))
28619005035SAkira Hatanaka SetCFGHazardAfflicted(true);
2876fdcb3c2SAkira Hatanaka };
2886fdcb3c2SAkira Hatanaka
2896fdcb3c2SAkira Hatanaka // Check for possible direct uses.
2906fdcb3c2SAkira Hatanaka switch (GetSeq()) {
2916fdcb3c2SAkira Hatanaka case S_MovableRelease:
2926fdcb3c2SAkira Hatanaka if (CanUse(Inst, Ptr, PA, Class)) {
293d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
294d34e60caSNicola Zaghen << *Ptr << "\n");
2956fdcb3c2SAkira Hatanaka SetSeqAndInsertReverseInsertPt(S_Use);
2966fdcb3c2SAkira Hatanaka } else if (const auto *Call = getreturnRVOperand(*Inst, Class)) {
2976fdcb3c2SAkira Hatanaka if (CanUse(Call, Ptr, PA, GetBasicARCInstKind(Call))) {
298d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " ReleaseUse: Seq: " << GetSeq() << "; "
2996fdcb3c2SAkira Hatanaka << *Ptr << "\n");
3006fdcb3c2SAkira Hatanaka SetSeqAndInsertReverseInsertPt(S_Stop);
3016fdcb3c2SAkira Hatanaka }
30216e6a205SMichael Gottesman }
30316e6a205SMichael Gottesman break;
30416e6a205SMichael Gottesman case S_Stop:
30516e6a205SMichael Gottesman if (CanUse(Inst, Ptr, PA, Class)) {
306d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " PreciseStopUse: Seq: " << GetSeq()
307d34e60caSNicola Zaghen << "; " << *Ptr << "\n");
30816e6a205SMichael Gottesman SetSeq(S_Use);
30916e6a205SMichael Gottesman }
31016e6a205SMichael Gottesman break;
31116e6a205SMichael Gottesman case S_CanRelease:
31216e6a205SMichael Gottesman case S_Use:
31316e6a205SMichael Gottesman case S_None:
31416e6a205SMichael Gottesman break;
31516e6a205SMichael Gottesman case S_Retain:
31616e6a205SMichael Gottesman llvm_unreachable("bottom-up pointer in retain state!");
31716e6a205SMichael Gottesman }
31816e6a205SMichael Gottesman }
31916e6a205SMichael Gottesman
32016e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
32116e6a205SMichael Gottesman // TopDownPtrState
32216e6a205SMichael Gottesman //===----------------------------------------------------------------------===//
32316e6a205SMichael Gottesman
InitTopDown(ARCInstKind Kind,Instruction * I)3244eae396aSMichael Gottesman bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
3254eae396aSMichael Gottesman bool NestingDetected = false;
3264eae396aSMichael Gottesman // Don't do retain+release tracking for ARCInstKind::RetainRV, because
3274eae396aSMichael Gottesman // it's
3284eae396aSMichael Gottesman // better to let it remain as the first instruction after a call.
3294eae396aSMichael Gottesman if (Kind != ARCInstKind::RetainRV) {
3304eae396aSMichael Gottesman // If we see two retains in a row on the same pointer. If so, make
3314eae396aSMichael Gottesman // a note, and we'll cicle back to revisit it after we've
3324eae396aSMichael Gottesman // hopefully eliminated the second retain, which may allow us to
3334eae396aSMichael Gottesman // eliminate the first retain too.
3344eae396aSMichael Gottesman // Theoretically we could implement removal of nested retain+release
3354eae396aSMichael Gottesman // pairs by making PtrState hold a stack of states, but this is
3364eae396aSMichael Gottesman // simple and avoids adding overhead for the non-nested case.
3374eae396aSMichael Gottesman if (GetSeq() == S_Retain)
3384eae396aSMichael Gottesman NestingDetected = true;
3394eae396aSMichael Gottesman
3404eae396aSMichael Gottesman ResetSequenceProgress(S_Retain);
3414eae396aSMichael Gottesman SetKnownSafe(HasKnownPositiveRefCount());
3424eae396aSMichael Gottesman InsertCall(I);
3434eae396aSMichael Gottesman }
3444eae396aSMichael Gottesman
3454eae396aSMichael Gottesman SetKnownPositiveRefCount();
3464eae396aSMichael Gottesman return NestingDetected;
3474eae396aSMichael Gottesman }
34860805963SMichael Gottesman
MatchWithRelease(ARCMDKindCache & Cache,Instruction * Release)34960805963SMichael Gottesman bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
35060805963SMichael Gottesman Instruction *Release) {
35160805963SMichael Gottesman ClearKnownPositiveRefCount();
35260805963SMichael Gottesman
35360805963SMichael Gottesman Sequence OldSeq = GetSeq();
35460805963SMichael Gottesman
35565cb7377SMichael Gottesman MDNode *ReleaseMetadata =
35665cb7377SMichael Gottesman Release->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
35760805963SMichael Gottesman
35860805963SMichael Gottesman switch (OldSeq) {
35960805963SMichael Gottesman case S_Retain:
36060805963SMichael Gottesman case S_CanRelease:
36160805963SMichael Gottesman if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
36260805963SMichael Gottesman ClearReverseInsertPts();
363cd1d5aafSJustin Bogner LLVM_FALLTHROUGH;
36460805963SMichael Gottesman case S_Use:
36560805963SMichael Gottesman SetReleaseMetadata(ReleaseMetadata);
36660805963SMichael Gottesman SetTailCallRelease(cast<CallInst>(Release)->isTailCall());
36760805963SMichael Gottesman return true;
36860805963SMichael Gottesman case S_None:
36960805963SMichael Gottesman return false;
37060805963SMichael Gottesman case S_Stop:
37160805963SMichael Gottesman case S_MovableRelease:
37260805963SMichael Gottesman llvm_unreachable("top-down pointer in bottom up state!");
37360805963SMichael Gottesman }
374322bdad0SYaron Keren llvm_unreachable("Sequence unknown enum value");
37560805963SMichael Gottesman }
37616e6a205SMichael Gottesman
HandlePotentialAlterRefCount(Instruction * Inst,const Value * Ptr,ProvenanceAnalysis & PA,ARCInstKind Class,const BundledRetainClaimRVs & BundledRVs)37719005035SAkira Hatanaka bool TopDownPtrState::HandlePotentialAlterRefCount(
37819005035SAkira Hatanaka Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA,
37919005035SAkira Hatanaka ARCInstKind Class, const BundledRetainClaimRVs &BundledRVs) {
380490397fcSAkira Hatanaka // Check for possible releases. Treat clang.arc.use as a releasing instruction
381490397fcSAkira Hatanaka // to prevent sinking a retain past it.
3820231a4e5SAkira Hatanaka if (!CanDecrementRefCount(Inst, Ptr, PA, Class) &&
383490397fcSAkira Hatanaka Class != ARCInstKind::IntrinsicUser)
38416e6a205SMichael Gottesman return false;
38516e6a205SMichael Gottesman
386d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " CanAlterRefCount: Seq: " << GetSeq() << "; "
387d34e60caSNicola Zaghen << *Ptr << "\n");
38816e6a205SMichael Gottesman ClearKnownPositiveRefCount();
389c01ab519SMichael Gottesman switch (GetSeq()) {
39016e6a205SMichael Gottesman case S_Retain:
39116e6a205SMichael Gottesman SetSeq(S_CanRelease);
39216e6a205SMichael Gottesman assert(!HasReverseInsertPts());
39316e6a205SMichael Gottesman InsertReverseInsertPt(Inst);
39416e6a205SMichael Gottesman
39519005035SAkira Hatanaka // Don't insert anything between a call/invoke with operand bundle
39619005035SAkira Hatanaka // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call
39719005035SAkira Hatanaka // result.
39819005035SAkira Hatanaka if (BundledRVs.contains(Inst))
39919005035SAkira Hatanaka SetCFGHazardAfflicted(true);
40019005035SAkira Hatanaka
40116e6a205SMichael Gottesman // One call can't cause a transition from S_Retain to S_CanRelease
40216e6a205SMichael Gottesman // and S_CanRelease to S_Use. If we've made the first transition,
40316e6a205SMichael Gottesman // we're done.
40416e6a205SMichael Gottesman return true;
40516e6a205SMichael Gottesman case S_Use:
40616e6a205SMichael Gottesman case S_CanRelease:
40716e6a205SMichael Gottesman case S_None:
40816e6a205SMichael Gottesman return false;
40916e6a205SMichael Gottesman case S_Stop:
41016e6a205SMichael Gottesman case S_MovableRelease:
41116e6a205SMichael Gottesman llvm_unreachable("top-down pointer in release state!");
41216e6a205SMichael Gottesman }
41316e6a205SMichael Gottesman llvm_unreachable("covered switch is not covered!?");
41416e6a205SMichael Gottesman }
41516e6a205SMichael Gottesman
HandlePotentialUse(Instruction * Inst,const Value * Ptr,ProvenanceAnalysis & PA,ARCInstKind Class)41616e6a205SMichael Gottesman void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
41716e6a205SMichael Gottesman ProvenanceAnalysis &PA,
41816e6a205SMichael Gottesman ARCInstKind Class) {
41916e6a205SMichael Gottesman // Check for possible direct uses.
42016e6a205SMichael Gottesman switch (GetSeq()) {
42116e6a205SMichael Gottesman case S_CanRelease:
42216e6a205SMichael Gottesman if (!CanUse(Inst, Ptr, PA, Class))
42316e6a205SMichael Gottesman return;
424d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " CanUse: Seq: " << GetSeq() << "; "
425d34e60caSNicola Zaghen << *Ptr << "\n");
42616e6a205SMichael Gottesman SetSeq(S_Use);
42716e6a205SMichael Gottesman return;
42816e6a205SMichael Gottesman case S_Retain:
42916e6a205SMichael Gottesman case S_Use:
43016e6a205SMichael Gottesman case S_None:
43116e6a205SMichael Gottesman return;
43216e6a205SMichael Gottesman case S_Stop:
43316e6a205SMichael Gottesman case S_MovableRelease:
43416e6a205SMichael Gottesman llvm_unreachable("top-down pointer in release state!");
43516e6a205SMichael Gottesman }
43616e6a205SMichael Gottesman }
437