Merge pull request #8111 from apple/revert-8099-wip-capture-propagation-generics

Revert "[sil-capture-propagation] Switch to the new notifyAddFunction API"
diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h
index da4efce..58406b6 100644
--- a/include/swift/SILOptimizer/Utils/Generics.h
+++ b/include/swift/SILOptimizer/Utils/Generics.h
@@ -50,10 +50,6 @@
   /// to direct.
   llvm::SmallBitVector Conversions;
 
-  /// If set, indirect to direct conversions should be performned by the generic
-  /// specializer.
-  bool ConvertIndirectToDirect;
-
   /// The first NumResults bits in Conversions refer to formal indirect
   /// out-parameters.
   unsigned NumFormalIndirectResults;
@@ -134,8 +130,7 @@
   /// If specialization is not possible getSpecializedType() will return an
   /// invalid type.
   ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
-                    SubstitutionList ParamSubs,
-                    bool ConvertIndirectToDirect = true);
+                    SubstitutionList ParamSubs);
 
   /// Constructs the ReabstractionInfo for generic function \p Orig with
   /// additional requirements. Requirements may contain new layout,
@@ -145,15 +140,14 @@
   /// Returns true if the \p ParamIdx'th (non-result) formal parameter is
   /// converted from indirect to direct.
   bool isParamConverted(unsigned ParamIdx) const {
-    return ConvertIndirectToDirect &&
-           Conversions.test(ParamIdx + NumFormalIndirectResults);
+    return Conversions.test(ParamIdx + NumFormalIndirectResults);
   }
 
   /// Returns true if the \p ResultIdx'th formal result is converted from
   /// indirect to direct.
   bool isFormalResultConverted(unsigned ResultIdx) const {
     assert(ResultIdx < NumFormalIndirectResults);
-    return ConvertIndirectToDirect && Conversions.test(ResultIdx);
+    return Conversions.test(ResultIdx);
   }
 
   /// Gets the total number of original function arguments.
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 3665886..acfa77a 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -11,15 +11,12 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "capture-prop"
-#include "swift/AST/GenericEnvironment.h"
 #include "swift/SILOptimizer/PassManager/Passes.h"
-#include "swift/SILOptimizer/Utils/Generics.h"
 #include "swift/SILOptimizer/Utils/SpecializationMangler.h"
 #include "swift/Demangling/Demangle.h"
 #include "swift/SIL/Mangle.h"
 #include "swift/SIL/SILCloner.h"
 #include "swift/SIL/SILInstruction.h"
-#include "swift/SIL/TypeSubstCloner.h"
 #include "swift/SILOptimizer/Analysis/ColdBlockInfo.h"
 #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
@@ -102,17 +99,16 @@
 /// caller, so the cloned function will have a mix of locations from different
 /// functions.
 class CapturePropagationCloner
-  : public TypeSubstCloner<CapturePropagationCloner> {
-  using SuperTy = TypeSubstCloner<CapturePropagationCloner>;
+  : public SILClonerWithScopes<CapturePropagationCloner> {
+  using SuperTy = SILClonerWithScopes<CapturePropagationCloner>;
   friend class SILVisitor<CapturePropagationCloner>;
   friend class SILCloner<CapturePropagationCloner>;
 
   SILFunction *OrigF;
   bool IsCloningConstant;
 public:
-  CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF,
-                           SubstitutionList Subs)
-      : SuperTy(*NewF, *OrigF, Subs), OrigF(OrigF), IsCloningConstant(false) {}
+  CapturePropagationCloner(SILFunction *OrigF, SILFunction *NewF)
+    : SuperTy(*NewF), OrigF(OrigF), IsCloningConstant(false) {}
 
   void cloneBlocks(OperandValueArrayRef Args);
 
@@ -223,20 +219,6 @@
   }
 }
 
-CanSILFunctionType getPartialApplyInterfaceResultType(PartialApplyInst *PAI) {
-  SILFunction *OrigF = PAI->getReferencedFunction();
-  // The new partial_apply will no longer take any arguments--they are all
-  // expressed as literals. So its callee signature will be the same as its
-  // return signature.
-  auto FTy = PAI->getType().castTo<SILFunctionType>();
-  CanGenericSignature CanGenericSig;
-  assert(!PAI->hasSubstitutions() || !hasArchetypes(PAI->getSubstitutions()));
-  FTy = cast<SILFunctionType>(
-    OrigF->mapTypeOutOfContext(FTy)->getCanonicalType());
-  auto NewFTy = FTy;
-  return NewFTy;
-}
-
 /// Given a partial_apply instruction, create a specialized callee by removing
 /// all constant arguments and adding constant literals to the specialized
 /// function body.
@@ -261,16 +243,12 @@
   // The new partial_apply will no longer take any arguments--they are all
   // expressed as literals. So its callee signature will be the same as its
   // return signature.
-  auto NewFTy = getPartialApplyInterfaceResultType(PAI);
-  NewFTy = Lowering::adjustFunctionType(NewFTy,
-                                        SILFunctionType::Representation::Thin);
-
-  GenericEnvironment *GenericEnv = nullptr;
-  if (NewFTy->getGenericSignature())
-    GenericEnv = OrigF->getGenericEnvironment();
+  CanSILFunctionType NewFTy =
+    Lowering::adjustFunctionType(PAI->getType().castTo<SILFunctionType>(),
+                                 SILFunctionType::Representation::Thin);
   SILFunction *NewF = OrigF->getModule().createFunction(
       SILLinkage::Shared, Name, NewFTy,
-      GenericEnv, OrigF->getLocation(), OrigF->isBare(),
+      OrigF->getGenericEnvironment(), OrigF->getLocation(), OrigF->isBare(),
       OrigF->isTransparent(), Fragile, OrigF->isThunk(),
       OrigF->getClassVisibility(), OrigF->getInlineStrategy(),
       OrigF->getEffectsKind(),
@@ -281,11 +259,7 @@
   DEBUG(llvm::dbgs() << "  Specialize callee as ";
         NewF->printName(llvm::dbgs()); llvm::dbgs() << " " << NewFTy << "\n");
 
-  DEBUG(if (PAI->hasSubstitutions()) {
-    llvm::dbgs() << "CapturePropagation of generic partial_apply:\n";
-    PAI->dumpInContext();
-  });
-  CapturePropagationCloner cloner(OrigF, NewF, PAI->getSubstitutions());
+  CapturePropagationCloner cloner(OrigF, NewF);
   cloner.cloneBlocks(PAI->getArguments());
   assert(OrigF->getDebugScope()->Parent != NewF->getDebugScope()->Parent);
   return NewF;
@@ -293,16 +267,10 @@
 
 void CapturePropagation::rewritePartialApply(PartialApplyInst *OrigPAI,
                                              SILFunction *SpecialF) {
-  DEBUG(llvm::dbgs() << "\n  Rewriting a partial apply:\n";
-        OrigPAI->dumpInContext(); llvm::dbgs() << "   with special function: "
-                                               << SpecialF->getName() << "\n";
-        llvm::dbgs() << "\nThe function being rewritten is:\n";
-        OrigPAI->getFunction()->dump());
-
   SILBuilderWithScope Builder(OrigPAI);
   auto FuncRef = Builder.createFunctionRef(OrigPAI->getLoc(), SpecialF);
-  auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(), FuncRef,
-                                                 OrigPAI->getType());
+  auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(),
+                                                 FuncRef, OrigPAI->getType());
   OrigPAI->replaceAllUsesWith(T2TF);
   recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
   DEBUG(llvm::dbgs() << "  Rewrote caller:\n" << *T2TF);
@@ -343,16 +311,12 @@
 
 /// Checks if \p Orig is a thunk which calls another function but without
 /// passing the trailing \p numDeadParams dead parameters.
-/// If a generic specialization was performed for a generic capture,
-/// GenericSpecialized contains a tuple:
-/// (new specialized function, old function)
-static SILFunction *getSpecializedWithDeadParams(
-    PartialApplyInst *PAI, SILFunction *Orig, int numDeadParams,
-    std::pair<SILFunction *, SILFunction *> &GenericSpecialized) {
+static SILFunction *getSpecializedWithDeadParams(SILFunction *Orig,
+                                                 int numDeadParams) {
   SILBasicBlock &EntryBB = *Orig->begin();
   unsigned NumArgs = EntryBB.getNumArguments();
   SILModule &M = Orig->getModule();
-
+  
   // Check if all dead parameters have trivial types. We don't support non-
   // trivial types because it's very hard to find places where we can release
   // those parameters (as a replacement for the removed partial_apply).
@@ -364,20 +328,20 @@
   }
   SILFunction *Specialized = nullptr;
   SILValue RetValue;
-
+  
   // Check all instruction of the entry block.
   for (SILInstruction &I : EntryBB) {
     if (auto FAS = FullApplySite::isa(&I)) {
+      
       // Check if this is the call of the specialized function.
-      // If the original partial_apply didn't have substitutions,
-      // also the specialized function must be not generic.
-      if (!PAI->hasSubstitutions() && FAS.hasSubstitutions())
+      // As the original function is not generic, also the specialized function
+      // must be not generic.
+      if (FAS.hasSubstitutions())
         return nullptr;
-
       // Is it the only call?
       if (Specialized)
         return nullptr;
-
+      
       Specialized = FAS.getReferencedFunction();
       if (!Specialized)
         return nullptr;
@@ -412,54 +376,29 @@
     if (I.mayHaveSideEffects() || isa<TermInst>(&I))
       return nullptr;
   }
-
-  GenericSpecialized = std::make_pair(nullptr, nullptr);
-
-  if (PAI->hasSubstitutions()) {
-    if (Specialized->isExternalDeclaration())
-      return nullptr;
-    // Perform a generic specialization of the Specialized function.
-    ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
-                             /* ConvertIndirectToDirect */ false);
-    GenericFuncSpecializer FuncSpecializer(Specialized,
-                                           ReInfo.getClonerParamSubstitutions(),
-                                           Specialized->isFragile(), ReInfo);
-
-    SILFunction *GenericSpecializedFunc = FuncSpecializer.trySpecialization();
-    if (!GenericSpecializedFunc)
-      return nullptr;
-    GenericSpecialized = std::make_pair(GenericSpecializedFunc, Specialized);
-    return GenericSpecializedFunc;
-  }
   return Specialized;
 }
 
 bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
+  // Check if the partial_apply has generic substitutions.
+  // FIXME: We could handle generic thunks if it's worthwhile.
+  if (PAI->hasSubstitutions())
+    return false;
+
   SILFunction *SubstF = PAI->getReferencedFunction();
   if (!SubstF)
     return false;
   if (SubstF->isExternalDeclaration())
     return false;
 
-  if (PAI->hasSubstitutions() && hasArchetypes(PAI->getSubstitutions())) {
-    DEBUG(llvm::dbgs()
-              << "CapturePropagation: cannot handle partial specialization "
-                 "of partial_apply:\n";
-          PAI->dumpInContext());
-    return false;
-  }
-
+  assert(!SubstF->getLoweredFunctionType()->isPolymorphic() &&
+         "cannot specialize generic partial apply");
 
   // First possibility: Is it a partial_apply where all partially applied
   // arguments are dead?
-  std::pair<SILFunction *, SILFunction *> GenericSpecialized;
-  if (auto *NewFunc = getSpecializedWithDeadParams(
-          PAI, SubstF, PAI->getNumArguments(), GenericSpecialized)) {
+  if (SILFunction *NewFunc = getSpecializedWithDeadParams(SubstF,
+                                                    PAI->getNumArguments())) {
     rewritePartialApply(PAI, NewFunc);
-    if (GenericSpecialized.first) {
-      // Notify the pass manager about the new function.
-      notifyAddFunction(GenericSpecialized.first, GenericSpecialized.second);
-    }
     return true;
   }
 
@@ -472,8 +411,7 @@
     return false;
 
   DEBUG(llvm::dbgs() << "Specializing closure for constant arguments:\n"
-                     << "  " << SubstF->getName() << "\n"
-                     << *PAI);
+        << "  " << SubstF->getName() << "\n" << *PAI);
   ++NumCapturesPropagated;
   SILFunction *NewF = specializeConstClosure(PAI, SubstF);
   rewritePartialApply(PAI, NewF);
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index f886a9c..b02d39f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -290,13 +290,10 @@
 }
 
 ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
-                                     ArrayRef<Substitution> ParamSubs,
-                                     bool ConvertIndirectToDirect) {
+                                     ArrayRef<Substitution> ParamSubs) {
   if (!prepareAndCheck(Apply, Callee, ParamSubs))
     return;
 
-  this->ConvertIndirectToDirect = ConvertIndirectToDirect;
-
   if (SpecializeGenericSubstitutions) {
     specializeConcreteAndGenericSubstitutions(Apply, Callee, ParamSubs);
   } else {
diff --git a/test/SILOptimizer/capture_propagation.sil b/test/SILOptimizer/capture_propagation.sil
index d8dce48..b0317c9 100644
--- a/test/SILOptimizer/capture_propagation.sil
+++ b/test/SILOptimizer/capture_propagation.sil
@@ -378,75 +378,3 @@
   return %2 : $@callee_owned (Int32, Int32) -> (Bool, @error Error)
 }
 
-// Test generic capture propagation
-
-sil @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> () {
-bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T):
-  %9999 = tuple()
-  return %9999 : $()
-}
-
-// CHECK-LABEL: sil @test_generic_capture_propagation2_caller
-// CHECK: %[[CALLEE:[0-9]+]] = function_ref @test_generic_capture_propagation2_callee 
-// CHECK: %[[FR:[0-9]+]] = function_ref @{{.*}}test_generic_capture_propagation2_thunk : $@convention(thin) () -> () 
-// CHECK: %[[CONVERTED:[0-9]+]] = thin_to_thick_function %[[FR]] : $@convention(thin) () -> () to $@callee_owned () -> ()
-// CHECK-NOT: partial_apply
-// CHECK: apply %[[CALLEE]](%[[CONVERTED]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
-// CHECL-NOT: partial_apply
-// CHECK: return
-sil @test_generic_capture_propagation2_caller : $@convention(thin) () -> () {
-  %0 = integer_literal $Builtin.Int32, 0
-  %1 = float_literal $Builtin.FPIEEE32, 0
-  %2 = string_literal utf8 "123"
-  %3 = global_addr @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $*Builtin.Word
-  %4 = function_ref @_TFtest_generic_capture_propagation2_closure : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
-  %5 = thin_to_thick_function %4 : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> () to $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
-  %6 = function_ref @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
-  %7 = function_ref @test_generic_capture_propagation2_thunk : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> ()
-  %8 = partial_apply %7<Builtin.Word>(%0, %1, %2, %3, %5) : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> ()
-  apply %6(%8) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
-  %9999 = tuple()
-  return %9999 : $()
-}
-
-sil shared @test_generic_capture_propagation2_thunk : $@convention(thin) <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T, @owned @callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()) -> () {
-bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*T, %4 : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()):
-  apply %4<T>(%0, %1, %2, %3) : $@callee_owned <T> (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in T) -> ()
-  %9999 = tuple()
-  return %9999 : $()
-}
-
-sil shared @test_generic_capture_propagation2_callee : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
-bb0(%0 : $@callee_owned () -> ()):
-  apply %0() : $@callee_owned () -> ()
-  %9999 = tuple()
-  return %9999 : $()
-}
-
-// Test dead partial applied arguments when using generics
-
-sil @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool {
-bb0(%0 : $*T, %1 : $*T):
-  %10 = integer_literal $Builtin.Int1, -1
-  %9999 = struct $Bool (%10 : $Builtin.Int1)
-  return %9999 : $Bool
-}
-
-sil @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool {
-bb0(%0 : $*T, %1 : $*T, %2 : $@thin T.Type):
-  %3 = function_ref @specialized_generic_nonthrowing_closure : $@convention(thin) <T> (@in T, @in T) -> Bool
-  %4 = apply %3<T>(%0, %1) : $@convention(thin) <T> (@in T, @in T) -> Bool
-  return %4 : $Bool
-}
-
-// CHECK-LABEL: sil @return_generic_nonthrowing_closure
-// CHECK: [[F:%[0-9]+]] = function_ref @_TTSg5Vs5Int32__specialized_generic_nonthrowing_closure
-// CHECK: [[R:%[0-9]+]] = thin_to_thick_function [[F]]
-// CHECK: return [[R]]
-sil @return_generic_nonthrowing_closure : $@convention(thin) () -> @owned @callee_owned (@in Int32, @in Int32) -> Bool {
-bb0:
-  %0 = metatype $@thin Int32.Type
-  %1 = function_ref @nonthrowing_generic_closure : $@convention(method) <T> (@in T, @in T, @thin T.Type) -> Bool
-  %2 = partial_apply %1<Int32>(%0) : $@convention(method) <T>(@in T, @in T, @thin T.Type) -> Bool
-  return %2 : $@callee_owned (@in Int32, @in Int32) -> Bool
-}
\ No newline at end of file