Merge pull request #22038 from gottesmm/pr-48a80b46d0806aa50603d26425b66bdb807aecc2

diff --git a/include/swift/SILOptimizer/Utils/SILSSAUpdater.h b/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
index bff40e2..30437bc 100644
--- a/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
+++ b/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
@@ -63,6 +63,10 @@
       SmallVectorImpl<SILPhiArgument *> *InsertedPHIs = nullptr);
   ~SILSSAUpdater();
 
+  void setInsertedPhis(SmallVectorImpl<SILPhiArgument *> *insertedPhis) {
+    InsertedPHIs = insertedPhis;
+  }
+
   /// Initialize for a use of a value of type.
   void Initialize(SILType T);
 
diff --git a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
index ecf3801..06a16fc 100644
--- a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
+++ b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
@@ -239,21 +239,36 @@
     }
 
     // Stores *to* the allocation are writes.
-    if (isa<StoreInst>(User) && UI->getOperandNumber() == 1) {
-      if (PointeeType.is<TupleType>()) {
-        UsesToScalarize.push_back(User);
+    if (auto *si = dyn_cast<StoreInst>(User)) {
+      if (UI->getOperandNumber() == StoreInst::Dest) {
+        if (PointeeType.is<TupleType>()) {
+          UsesToScalarize.push_back(User);
+          continue;
+        }
+
+        auto kind = ([&]() -> PMOUseKind {
+          switch (si->getOwnershipQualifier()) {
+          // Coming out of SILGen, we assume that raw stores are
+          // initializations, unless they have trivial type (which we classify
+          // as InitOrAssign).
+          case StoreOwnershipQualifier::Unqualified:
+            if (PointeeType.isTrivial(User->getModule()))
+              return PMOUseKind::InitOrAssign;
+            return PMOUseKind::Initialization;
+
+          case StoreOwnershipQualifier::Init:
+            return PMOUseKind::Initialization;
+
+          case StoreOwnershipQualifier::Assign:
+            return PMOUseKind::Assign;
+
+          case StoreOwnershipQualifier::Trivial:
+            return PMOUseKind::InitOrAssign;
+          }
+        })();
+        Uses.emplace_back(si, kind);
         continue;
       }
-
-      // Coming out of SILGen, we assume that raw stores are initializations,
-      // unless they have trivial type (which we classify as InitOrAssign).
-      auto Kind = ([&]() -> PMOUseKind {
-        if (PointeeType.isTrivial(User->getModule()))
-          return PMOUseKind::InitOrAssign;
-        return PMOUseKind::Initialization;
-      })();
-      Uses.emplace_back(User, Kind);
-      continue;
     }
 
     if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
diff --git a/test/SILOptimizer/predictable_memaccess_opts.sil b/test/SILOptimizer/predictable_memaccess_opts.sil
index 04ba866..cb1d198 100644
--- a/test/SILOptimizer/predictable_memaccess_opts.sil
+++ b/test/SILOptimizer/predictable_memaccess_opts.sil
@@ -441,6 +441,27 @@
   return %4 : $Klass
 }
 
+// CHECK-LABEL: sil [ossa] @simple_assignstore : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass {
+// CHECK: bb0([[ARG0:%.*]] : @owned $Klass, [[ARG1:%.*]] : @owned $Klass):
+// CHECK:   [[STACK:%.*]] = alloc_stack $Klass
+// CHECK:   store [[ARG0]] to [init] [[STACK]]
+// CHECK:   [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
+// CHECK:   store [[ARG1]] to [assign] [[STACK]]
+// CHECK:   destroy_addr [[STACK]]
+// CHECK:   dealloc_stack [[STACK]]
+// CHECK:   return [[ARG1_COPY]]
+// CHECK: } // end sil function 'simple_assignstore'
+sil [ossa] @simple_assignstore : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass {
+bb0(%0 : @owned $Klass, %1 : @owned $Klass):
+  %2 = alloc_stack $Klass
+  store %0 to [init] %2 : $*Klass
+  store %1 to [assign] %2 : $*Klass
+  %3 = load [copy] %2 : $*Klass
+  destroy_addr %2 : $*Klass
+  dealloc_stack %2 : $*Klass
+  return %3 : $Klass
+}
+
 ////////////////////
 // Negative Tests //
 ////////////////////