Merge pull request #16833 from gottesmm/pr-36d7415d3531d61aabb8231290000c5797d2bf8e

diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 56c6c6c..1604f8d 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -323,10 +323,15 @@
 
   // Casting to a less-optional type can always fail.
   } else if (sourceObject) {
-    return atBest(classifyDynamicCast(M, sourceObject, target,
-                                      /* isSourceTypeExact */ false,
-                                      isWholeModuleOpts),
-                  DynamicCastFeasibility::MaySucceed);
+    auto result = atBest(classifyDynamicCast(M, sourceObject, target,
+                                             /* isSourceTypeExact */ false,
+                                             isWholeModuleOpts),
+                         DynamicCastFeasibility::MaySucceed);
+    if (target.isExistentialType()) {
+      result = atWorst(result, classifyDynamicCastToProtocol(
+                                   M, source, target, isWholeModuleOpts));
+    }
+    return result;
   }
   assert(!sourceObject && !targetObject);
 
diff --git a/test/SILOptimizer/cast_folding.swift b/test/SILOptimizer/cast_folding.swift
index 26a71b9..6f27f50 100644
--- a/test/SILOptimizer/cast_folding.swift
+++ b/test/SILOptimizer/cast_folding.swift
@@ -1032,6 +1032,39 @@
   return P.Type.self as? P.Type.Type
 }
 
+protocol PForOptional {
+}
+
+extension Optional: PForOptional {
+}
+
+func testCastToPForOptional<T>(_ t: T) -> Bool {
+  if let _ = t as? PForOptional {
+    return true
+  }
+  return false
+}
+
+// CHECK-LABEL: // testCastToPForOptionalSuccess()
+// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: [[RET:%.*]] = struct $Bool ([[RES]] : $Builtin.Int1)
+// CHECK: return [[RET]] : $Bool
+@inline(never)
+public func testCastToPForOptionalSuccess() -> Bool {
+  let t: Int? = 42
+  return testCastToPForOptional(t)
+}
+
+// CHECK-LABEL: // testCastToPForOptionalFailure()
+// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int1, 0
+// CHECK: [[RET:%.*]] = struct $Bool ([[RES]] : $Builtin.Int1)
+// CHECK: return [[RET]] : $Bool
+@inline(never)
+public func testCastToPForOptionalFailure() -> Bool {
+  let t: Int = 42
+  return testCastToPForOptional(t)
+}
+
 print("test0=\(test0())")
 
 print("test1=\(test1())")