Merge pull request #15659 from atrick/irgen-endaccess

Full IRGen support for begin_access [no_nested_conflict].
diff --git a/README.md b/README.md
index 54819c2..5264e05 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@
 
 For Ubuntu, you'll need the following development dependencies:
 
-    sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata
+    sudo apt-get install git cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev autoconf libtool systemtap-sdt-dev tzdata rsync
 
 **Note:** LLDB currently requires at least `swig-1.3.40` but will successfully build
 with version 2 shipped with Ubuntu.
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index 2af1829..63f457c 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -89,12 +89,36 @@
 //===----------------------------------------------------------------------===//
 //                     Function Signature Transformation 
 //===----------------------------------------------------------------------===//
-class FunctionSignatureTransform {
-  /// The actual function to analyze and transform.
-  SILFunction *F;
 
-  /// The newly created function.
-  SILFunction *NewF;
+struct FunctionSignatureTransformDescriptor {
+  /// The original function that we are analyzing/transforming.
+  SILFunction *OriginalFunction;
+
+  /// The new optimize function that we will create.
+  NullablePtr<SILFunction> OptimizedFunction;
+
+  /// A map from a pre-transformed argument to a post-transformed argument.
+  ArgumentIndexMap &AIM;
+
+  /// Set to true if we are going to modify self during our transformation.
+  ///
+  /// TODO: Rename to willModifySelfArgument.
+  bool shouldModifySelfArgument;
+
+  /// Keep a "view" of precompiled information on arguments that we use 
+  /// during our optimization.
+  MutableArrayRef<ArgumentDescriptor> ArgumentDescList;
+
+  /// Keep a "view" of precompiled information on the direct results that we
+  /// will use during our optimization.
+  MutableArrayRef<ResultDescriptor> ResultDescList;
+};
+
+class FunctionSignatureTransform {
+  /// A struct that contains all data that we use during our
+  /// transformation. This is an initial step towards splitting this struct into
+  /// multiple "transforms" that can be tested independently of each other.
+  FunctionSignatureTransformDescriptor TransformDescriptor;
 
   /// The RC identity analysis we are using.
   RCIdentityAnalysis *RCIA;
@@ -105,20 +129,6 @@
   // The function signature mangler we are using.
   Mangle::FunctionSignatureSpecializationMangler &Mangler;
 
-  // Keep tracks to argument mapping.
-  ArgumentIndexMap &AIM;
-
-  // Self argument is modified.
-  bool shouldModifySelfArgument;
-
-  /// Keep a "view" of precompiled information on arguments that we use 
-  /// during our optimization.
-  llvm::SmallVector<ArgumentDescriptor, 4> &ArgumentDescList;
-
-  /// Keep a "view" of precompiled information on the direct results that we
-  /// will use during our optimization.
-  llvm::SmallVector<ResultDescriptor, 4> &ResultDescList;
-
   /// Return a function name based on ArgumentDescList and ResultDescList.
   std::string createOptimizedSILFunctionName();
 
@@ -217,22 +227,23 @@
 
 public:
   /// Constructor.
-  FunctionSignatureTransform(SILFunction *F,
-                             RCIdentityAnalysis *RCIA, EpilogueARCAnalysis *EA,
-                   Mangle::FunctionSignatureSpecializationMangler &Mangler,
-                             ArgumentIndexMap &AIM,
-                             llvm::SmallVector<ArgumentDescriptor, 4> &ADL,
-                             llvm::SmallVector<ResultDescriptor, 4> &RDL)
-    : F(F), NewF(nullptr), RCIA(RCIA), EA(EA), Mangler(Mangler),
-      AIM(AIM), shouldModifySelfArgument(false), ArgumentDescList(ADL),
-      ResultDescList(RDL) {}
+  FunctionSignatureTransform(
+      SILFunction *F, RCIdentityAnalysis *RCIA, EpilogueARCAnalysis *EA,
+      Mangle::FunctionSignatureSpecializationMangler &Mangler,
+      ArgumentIndexMap &AIM, llvm::SmallVector<ArgumentDescriptor, 4> &ADL,
+      llvm::SmallVector<ResultDescriptor, 4> &RDL)
+      : TransformDescriptor{F, nullptr, AIM, false, ADL, RDL}, RCIA(RCIA),
+        EA(EA), Mangler(Mangler) {}
 
   /// Return the optimized function.
-  SILFunction *getOptimizedFunction() { return NewF; }
+  SILFunction *getOptimizedFunction() {
+    return TransformDescriptor.OptimizedFunction.getPtrOrNull();
+  }
 
   /// Run the optimization.
   bool run(bool hasCaller) {
     bool Changed = false;
+    SILFunction *F = TransformDescriptor.OriginalFunction;
 
     if (!hasCaller && canBeCalledIndirectly(F->getRepresentation())) {
       DEBUG(llvm::dbgs() << "  function has no caller -> abort\n");
@@ -295,25 +306,32 @@
     if (!DeadArgumentAnalyzeParameters())
       return false;
 
+    SILFunction *F = TransformDescriptor.OriginalFunction;
+    auto ArgumentDescList = TransformDescriptor.ArgumentDescList;
+
     // Check if at least the minimum number of partially applied arguments
     // are dead. Otherwise no partial_apply can be removed anyway.
-    for (unsigned Idx = 0, Num = ArgumentDescList.size(); Idx < Num; ++Idx) {
-      if (Idx < Num - minPartialAppliedArgs) {
+    unsigned Size = ArgumentDescList.size();
+    for (unsigned Idx : range(Size)) {
+      if (Idx < Size - minPartialAppliedArgs) {
         // Don't remove arguments other than the partial applied ones, even if
         // they are dead.
         ArgumentDescList[Idx].IsEntirelyDead = false;
-      } else {
-        // Is the partially applied argument dead?
-        if (!ArgumentDescList[Idx].IsEntirelyDead)
-          return false;
-        
-        // Currently we require that all dead parameters have trivial types.
-        // The reason is that it's very hard to find places where we can release
-        // those parameters (as a replacement for the removed partial_apply).
-        // TODO: maybe we can skip this restriction when we have semantic ARC.
-        if (!ArgumentDescList[Idx].Arg->getType().isTrivial(F->getModule()))
-          return false;
+        continue;
       }
+
+      // Is the partially applied argument dead?
+      if (!ArgumentDescList[Idx].IsEntirelyDead)
+        return false;
+
+      // Currently we require that all dead parameters have trivial types.  The
+      // reason is that it's very hard to find places where we can release those
+      // parameters (as a replacement for the removed partial_apply).
+      //
+      // TODO: Maybe we can skip this restriction when we have semantic ARC.
+      if (ArgumentDescList[Idx].Arg->getType().isTrivial(F->getModule()))
+        continue;
+      return false;
     }
 
     DEBUG(llvm::dbgs() << "  remove dead arguments for partial_apply\n");
@@ -324,6 +342,10 @@
 };
 
 std::string FunctionSignatureTransform::createOptimizedSILFunctionName() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
+  auto ArgumentDescList = TransformDescriptor.ArgumentDescList;
+  auto ResultDescList = TransformDescriptor.ResultDescList;
+
   // Handle arguments' changes.
   for (unsigned i : indices(ArgumentDescList)) {
     const ArgumentDescriptor &Arg = ArgumentDescList[i];
@@ -545,6 +567,10 @@
 }
 
 CanSILFunctionType FunctionSignatureTransform::createOptimizedSILFunctionType() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
+  auto ArgumentDescList = TransformDescriptor.ArgumentDescList;
+  auto ResultDescList = TransformDescriptor.ResultDescList;
+
   CanSILFunctionType FTy = F->getLoweredFunctionType();
   auto ExpectedFTy = F->getLoweredType().castTo<SILFunctionType>();
   auto HasGenericSignature = FTy->getGenericSignature() != nullptr;
@@ -562,10 +588,9 @@
   // change an indirect result.  Piece the modified direct result information
   // back into the all-results list.
   llvm::SmallVector<SILResultInfo, 8> InterfaceResults;
-  auto &ResultDescs = ResultDescList;
   for (SILResultInfo InterfaceResult : FTy->getResults()) {
     if (InterfaceResult.isFormalDirect()) {
-      auto &RV = ResultDescs[0];
+      auto &RV = ResultDescList[0];
       if (!RV.CalleeRetain.empty()) {
         ++NumOwnedConvertedToNotOwnedResult;
         InterfaceResults.push_back(SILResultInfo(InterfaceResult.getType(),
@@ -618,7 +643,7 @@
   // Don't use a method representation if we modified self.
   auto ExtInfo = FTy->getExtInfo();
   auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrNone();
-  if (shouldModifySelfArgument) {
+  if (TransformDescriptor.shouldModifySelfArgument) {
     ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin);
     witnessMethodConformance = None;
   }
@@ -642,7 +667,8 @@
 }
 
 void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
-  // Create the optimized function !
+  // Create the optimized function!
+  SILFunction *F = TransformDescriptor.OriginalFunction;
   SILModule &M = F->getModule();
   std::string Name = createOptimizedSILFunctionName();
   SILLinkage linkage = getSpecializedLinkage(F, F->getLinkage());
@@ -657,11 +683,12 @@
     NewFGenericEnv = nullptr;
   }
 
-  NewF = M.createFunction(linkage, Name, NewFTy, NewFGenericEnv,
-                          F->getLocation(), F->isBare(), F->isTransparent(),
-                          F->isSerialized(), F->getEntryCount(), F->isThunk(),
-                          F->getClassSubclassScope(), F->getInlineStrategy(),
-                          F->getEffectsKind(), nullptr, F->getDebugScope());
+  TransformDescriptor.OptimizedFunction = M.createFunction(
+      linkage, Name, NewFTy, NewFGenericEnv, F->getLocation(), F->isBare(),
+      F->isTransparent(), F->isSerialized(), F->getEntryCount(), F->isThunk(),
+      F->getClassSubclassScope(), F->getInlineStrategy(), F->getEffectsKind(),
+      nullptr, F->getDebugScope());
+  SILFunction *NewF = TransformDescriptor.OptimizedFunction.get();
   if (!F->hasQualifiedOwnership()) {
     NewF->setUnqualifiedOwnership();
   }
@@ -681,7 +708,6 @@
   DeadArgumentFinalizeOptimizedFunction();
 
   // Update the ownership kinds of function entry BB arguments.
-
   for (auto Arg : NewF->begin()->getFunctionArguments()) {
     SILType MappedTy = Arg->getType();
     auto Ownershipkind =
@@ -697,7 +723,7 @@
   // caller side.
   F->setInlineStrategy(AlwaysInline);
   SILBasicBlock *ThunkBody = F->createBasicBlock();
-  for (auto &ArgDesc : ArgumentDescList) {
+  for (auto &ArgDesc : TransformDescriptor.ArgumentDescList) {
     ThunkBody->createFunctionArgument(ArgDesc.Arg->getType(), ArgDesc.Decl);
   }
 
@@ -709,7 +735,7 @@
 
   // Create the args for the thunk's apply, ignoring any dead arguments.
   llvm::SmallVector<SILValue, 8> ThunkArgs;
-  for (auto &ArgDesc : ArgumentDescList) {
+  for (auto &ArgDesc : TransformDescriptor.ArgumentDescList) {
     addThunkArgument(ArgDesc, Builder, ThunkBody, ThunkArgs);
   }
 
@@ -769,12 +795,14 @@
 /// ----------------------------------------------------------///
 bool FunctionSignatureTransform::DeadArgumentAnalyzeParameters() {
   // Did we decide we should optimize any parameter?
+  SILFunction *F = TransformDescriptor.OriginalFunction;
   bool SignatureOptimize = false;
   auto Args = F->begin()->getFunctionArguments();
-  auto OrigShouldModifySelfArgument = shouldModifySelfArgument;
+  auto OrigShouldModifySelfArgument =
+      TransformDescriptor.shouldModifySelfArgument;
   // Analyze the argument information.
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-    ArgumentDescriptor &A = ArgumentDescList[i];
+    ArgumentDescriptor &A = TransformDescriptor.ArgumentDescList[i];
     if (!A.PInfo.hasValue()) {
       // It is not an argument. It could be an indirect result. 
       continue;
@@ -789,7 +817,7 @@
       A.IsEntirelyDead = true;
       SignatureOptimize = true;
       if (Args[i]->isSelf())
-        shouldModifySelfArgument = true;
+        TransformDescriptor.shouldModifySelfArgument = true;
     }
   }
 
@@ -798,7 +826,7 @@
     // don't remove them, because it would produce a slower code
     // for generic functions.
     bool HasNonTypeDeadArguments = false;
-    for (auto &AD : ArgumentDescList) {
+    for (auto &AD : TransformDescriptor.ArgumentDescList) {
       if (AD.IsEntirelyDead &&
           !isa<AnyMetatypeType>(AD.Arg->getType().getSwiftRValueType())) {
         HasNonTypeDeadArguments = true;
@@ -807,13 +835,14 @@
     }
 
     if (!HasNonTypeDeadArguments) {
-      for (auto &AD : ArgumentDescList) {
+      for (auto &AD : TransformDescriptor.ArgumentDescList) {
         if (AD.IsEntirelyDead) {
           AD.IsEntirelyDead = false;
           break;
         }
       }
-      shouldModifySelfArgument = OrigShouldModifySelfArgument;
+      TransformDescriptor.shouldModifySelfArgument =
+          OrigShouldModifySelfArgument;
       SignatureOptimize = false;
     }
   }
@@ -822,8 +851,9 @@
 }
 
 void FunctionSignatureTransform::DeadArgumentTransformFunction() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
   SILBasicBlock *BB = &*F->begin();
-  for (const ArgumentDescriptor &AD : ArgumentDescList) {
+  for (const ArgumentDescriptor &AD : TransformDescriptor.ArgumentDescList) {
     if (!AD.IsEntirelyDead)
       continue;
     eraseUsesOfValue(BB->getArgument(AD.Index));
@@ -831,19 +861,22 @@
 }
 
 void FunctionSignatureTransform::DeadArgumentFinalizeOptimizedFunction() {
-  auto *BB = &*NewF->begin();
+  auto *BB = &*TransformDescriptor.OptimizedFunction.get()->begin();
   // Remove any dead argument starting from the last argument to the first.
-  for (const ArgumentDescriptor &AD : reverse(ArgumentDescList)) {
+  for (const ArgumentDescriptor &AD :
+       reverse(TransformDescriptor.ArgumentDescList)) {
     if (!AD.IsEntirelyDead)
       continue;
     BB->eraseArgument(AD.Arg->getIndex());
   }
 }
 
-/// ----------------------------------------------------------///
-/// Owned to Guaranteed transformation.                       ///
-/// ----------------------------------------------------------///
+//===----------------------------------------------------------------------===//
+//                     Owned to Guaranteed Transformation
+//===----------------------------------------------------------------------===//
+
 bool FunctionSignatureTransform::OwnedToGuaranteedAnalyzeParameters() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
   auto Args = F->begin()->getFunctionArguments();
   // A map from consumed SILArguments to the release associated with an
   // argument.
@@ -862,7 +895,7 @@
 
   // Analyze the argument information.
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-    ArgumentDescriptor &A = ArgumentDescList[i];
+    ArgumentDescriptor &A = TransformDescriptor.ArgumentDescList[i];
     if (!A.canOptimizeLiveArg()) {
       continue;
     }
@@ -890,13 +923,16 @@
 
     // Modified self argument.
     if (A.OwnedToGuaranteed && Args[i]->isSelf()) {
-      shouldModifySelfArgument = true;
+      TransformDescriptor.shouldModifySelfArgument = true;
     }
   }
   return SignatureOptimize;
 }
 
 bool FunctionSignatureTransform::OwnedToGuaranteedAnalyzeResults() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
+  auto ResultDescList = TransformDescriptor.ResultDescList;
+
   auto fnConv = F->getConventions();
   // For now, only do anything if there's a single direct result.
   if (fnConv.getNumDirectSILResults() != 1)
@@ -928,7 +964,7 @@
 void FunctionSignatureTransform::OwnedToGuaranteedTransformFunctionParameters() {
   // And remove all Callee releases that we found and made redundant via owned
   // to guaranteed conversion.
-  for (const ArgumentDescriptor &AD : ArgumentDescList) {
+  for (const ArgumentDescriptor &AD : TransformDescriptor.ArgumentDescList) {
     if (!AD.OwnedToGuaranteed)
       continue;
     for (auto &X : AD.CalleeRelease) { 
@@ -947,7 +983,7 @@
 void FunctionSignatureTransform::OwnedToGuaranteedTransformFunctionResults() {
   // And remove all callee retains that we found and made redundant via owned
   // to unowned conversion.
-  for (const ResultDescriptor &RD : ResultDescList) {
+  for (const ResultDescriptor &RD : TransformDescriptor.ResultDescList) {
     if (!RD.OwnedToGuaranteed)
       continue;
     for (auto &X : RD.CalleeRetain) {
@@ -965,10 +1001,10 @@
 void FunctionSignatureTransform::
 OwnedToGuaranteedFinalizeThunkFunction(SILBuilder &Builder, SILFunction *F) {
   // Finish the epilogue work for the argument as well as result.
-  for (auto &ArgDesc : ArgumentDescList) {
+  for (auto &ArgDesc : TransformDescriptor.ArgumentDescList) {
     OwnedToGuaranteedAddArgumentRelease(ArgDesc, Builder, F);
   }
-  for (auto &ResDesc : ResultDescList) {
+  for (auto &ResDesc : TransformDescriptor.ResultDescList) {
     OwnedToGuaranteedAddResultRelease(ResDesc, Builder, F);
   }
 }
@@ -1039,10 +1075,12 @@
   }
 }
 
-/// ----------------------------------------------------------///
-/// Argument Explosion transformation.                        ///
-/// ----------------------------------------------------------///
+//===----------------------------------------------------------------------===//
+//                     Argument Explosion Transformation
+//===----------------------------------------------------------------------===//
+
 bool FunctionSignatureTransform::ArgumentExplosionAnalyzeParameters() {
+  SILFunction *F = TransformDescriptor.OriginalFunction;
   // Did we decide we should optimize any parameter?
   bool SignatureOptimize = false;
   auto Args = F->begin()->getFunctionArguments();
@@ -1051,7 +1089,7 @@
 
   // Analyze the argument information.
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
-    ArgumentDescriptor &A = ArgumentDescList[i];
+    ArgumentDescriptor &A = TransformDescriptor.ArgumentDescList[i];
     // Do not optimize argument.
     if (!A.canOptimizeLiveArg()) {
       continue;
@@ -1066,7 +1104,7 @@
 
     // Modified self argument.
     if (A.Explode && Args[i]->isSelf()) {
-      shouldModifySelfArgument = true;
+      TransformDescriptor.shouldModifySelfArgument = true;
     }
 
     SignatureOptimize |= A.Explode;
@@ -1075,14 +1113,15 @@
 }
 
 void FunctionSignatureTransform::ArgumentExplosionFinalizeOptimizedFunction() {
+  SILFunction *NewF = TransformDescriptor.OptimizedFunction.get();
   SILBasicBlock *BB = &*NewF->begin();
   SILBuilder Builder(BB->begin());
   Builder.setCurrentDebugScope(BB->getParent()->getDebugScope());
   unsigned TotalArgIndex = 0;
-  for (ArgumentDescriptor &AD : ArgumentDescList) {
+  for (ArgumentDescriptor &AD : TransformDescriptor.ArgumentDescList) {
     // Simply continue if do not explode.
     if (!AD.Explode) {
-      AIM[TotalArgIndex] = AD.Index;
+      TransformDescriptor.AIM[TotalArgIndex] = AD.Index;
       TotalArgIndex ++;
       continue;
     }
@@ -1102,7 +1141,7 @@
       LeafValues.push_back(BB->insertFunctionArgument(
           ArgOffset++, Node->getType(), OwnershipKind,
           BB->getArgument(OldArgIndex)->getDecl()));
-      AIM[TotalArgIndex - 1] = AD.Index;
+      TransformDescriptor.AIM[TotalArgIndex - 1] = AD.Index;
       TotalArgIndex ++;
     }