Merge pull request #14395 from jckarter/class-init-writeback-di-4.1

[4.1] DefiniteInitialization: Storing back to the 'self' box in a class init is OK.
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
index 19d4537..3e43c05 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
@@ -1128,8 +1128,14 @@
         }
 
         // A store of a load from the box is ignored.
-        // FIXME: SILGen should not emit these.
-        if (auto *LI = dyn_cast<LoadInst>(SI->getSrc()))
+        // SILGen emits these if delegation to another initializer was
+        // interrupted before the initializer was called.
+        SILValue src = SI->getSrc();
+        // Look through conversions.
+        while (auto conversion = dyn_cast<ConversionInst>(src))
+          src = conversion->getConverted();
+        
+        if (auto *LI = dyn_cast<LoadInst>(src))
           if (LI->getOperand() == MUI)
             continue;
 
@@ -1503,7 +1509,7 @@
     // Stores to self.
     if (auto *SI = dyn_cast<StoreInst>(User)) {
       if (Op->getOperandNumber() == 1) {
-        // The initial store of 'self' into the box at the start of the
+        // A store of 'self' into the box at the start of the
         // function. Ignore it.
         if (auto *Arg = dyn_cast<SILArgument>(SI->getSrc())) {
           if (Arg->getParent() == MUI->getParent()) {
@@ -1513,8 +1519,14 @@
         }
 
         // A store of a load from the box is ignored.
-        // FIXME: SILGen should not emit these.
-        if (auto *LI = dyn_cast<LoadInst>(SI->getSrc()))
+        // SILGen emits these if delegation to another initializer was
+        // interrupted before the initializer was called.
+        SILValue src = SI->getSrc();
+        // Look through conversions.
+        while (auto conversion = dyn_cast<ConversionInst>(src))
+          src = conversion->getConverted();
+        
+        if (auto *LI = dyn_cast<LoadInst>(src))
           if (LI->getOperand() == MUI)
             continue;
 
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index 48cdeac..2ed62e5 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -1636,7 +1636,14 @@
                                            bool SuperInitDone,
                                            bool FailedSelfUse) {
   SILInstruction *Inst = Use.Inst;
-  
+
+  // Stores back to the 'self' box are OK.
+  if (auto store = dyn_cast<StoreInst>(Inst)) {
+    if (store->getDest() == TheMemory.MemoryInst
+        && TheMemory.isClassInitSelf())
+      return;
+  }
+
   if (FailedSelfUse) {
     emitSelfConsumedDiagnostic(Inst);
     return;
diff --git a/test/SILOptimizer/definite-init-try-in-self-init-argument.swift b/test/SILOptimizer/definite-init-try-in-self-init-argument.swift
new file mode 100644
index 0000000..ebbaf4a
--- /dev/null
+++ b/test/SILOptimizer/definite-init-try-in-self-init-argument.swift
@@ -0,0 +1,12 @@
+// RUN: %target-swift-frontend -emit-sil -verify %s
+
+class Y: X {
+  required init(_: Z) throws {
+    try super.init(Z())
+  }
+}
+class Z { init() throws {} }
+
+class X {
+  required init(_: Z) throws {}
+}