// Track the lifetime, release points, and released values referenced by a
// newly allocated object.
bool DeadObjectAnalysis::analyze() {
  DEBUG(llvm::dbgs() << "    Analyzing nontrivial dead object: "
        << NewAddrValue);

  // Populate AllValues, AddressProjectionTrie, and StoredLocations.
  AddressProjectionTrie = new IndexTrieNode();
  if (!recursivelyCollectInteriorUses(NewAddrValue,
                                      AddressProjectionTrie, false)) {
    return false;
  }
  // If all stores are leaves in the AddressProjectionTrie, then we can analyze
  // the stores that reach the end of the object lifetime. Otherwise bail.
  // This iteration order is nondeterministic but has no impact.
  for (auto &AddressToStoresPair : StoredLocations) {
    IndexTrieNode *Location = AddressToStoresPair.first;
    if (!Location->isLeaf())
      return false;
  }
  return true;
}
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;
}