Merge pull request #4480 from eeckstein/partial-apply-opt2

address gottesmm's and jrose-apple's comments on the partial_apply optimization
diff --git a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
index 309997f..770d55c 100644
--- a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
@@ -53,6 +53,7 @@
     llvm::SmallSet<SILFunction *, 4> Callers;
 
     /// The number of partial applied arguments of this function.
+    ///
     /// Specifically, it stores the minimum number of partial applied arguments
     /// of each function which contain one or multiple partial_applys of this
     /// function.
@@ -67,6 +68,7 @@
     }
 
     /// Returns non zero if this function is partially applied anywhere.
+    ///
     /// The return value is the minimum number of partially applied arguments.
     /// Usually all partial applies of a function partially apply the same
     /// number of arguments anyway.
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index a60a00b..6bee0b0 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -286,7 +286,7 @@
 
 /// Returns true if block \p BB only contains a return or throw of the first
 /// block argument and side-effect-free instructions.
-static bool isArgReturnOrThrow(SILBasicBlock *BB) {
+static bool onlyContainsReturnOrThrowOfArg(SILBasicBlock *BB) {
   for (SILInstruction &I : *BB) {
     if (isa<ReturnInst>(&I) || isa<ThrowInst>(&I)) {
       SILValue RetVal = I.getOperand(0);
@@ -349,8 +349,8 @@
 
       if (TryApplyInst *TAI = dyn_cast<TryApplyInst>(&I)) {
         // Check the normal and throw blocks of the try_apply.
-        if (isArgReturnOrThrow(TAI->getNormalBB()) &&
-            isArgReturnOrThrow(TAI->getErrorBB()))
+        if (onlyContainsReturnOrThrowOfArg(TAI->getNormalBB()) &&
+            onlyContainsReturnOrThrowOfArg(TAI->getErrorBB()))
           return Specialized;
         return nullptr;
       }
diff --git a/test/SILOptimizer/functionsigopts.sil b/test/SILOptimizer/functionsigopts.sil
index 2754a1a..37072ea 100644
--- a/test/SILOptimizer/functionsigopts.sil
+++ b/test/SILOptimizer/functionsigopts.sil
@@ -1326,6 +1326,27 @@
 }
 
 
+// Check if externally available functions are optimized.
+
+sil public_external [noinline] @externally_available_with_dead_arg : $@convention(thin) (@guaranteed foo) -> () {
+bb0(%0 : $foo):
+  %r = tuple()
+  return %r : $()
+}
+
+// CHECK-LABEL: sil @call_externally_available
+// CHECK: [[F:%[0-9]+]] = function_ref @_TTSf4d__externally_available_with_dead_arg : $@convention(thin) () -> ()
+// CHECK: apply [[F]]()
+// CHECK: return
+sil @call_externally_available : $@convention(thin) (@guaranteed foo) -> () {
+bb0(%0 : $foo):
+  %f = function_ref @externally_available_with_dead_arg : $@convention(thin) (@guaranteed foo) -> ()
+  %a = apply %f(%0) : $@convention(thin) (@guaranteed foo) -> ()
+  %r = tuple()
+  return %r : $()
+}
+
+
 // We should remove the array semantic from specialized calls.
 
 // CHECK-LABEL: sil [fragile] [thunk] [always_inline] [_semantics "array.foobar"] @array_semantic : $@convention(method) (@owned Builtin.NativeObject) -> () {