Merge pull request #17598 from gottesmm/swift-4.2-branch-fix-pmo-bug

[4.2][pmo] Eliminate incomplete support for promoting enums.
diff --git a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
index de4bc11..3fec285 100644
--- a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
+++ b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
@@ -231,10 +231,6 @@
   /// element we attribute an access to.
   bool InStructSubElement = false;
 
-  /// When walking the use list, if we index into an enum slice, keep track
-  /// of this.
-  bool InEnumSubElement = false;
-
 public:
   ElementUseCollector(const PMOMemoryObjectInfo &TheMemory,
                       SmallVectorImpl<PMOMemoryUse> &Uses,
@@ -294,7 +290,7 @@
   // If we're in a subelement of a struct or enum, just mark the struct, not
   // things that come after it in a parent tuple.
   unsigned NumElements = 1;
-  if (TheMemory.NumElements != 1 && !InStructSubElement && !InEnumSubElement)
+  if (TheMemory.NumElements != 1 && !InStructSubElement)
     NumElements = getElementCountRec(Module, UseTy);
 
   Uses.push_back(PMOMemoryUse(User, Kind, BaseEltNo, NumElements));
@@ -309,7 +305,7 @@
   // If we're walking into a tuple within a struct or enum, don't adjust the
   // BaseElt.  The uses hanging off the tuple_element_addr are going to be
   // counted as uses of the struct or enum itself.
-  if (InStructSubElement || InEnumSubElement)
+  if (InStructSubElement)
     return collectUses(TEAI, BaseEltNo);
 
   // tuple_element_addr P, 42 indexes into the current tuple element.
@@ -554,26 +550,6 @@
       llvm_unreachable("bad parameter convention");
     }
 
-    // init_enum_data_addr is treated like a tuple_element_addr or other
-    // instruction that is looking into the memory object (i.e., the memory
-    // object needs to be explicitly initialized by a copy_addr or some other
-    // use of the projected address).
-    if (auto I = dyn_cast<InitEnumDataAddrInst>(User)) {
-      // If we are in a struct already, bail. With proper analysis, we should be
-      // able to do this optimization.
-      if (InStructSubElement) {
-        return false;
-      }
-
-      // Keep track of the fact that we're inside of an enum.  This informs our
-      // recursion that tuple stores are not scalarized outside, and that stores
-      // should not be treated as partial stores.
-      llvm::SaveAndRestore<bool> X(InEnumSubElement, true);
-      if (!collectUses(I, BaseEltNo))
-        return false;
-      continue;
-    }
-
     // init_existential_addr is modeled as an initialization store.
     if (isa<InitExistentialAddrInst>(User)) {
       // init_existential_addr should not apply to struct subelements.
@@ -585,17 +561,6 @@
       continue;
     }
 
-    // inject_enum_addr is modeled as an initialization store.
-    if (isa<InjectEnumAddrInst>(User)) {
-      // inject_enum_addr the subelement of a struct unless in a ctor.
-      if (InStructSubElement) {
-        return false;
-      }
-      Uses.push_back(
-          PMOMemoryUse(User, PMOUseKind::Initialization, BaseEltNo, 1));
-      continue;
-    }
-
     // open_existential_addr is a use of the protocol value,
     // so it is modeled as a load.
     if (isa<OpenExistentialAddrInst>(User)) {
diff --git a/test/SILOptimizer/predictable_memopt.sil b/test/SILOptimizer/predictable_memopt.sil
index 1a10f8f..4bf5838 100644
--- a/test/SILOptimizer/predictable_memopt.sil
+++ b/test/SILOptimizer/predictable_memopt.sil
@@ -880,4 +880,24 @@
   %4 = load %0 : $*SWithOpt
   dealloc_stack %0 : $*SWithOpt
   return %4 : $SWithOpt
-}
\ No newline at end of file
+}
+
+// We do not support this now, so make sure we do not do anything.
+//
+// CHECK-LABEL: sil @promote_init_enum_data_addr : $@convention(thin)
+// CHECK: alloc_stack
+// CHECK: load
+// CHECK: [[RESULT:%.*]] = load
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function 'promote_init_enum_data_addr'
+sil @promote_init_enum_data_addr : $@convention(thin) (@in Int) -> Int {
+bb0(%0 : $*Int):
+  %1 = alloc_stack $Optional<Int>
+  %2 = load %0 : $*Int
+  %3 = init_enum_data_addr %1 : $*Optional<Int>, #Optional.some!enumelt.1
+  store %2 to %3 : $*Int
+  inject_enum_addr %1 : $*Optional<Int>, #Optional.some!enumelt.1
+  %4 = load %3 : $*Int
+  dealloc_stack %1 : $*Optional<Int>
+  return %4 : $Int
+}