Merge pull request #14832 from gottesmm/swift-4.1-branchrdar37820485

[arc] An apply of a callee_guaranteed thick function is a "guaranteed…
diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
index ddf50c8..c88021b 100644
--- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
@@ -441,8 +441,17 @@
 
   FullApplySite FAS(User);
 
-  // Ok, we have a full apply site. If the apply has no arguments, we don't need
-  // to worry about any guaranteed parameters.
+  // Ok, we have a full apply site. Check if the callee is callee_guaranteed. In
+  // such a case, if we can not prove no alias, we need to be conservative and
+  // return true.
+  CanSILFunctionType FType = FAS.getSubstCalleeType();
+  if (FType->isCalleeGuaranteed() && !AA->isNoAlias(FAS.getCallee(), Ptr)) {
+    return true;
+  }
+
+  // Ok, we have a full apply site and our callee is a normal use. Thus if the
+  // apply does not have any normal arguments, we don't need to worry about any
+  // guaranteed parameters and return early.
   if (!FAS.getNumArguments())
     return false;
 
@@ -450,7 +459,6 @@
   // iterate through the function parameters. If any of the parameters are
   // guaranteed, attempt to prove that the passed in parameter cannot alias
   // Ptr. If we fail, return true.
-  CanSILFunctionType FType = FAS.getSubstCalleeType();
   auto Params = FType->getParameters();
   for (unsigned i : indices(Params)) {    
     if (!Params[i].isGuaranteed())
diff --git a/test/SILOptimizer/arcsequenceopts.sil b/test/SILOptimizer/arcsequenceopts.sil
index 1ba2037..c1ad811 100644
--- a/test/SILOptimizer/arcsequenceopts.sil
+++ b/test/SILOptimizer/arcsequenceopts.sil
@@ -2146,3 +2146,20 @@
   strong_release %1 : $Builtin.NativeObject
   return undef : $()
 }
+
+// Make sure that we treat applications of callee_guaranteed functions as a
+// guaranteed use of the function object.
+//
+// CHECK-LABEL: sil @test_callee_guaranteed_is_treated_as_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+// CHECK: strong_retain
+// CHECK: apply
+// CHECK: strong_release
+// CHECK: } // end sil function 'test_callee_guaranteed_is_treated_as_guaranteed'
+sil @test_callee_guaranteed_is_treated_as_guaranteed : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+bb0(%0 : $@callee_guaranteed () -> ()):
+  strong_retain %0 : $@callee_guaranteed () -> ()
+  apply %0() : $@callee_guaranteed () -> ()
+  strong_release %0 : $@callee_guaranteed () -> ()
+  %9999 = tuple()
+  return %9999 : $()
+}