diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift index 5fe28a090ea..e7fbdad4933 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift @@ -179,7 +179,8 @@ private extension AllocStackInst { /// use %3 /// ``` func optimizeExistential(_ context: SimplifyContext) -> Bool { - guard type.isExistential || type.isExistentialArchetype, + // TODO: support non-root existential archetypes + guard type.isExistential || type.isRootExistentialArchetype, let concreteFormalType = getConcreteTypeOfExistential() else { return false diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift index 7def68d6389..046ed4a08f4 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift @@ -170,8 +170,9 @@ private extension FullApplySite { // Make sure that existential archetype _is_ a replacement type and not e.g. _contained_ in a // replacement type, like // apply %1() - guard substitutionMap.replacementTypes.contains(where: { $0.isExistentialArchetype }), - substitutionMap.replacementTypes.allSatisfy({ $0.isExistentialArchetype || !$0.hasLocalArchetype }) + // TODO: support non-root existential archetypes + guard substitutionMap.replacementTypes.contains(where: { $0.isRootExistentialArchetype }), + substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype }) else { return false } @@ -191,9 +192,9 @@ private extension FullApplySite { let type = value.type // Allow three cases: // case 1. the argument _is_ the existential archetype - return type.isExistentialArchetype || + return type.isRootExistentialArchetype || // case 2. the argument _is_ a metatype of the existential archetype - (type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) || + (type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isRootExistentialArchetype) || // case 3. the argument has nothing to do with the existential archetype (or any other local archetype) !type.hasLocalArchetype } diff --git a/test/SILOptimizer/simplify_alloc_stack.sil b/test/SILOptimizer/simplify_alloc_stack.sil index 9a5e4b5e143..d1623d23cef 100644 --- a/test/SILOptimizer/simplify_alloc_stack.sil +++ b/test/SILOptimizer/simplify_alloc_stack.sil @@ -10,11 +10,27 @@ public struct S {} protocol P { } +protocol Q { + associatedtype A +} + public class C2: P {} public struct T: P { let c: C let s: S + + struct A { + var y: String + } +} + +public struct U: Q { + let s: String + + struct A { + var y: String + } } public struct T1: P { @@ -235,6 +251,24 @@ bb0(%0 : @owned $T): return %r } +// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case. +// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype : +// CHECK: alloc_stack {{.*}}@opened +// CHECK: } // end sil function 'dont_replace_dependent_archetype' +sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (@owned U.A) -> () { +bb0(%0 : @owned $U.A): + %1 = metatype $@thick U.Type + %2 = init_existential_metatype %1, $@thick Q.Type + %3 = open_existential_metatype %2 to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).Type + %4 = alloc_stack $(@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).A + %5 = unchecked_addr_cast %4 to $*U.A + store %0 to [init] %5 + destroy_addr %4 + dealloc_stack %4 + %r = tuple () + return %r +} + // CHECK-LABEL: sil [ossa] @replace_existential_with_concrete_type1 : // CHECK: [[S:%.*]] = alloc_stack $T // CHECK-NOT: init_existential_addr diff --git a/test/SILOptimizer/simplify_apply.sil b/test/SILOptimizer/simplify_apply.sil index 0e4614ee83a..25e5e8b2b2e 100644 --- a/test/SILOptimizer/simplify_apply.sil +++ b/test/SILOptimizer/simplify_apply.sil @@ -26,6 +26,20 @@ struct GenS { var x: Int } +protocol P2 { + associatedtype A: Q +} + +protocol Q { +} + +public struct S2: P2 { + var x: String + struct A: Q { + var y: String + } +} + sil @cl : $@convention(thin) () -> Int // CHECK-LABEL: sil [ossa] @thick_to_thin : @@ -60,6 +74,7 @@ sil_vtable Bar { } sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type, Int) -> @out τ_0_0 +sil @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0 sil @useGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (GenS<τ_0_0>) -> () sil @returnGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> GenS<τ_0_0> @@ -124,6 +139,22 @@ bb0(%0 : $Int): return %11 } +// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case. +// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype : +// CHECK: apply %{{[0-9]+}}<@opened +// CHECK: } // end sil function 'dont_replace_dependent_archetype' +sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (Int) -> @out any Q { +bb0(%0 : $*any Q, %1 : $Int): + %2 = metatype $@thick S2.Type + %3 = init_existential_metatype %2, $@thick any P2.Type + %4 = open_existential_metatype %3 to $@thick (@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).Type + %6 = function_ref @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0 + %7 = init_existential_addr %0, $(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A + %8 = apply %6<(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A>(%7, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0 + %11 = tuple () + return %11 +} + // CHECK-LABEL: sil [ossa] @dont_replace_returned_embedded_archetype : // CHECK: apply %{{[0-9]+}}<@opened // CHECK: } // end sil function 'dont_replace_returned_embedded_archetype'