const IndexTrieNode * AccessSummaryAnalysis::findSubPathAccessed(BeginAccessInst *BAI) { IndexTrieNode *SubPath = SubPathTrie; // For each single-user projection of BAI, construct or get a node // from the trie representing the index of the field or tuple element // accessed by that projection. SILInstruction *Iter = BAI; while (true) { std::pair<SILInstruction *, unsigned> ProjectionUser = getSingleAddressProjectionUser(Iter); if (!ProjectionUser.first) break; SubPath = SubPath->getChild(ProjectionUser.second); Iter = ProjectionUser.first; } return SubPath; }
// Collect instructions that either initialize or release any values at the // object defined by defInst. // // Populates AllUsers, AddressProjectionTrie, and StoredLocations. // // If a use is visited that potentially causes defInst's address to // escape, then return false without fully populating the data structures. // // `InteriorAddress` is true if the current address projection already includes // a struct/ref/tuple element address. index_addr is only expected at the top // level. The first non-index element address encountered pushes an "zero index" // address node to represent the implicit index_addr #0. We do not support // nested indexed data types in native SIL. bool DeadObjectAnalysis:: recursivelyCollectInteriorUses(ValueBase *DefInst, IndexTrieNode* AddressNode, bool IsInteriorAddress) { for (auto Op : DefInst->getUses()) { auto User = Op->getUser(); // Lifetime endpoints that don't allow the address to escape. if (isa<RefCountingInst>(User) || isa<DebugValueInst>(User)) { AllUsers.insert(User); continue; } // Initialization points. if (auto *Store = dyn_cast<StoreInst>(User)) { // Bail if this address is stored to another object. if (Store->getDest() != DefInst) { DEBUG(llvm::dbgs() << " Found an escaping store: " << *User); return false; } IndexTrieNode *StoreAddrNode = AddressNode; // Push an extra zero index node for a store to noninterior address. if (!IsInteriorAddress) StoreAddrNode = AddressNode->getChild(0); addStore(Store, StoreAddrNode); AllUsers.insert(User); continue; } if (isa<PointerToAddressInst>(User)) { // Only one pointer-to-address is allowed for safety. if (SeenPtrToAddr) return false; SeenPtrToAddr = true; if (!recursivelyCollectInteriorUses(User, AddressNode, IsInteriorAddress)) return false; continue; } // Recursively follow projections. ProjectionIndex PI(User); if (PI.isValid()) { IndexTrieNode *ProjAddrNode = AddressNode; bool ProjInteriorAddr = IsInteriorAddress; if (Projection::isAddrProjection(User)) { if (User->getKind() == ValueKind::IndexAddrInst) { // Don't support indexing within an interior address. if (IsInteriorAddress) return false; } else if (!IsInteriorAddress) { // Push an extra zero index node for the first interior address. ProjAddrNode = AddressNode->getChild(0); ProjInteriorAddr = true; } } else if (IsInteriorAddress) { // Don't expect to extract values once we've taken an address. return false; } if (!recursivelyCollectInteriorUses(User, ProjAddrNode->getChild(PI.Index), ProjInteriorAddr)) { return false; } continue; } // Otherwise bail. DEBUG(llvm::dbgs() << " Found an escaping use: " << *User); return false; } return true; }