Skip to content

Commit 90e599b

Browse files
authored
Merge pull request swiftlang#83946 from eeckstein/fix-simplify-alloc-stack-apply-6.2
[6.2] Optimizer: fix handling of dependent existential archetypes in `alloc_stack` and `apply` simplification
2 parents 59fa858 + 77a2954 commit 90e599b

File tree

7 files changed

+106
-5
lines changed

7 files changed

+106
-5
lines changed

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
4848

4949
public var instanceTypeOfMetatype: Type { Type(bridged: bridged.getInstanceTypeOfMetatype()) }
5050

51+
public var staticTypeOfDynamicSelf: Type { Type(bridged: bridged.getStaticTypeOfDynamicSelf()) }
52+
53+
public var interfaceTypeOfArchetype: Type { Type(bridged: bridged.getInterfaceTypeOfArchetype()) }
54+
5155
public var superClassType: Type? {
5256
precondition(isClass)
5357
let bridgedSuperClassTy = bridged.getSuperClassType()
@@ -136,10 +140,14 @@ extension TypeProperties {
136140

137141
public var isTuple: Bool { rawType.bridged.isTuple() }
138142
public var isFunction: Bool { rawType.bridged.isFunction() }
143+
public var isArchetype: Bool { rawType.bridged.isArchetype() }
139144
public var isExistentialArchetype: Bool { rawType.bridged.isExistentialArchetype() }
140145
public var isExistentialArchetypeWithError: Bool { rawType.bridged.isExistentialArchetypeWithError() }
146+
public var isRootArchetype: Bool { rawType.interfaceTypeOfArchetype.isGenericTypeParameter }
147+
public var isRootExistentialArchetype: Bool { isExistentialArchetype && isRootArchetype }
141148
public var isExistential: Bool { rawType.bridged.isExistential() }
142149
public var isClassExistential: Bool { rawType.bridged.isClassExistential() }
150+
public var isGenericTypeParameter: Bool { rawType.bridged.isGenericTypeParam() }
143151
public var isUnownedStorageType: Bool { return rawType.bridged.isUnownedStorageType() }
144152
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
145153
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
@@ -187,6 +195,7 @@ extension TypeProperties {
187195
public var isEscapable: Bool { rawType.bridged.isEscapable() }
188196
public var isNoEscape: Bool { rawType.bridged.isNoEscape() }
189197
public var isBuiltinType: Bool { rawType.bridged.isBuiltinType() }
198+
public var archetypeRequiresClass: Bool { rawType.bridged.archetypeRequiresClass() }
190199

191200
public var representationOfMetatype: AST.`Type`.MetatypeRepresentation {
192201
rawType.bridged.getRepresentationOfMetatype().representation

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ private extension AllocStackInst {
179179
/// use %3
180180
/// ```
181181
func optimizeExistential(_ context: SimplifyContext) -> Bool {
182-
guard type.isExistential || type.isExistentialArchetype,
182+
// TODO: support non-root existential archetypes
183+
guard type.isExistential || type.isRootExistentialArchetype,
183184
let concreteFormalType = getConcreteTypeOfExistential()
184185
else {
185186
return false

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,9 @@ private extension FullApplySite {
170170
// Make sure that existential archetype _is_ a replacement type and not e.g. _contained_ in a
171171
// replacement type, like
172172
// apply %1<Array<@opened("...")>()
173-
guard substitutionMap.replacementTypes.contains(where: { $0.isExistentialArchetype }),
174-
substitutionMap.replacementTypes.allSatisfy({ $0.isExistentialArchetype || !$0.hasLocalArchetype })
173+
// TODO: support non-root existential archetypes
174+
guard substitutionMap.replacementTypes.contains(where: { $0.isRootExistentialArchetype }),
175+
substitutionMap.replacementTypes.allSatisfy({ $0.isRootExistentialArchetype || !$0.hasLocalArchetype })
175176
else {
176177
return false
177178
}
@@ -191,9 +192,9 @@ private extension FullApplySite {
191192
let type = value.type
192193
// Allow three cases:
193194
// case 1. the argument _is_ the existential archetype
194-
return type.isExistentialArchetype ||
195+
return type.isRootExistentialArchetype ||
195196
// case 2. the argument _is_ a metatype of the existential archetype
196-
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
197+
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isRootExistentialArchetype) ||
197198
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
198199
!type.hasLocalArchetype
199200
}

include/swift/AST/ASTBridging.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,11 +3100,14 @@ struct BridgedASTType {
31003100
BRIDGED_INLINE bool isGenericAtAnyLevel() const;
31013101
BRIDGED_INLINE bool hasTypeParameter() const;
31023102
BRIDGED_INLINE bool hasLocalArchetype() const;
3103+
BRIDGED_INLINE bool isArchetype() const;
3104+
BRIDGED_INLINE bool archetypeRequiresClass() const;
31033105
BRIDGED_INLINE bool isExistentialArchetype() const;
31043106
BRIDGED_INLINE bool isExistentialArchetypeWithError() const;
31053107
BRIDGED_INLINE bool isExistential() const;
31063108
BRIDGED_INLINE bool isDynamicSelf() const;
31073109
BRIDGED_INLINE bool isClassExistential() const;
3110+
BRIDGED_INLINE bool isGenericTypeParam() const;
31083111
BRIDGED_INLINE bool isEscapable() const;
31093112
BRIDGED_INLINE bool isNoEscape() const;
31103113
BRIDGED_INLINE bool isInteger() const;
@@ -3129,6 +3132,8 @@ struct BridgedASTType {
31293132
BRIDGED_INLINE TraitResult canBeClass() const;
31303133
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedDeclObj getAnyNominal() const;
31313134
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInstanceTypeOfMetatype() const;
3135+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getStaticTypeOfDynamicSelf() const;
3136+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getInterfaceTypeOfArchetype() const;
31323137
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getSuperClassType() const;
31333138
BRIDGED_INLINE MetatypeRepresentation getRepresentationOfMetatype() const;
31343139
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getContextSubstitutionMap() const;

include/swift/AST/ASTBridgingImpl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,14 @@ bool BridgedASTType::hasLocalArchetype() const {
423423
return unbridged()->hasLocalArchetype();
424424
}
425425

426+
bool BridgedASTType::isArchetype() const {
427+
return unbridged()->is<swift::ArchetypeType>();
428+
}
429+
430+
bool BridgedASTType::archetypeRequiresClass() const {
431+
return unbridged()->castTo<swift::ArchetypeType>()->requiresClass();
432+
}
433+
426434
bool BridgedASTType::isExistentialArchetype() const {
427435
return unbridged()->is<swift::ExistentialArchetypeType>();
428436
}
@@ -443,6 +451,10 @@ bool BridgedASTType::isClassExistential() const {
443451
return unbridged()->isClassExistentialType();
444452
}
445453

454+
bool BridgedASTType::isGenericTypeParam() const {
455+
return unbridged()->is<swift::GenericTypeParamType>();
456+
}
457+
446458
bool BridgedASTType::isEscapable() const {
447459
return unbridged()->isEscapable();
448460
}
@@ -551,6 +563,14 @@ BridgedASTType BridgedASTType::getInstanceTypeOfMetatype() const {
551563
return {unbridged()->getAs<swift::AnyMetatypeType>()->getInstanceType().getPointer()};
552564
}
553565

566+
BridgedASTType BridgedASTType::getStaticTypeOfDynamicSelf() const {
567+
return {unbridged()->getAs<swift::DynamicSelfType>()->getSelfType().getPointer()};
568+
}
569+
570+
BridgedASTType BridgedASTType::getInterfaceTypeOfArchetype() const {
571+
return {unbridged()->getAs<swift::ArchetypeType>()->getInterfaceType().getPointer()};
572+
}
573+
554574
BridgedASTType BridgedASTType::getSuperClassType() const {
555575
return {unbridged()->getSuperclass().getPointer()};
556576
}

test/SILOptimizer/simplify_alloc_stack.sil

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,27 @@ public struct S {}
1010
protocol P {
1111
}
1212

13+
protocol Q {
14+
associatedtype A
15+
}
16+
1317
public class C2: P {}
1418

1519
public struct T: P {
1620
let c: C
1721
let s: S
22+
23+
struct A {
24+
var y: String
25+
}
26+
}
27+
28+
public struct U: Q {
29+
let s: String
30+
31+
struct A {
32+
var y: String
33+
}
1834
}
1935

2036
public struct T1: P {
@@ -235,6 +251,24 @@ bb0(%0 : @owned $T):
235251
return %r
236252
}
237253

254+
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
255+
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
256+
// CHECK: alloc_stack {{.*}}@opened
257+
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
258+
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (@owned U.A) -> () {
259+
bb0(%0 : @owned $U.A):
260+
%1 = metatype $@thick U.Type
261+
%2 = init_existential_metatype %1, $@thick Q.Type
262+
%3 = open_existential_metatype %2 to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).Type
263+
%4 = alloc_stack $(@opened("82105EE0-DCB0-11E5-865D-C8E0EB309914", Q) Self).A
264+
%5 = unchecked_addr_cast %4 to $*U.A
265+
store %0 to [init] %5
266+
destroy_addr %4
267+
dealloc_stack %4
268+
%r = tuple ()
269+
return %r
270+
}
271+
238272
// CHECK-LABEL: sil [ossa] @replace_existential_with_concrete_type1 :
239273
// CHECK: [[S:%.*]] = alloc_stack $T
240274
// CHECK-NOT: init_existential_addr

test/SILOptimizer/simplify_apply.sil

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ struct GenS<T> {
2626
var x: Int
2727
}
2828

29+
protocol P2 {
30+
associatedtype A: Q
31+
}
32+
33+
protocol Q {
34+
}
35+
36+
public struct S2: P2 {
37+
var x: String
38+
struct A: Q {
39+
var y: String
40+
}
41+
}
42+
2943
sil @cl : $@convention(thin) () -> Int
3044

3145
// CHECK-LABEL: sil [ossa] @thick_to_thin :
@@ -60,6 +74,7 @@ sil_vtable Bar {
6074
}
6175

6276
sil @createit : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type, Int) -> @out τ_0_0
77+
sil @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
6378
sil @useGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (GenS<τ_0_0>) -> ()
6479
sil @returnGenS : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> GenS<τ_0_0>
6580

@@ -124,6 +139,22 @@ bb0(%0 : $Int):
124139
return %11
125140
}
126141

142+
// TODO: we don't support dependent existential archetypes, yet. Once we do, change this test case.
143+
// CHECK-LABEL: sil [ossa] @dont_replace_dependent_archetype :
144+
// CHECK: apply %{{[0-9]+}}<@opened
145+
// CHECK: } // end sil function 'dont_replace_dependent_archetype'
146+
sil [ossa] @dont_replace_dependent_archetype : $@convention(thin) (Int) -> @out any Q {
147+
bb0(%0 : $*any Q, %1 : $Int):
148+
%2 = metatype $@thick S2.Type
149+
%3 = init_existential_metatype %2, $@thick any P2.Type
150+
%4 = open_existential_metatype %3 to $@thick (@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).Type
151+
%6 = function_ref @create2 : $@convention(thin) <τ_0_0 where τ_0_0 : Q> (Int) -> @out τ_0_0
152+
%7 = init_existential_addr %0, $(@opened("0FC03D78-E9DB-11EF-B47C-0EA13E3AABB4", any P2) Self).A
153+
%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
154+
%11 = tuple ()
155+
return %11
156+
}
157+
127158
// CHECK-LABEL: sil [ossa] @dont_replace_returned_embedded_archetype :
128159
// CHECK: apply %{{[0-9]+}}<@opened
129160
// CHECK: } // end sil function 'dont_replace_returned_embedded_archetype'

0 commit comments

Comments
 (0)