[capture-promotion] Change isNonEscapingUse to use a visitor.
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 601bb7c..18a7b36 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -630,88 +630,143 @@
   return true;
 }
 
+namespace {
+
+class NonEscapingUserVisitor
+    : public SILInstructionVisitor<NonEscapingUserVisitor, bool> {
+  llvm::SmallVector<Operand *, 32> Worklist;
+  llvm::SmallVectorImpl<SILInstruction *> &Mutations;
+  NullablePtr<Operand> CurrentOp;
+
+public:
+  NonEscapingUserVisitor(Operand *Op,
+                         llvm::SmallVectorImpl<SILInstruction *> &Mutations)
+      : Worklist(), Mutations(Mutations), CurrentOp() {
+    Worklist.push_back(Op);
+  }
+
+  NonEscapingUserVisitor(const NonEscapingUserVisitor &) = delete;
+  NonEscapingUserVisitor &operator=(const NonEscapingUserVisitor &) = delete;
+  NonEscapingUserVisitor(NonEscapingUserVisitor &&) = delete;
+  NonEscapingUserVisitor &operator=(NonEscapingUserVisitor &&) = delete;
+
+  bool compute() {
+    while (!Worklist.empty()) {
+      CurrentOp = Worklist.pop_back_val();
+      SILInstruction *User = CurrentOp.get()->getUser();
+
+      // Ignore type dependent operands.
+      if (User->isTypeDependentOperand(*(CurrentOp.get())))
+        continue;
+
+      // Then visit the specific user. This routine returns true if the value
+      // does not escape. In such a case, continue.
+      if (visit(User)) {
+        continue;
+      }
+
+      return false;
+    }
+
+    return true;
+  }
+
+  /// Visit a random value base.
+  ///
+  /// These are considered to be escapes.
+  bool visitValueBase(ValueBase *V) { return false; }
+
+#define ALWAYS_NON_ESCAPING_INST(INST)                                         \
+  bool visit##INST##Inst(INST##Inst *V) { return true; }
+  // Marking the boxed value as escaping is OK. It's just a DI annotation.
+  ALWAYS_NON_ESCAPING_INST(MarkFunctionEscape)
+  // These remaining instructions are ok and don't count as mutations.
+  ALWAYS_NON_ESCAPING_INST(StrongRetain)
+  ALWAYS_NON_ESCAPING_INST(Load)
+  ALWAYS_NON_ESCAPING_INST(StrongRelease)
+#undef ALWAYS_NON_ESCAPING_INST
+
+  bool visitDeallocBoxInst(DeallocBoxInst *DBI) {
+    Mutations.push_back(DBI);
+    return true;
+  }
+
+  bool visitApplyInst(ApplyInst *AI) {
+    auto argIndex = CurrentOp.get()->getOperandNumber() - 1;
+    SILFunctionConventions substConv(AI->getSubstCalleeType(), AI->getModule());
+    auto convention = substConv.getSILArgumentConvention(argIndex);
+    if (!convention.isIndirectConvention()) {
+      return false;
+    }
+    Mutations.push_back(AI);
+    return true;
+  }
+
+  /// Add the Operands of a transitive use instruction to the worklist.
+  void addUserOperandsToWorklist(SILInstruction *I) {
+    for (auto *User : I->getUses()) {
+      Worklist.push_back(User);
+    }
+  }
+
+  bool visitStructElementAddrInst(StructElementAddrInst *I) {
+    addUserOperandsToWorklist(I);
+    return true;
+  }
+
+  bool visitTupleElementAddrInst(TupleElementAddrInst *I) {
+    addUserOperandsToWorklist(I);
+    return true;
+  }
+
+  bool visitInitEnumDataAddrInst(InitEnumDataAddrInst *I) {
+    addUserOperandsToWorklist(I);
+    return true;
+  }
+
+  bool visitOpenExistentialAddrInst(OpenExistentialAddrInst *I) {
+    addUserOperandsToWorklist(I);
+    return true;
+  }
+
+  bool visitUncheckedTakeEnumDataAddrInst(UncheckedTakeEnumDataAddrInst *I) {
+    // UncheckedTakeEnumDataAddr is additionally a mutation.
+    Mutations.push_back(I);
+
+    addUserOperandsToWorklist(I);
+    return true;
+  }
+
+  bool visitCopyAddrInst(CopyAddrInst *CAI) {
+    if (CurrentOp.get()->getOperandNumber() == 1 || CAI->isTakeOfSrc())
+      Mutations.push_back(CAI);
+    return true;
+  }
+
+  bool visitStoreInst(StoreInst *SI) {
+    if (CurrentOp.get()->getOperandNumber() != 1)
+      return false;
+    Mutations.push_back(SI);
+    return true;
+  }
+
+  bool visitAssignInst(AssignInst *AI) {
+    if (CurrentOp.get()->getOperandNumber() != 1)
+      return false;
+    Mutations.push_back(AI);
+    return true;
+  }
+};
+
+} // end anonymous namespace
+
 /// \brief Given a use of an alloc_box instruction, return true if the use
 /// definitely does not allow the box to escape; also, if the use is an
 /// instruction which possibly mutates the contents of the box, then add it to
 /// the Mutations vector.
 static bool isNonEscapingUse(Operand *InitialOp,
                              SmallVectorImpl<SILInstruction *> &Mutations) {
-  llvm::SmallVector<Operand *, 32> Worklist;
-  Worklist.push_back(InitialOp);
-
-  while (!Worklist.empty()) {
-    auto *Op = Worklist.pop_back_val();
-    SILInstruction *User = Op->getUser();
-
-    if (User->isTypeDependentOperand(*Op))
-      continue;
-
-    // Marking the boxed value as escaping is OK. It's just a DI annotation.
-    if (isa<MarkFunctionEscapeInst>(User))
-      continue;
-
-    // A store or assign is ok if the alloc_box is the destination.
-    if (isa<StoreInst>(User) || isa<AssignInst>(User)) {
-      if (Op->getOperandNumber() != 1)
-        return false;
-      Mutations.push_back(User);
-      continue;
-    }
-
-    // copy_addr is ok, but counts as a mutation if the use is as the
-    // destination or the copy_addr is a take.
-    if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
-      if (Op->getOperandNumber() == 1 || CAI->isTakeOfSrc())
-        Mutations.push_back(CAI);
-      continue;
-    }
-
-    // Recursively see through struct_element_addr, tuple_element_addr, and
-    // open_existential_addr instructions.
-    if (isa<StructElementAddrInst>(User) || isa<TupleElementAddrInst>(User) ||
-        isa<InitEnumDataAddrInst>(User) || isa<OpenExistentialAddrInst>(User) ||
-        isa<UncheckedTakeEnumDataAddrInst>(User)) {
-      // UncheckedTakeEnumDataAddr is additionally a mutation.
-      if (isa<UncheckedTakeEnumDataAddrInst>(User))
-        Mutations.push_back(User);
-
-      for (auto *UserOperand : User->getUses()) {
-        Worklist.push_back(UserOperand);
-      }
-
-      continue;
-    }
-
-    // An apply is ok if the argument is used as an inout parameter or an
-    // indirect return, but counts as a possible mutation in both cases.
-    if (auto *AI = dyn_cast<ApplyInst>(User)) {
-      auto argIndex = Op->getOperandNumber() - 1;
-      SILFunctionConventions substConv(AI->getSubstCalleeType(),
-                                       AI->getModule());
-      auto convention = substConv.getSILArgumentConvention(argIndex);
-      if (!convention.isIndirectConvention()) {
-        return false;
-      }
-      Mutations.push_back(AI);
-      continue;
-    }
-
-    // These instructions are ok but count as mutations.
-    if (isa<DeallocBoxInst>(User)) {
-      Mutations.push_back(User);
-      continue;
-    }
-
-    // These remaining instructions are ok and don't count as mutations.
-    if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
-        isa<LoadInst>(User)) {
-      continue;
-    }
-
-    return false;
-  }
-
-  return true;
+  return NonEscapingUserVisitor(InitialOp, Mutations).compute();
 }
 
 /// \brief Examine an alloc_box instruction, returning true if at least one