Merge pull request #11261 from gottesmm/swift-4.0-branch_rdar33595317_1

[4.0] [sil-combine] Make sure that (apply (partial_apply)) -> (apply') bail…
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 99788a0..38b12c0 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -151,14 +151,15 @@
   // Emit a destroy value for each captured closure argument.
   ArrayRef<SILParameterInfo> Params = PAITy->getParameters();
   auto Args = PAI->getArguments();
-  unsigned Delta = Params.size() - Args.size();
+  Params = Params.drop_front(Params.size() - Args.size());
 
   llvm::SmallVector<std::pair<SILValue, unsigned>, 8> ArgsToHandle;
-  for (unsigned AI = 0, AE = Args.size(); AI != AE; ++AI) {
-    SILValue Arg = Args[AI];
-    SILParameterInfo Param = Params[AI + Delta];
+  for (unsigned i : indices(Args)) {
+    SILValue Arg = Args[i];
+    SILParameterInfo Param = Params[i];
     if (Param.isIndirectMutating())
       continue;
+
     // Create a temporary and copy the argument into it, if:
     // - the argument stems from an alloc_stack
     // - the argument is consumed by the callee and is indirect
@@ -166,10 +167,18 @@
     if (isa<AllocStackInst>(Arg)
         || (Param.isConsumed()
             && PAI->getSubstCalleeConv().isSILIndirect(Param))) {
+      // If the argument has a dependent type, then we can not create a
+      // temporary for it at the beginning of the function, so we must bail.
+      //
+      // TODO: This is because we are inserting alloc_stack at the beginning/end
+      // of functions where the dependent type may not exist yet.
+      if (Arg->getType().hasOpenedExistential())
+        return false;
+
       // If the temporary is non-trivial, we need to release it later.
       if (!Arg->getType().isTrivial(PAI->getModule()))
         needsReleases = true;
-      ArgsToHandle.push_back(std::make_pair(Arg, AI));
+      ArgsToHandle.push_back(std::make_pair(Arg, i));
     }
   }
 
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index 0c85a11..2bf1e6f 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -11,6 +11,10 @@
 
 protocol Error {}
 
+protocol SwiftP {
+  func foo()
+}
+
 /////////////////////////////////
 // Tests for SILCombinerApply. //
 /////////////////////////////////
@@ -235,10 +239,6 @@
   throw %5 : $Error
 }
 
-protocol SwiftP {
-  func foo()
-}
-
 // Make sure that we do not optimize this case. If we do optimize this case,
 // given the current algorithm which puts alloc_stack at the beginning/end of
 // the function, we will have a fatal error.
@@ -285,4 +285,27 @@
   %a1 = apply %pa(%0) : $@callee_owned (@in T) -> ()
   %r = tuple ()
   return %r : $()
+}
+
+// Today when we optimize (apply (partial_apply)) -> apply, we can not handle
+// dependent types since the algorithm attempts to create an alloc_stack at the
+// beginning/end of the function. In such a case, the dependent type may not be
+// alive at that point, so the compiler will crash. This test ensures that we do
+// not optimize this case.
+//
+// CHECK-LABEL: sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
+// CHECK: [[PAI:%.*]] = partial_apply
+// CHECK: apply [[PAI]]
+sil @sil_combine_applied_partialapply_to_apply_with_dependent_type : $@convention(thin) (@in SwiftP) -> () {
+bb0(%0 : $*SwiftP):
+  %0b = alloc_stack $SwiftP
+  %1 = open_existential_addr mutable_access %0b : $*SwiftP to $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
+  %2 = witness_method $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP, #SwiftP.foo!1, %1 : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
+  %0c = alloc_stack $@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
+  %3 = partial_apply %2<@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP>(%0c) : $@convention(witness_method) <τ_0_0 where τ_0_0 : SwiftP> (@in_guaranteed τ_0_0) -> ()
+  dealloc_stack %0c : $*@opened("3305E696-5685-11E5-9393-B8E856428C60") SwiftP
+  dealloc_stack %0b : $*SwiftP
+  %4 = apply %3() : $@callee_owned () -> ()
+  %9999 = tuple()
+  return %9999 : $()
 }
\ No newline at end of file