Skip to content

Commit 53eaa76

Browse files
committed
[SIL][Optimizer] eliminate @pack_element types
* SwiftCompilerSources/Sources/AST/Type.swift * SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift * SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyUncheckedAddrCast.swift * SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyWitnessMethod.swift * SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift * include/swift/AST/ASTBridging.h * include/swift/AST/ASTBridgingImpl.h
1 parent 62d8a6a commit 53eaa76

File tree

7 files changed

+113
-0
lines changed

7 files changed

+113
-0
lines changed

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ extension TypeProperties {
273273
public var isSILPackElementAddress: Bool {
274274
return rawType.bridged.isSILPackElementAddress()
275275
}
276+
277+
public func getPackElementType(_ index: Int) -> Type {
278+
return Type(bridged: rawType.bridged.getPackElementType(index));
279+
}
276280
}
277281

278282
public struct TypeArray : RandomAccessCollection, CustomReflectable {

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extension AllocStackInst : Simplifiable, SILCombineSimplifiable {
1919
return
2020
}
2121
_ = optimizeExistential(context)
22+
_ = optimizePackElement(context)
2223
}
2324
}
2425

@@ -302,4 +303,37 @@ private extension AllocStackInst {
302303
}
303304
return concreteType
304305
}
306+
307+
/// Replaces an alloc_stack of an Pack Element by an alloc_stack of the concrete type.
308+
///
309+
/// For example:
310+
/// ```
311+
/// %0 = alloc_stack $@pack_element(...) ...
312+
/// use %1
313+
/// ```
314+
/// is transformed to
315+
/// ```
316+
/// %0 = alloc_stack $T
317+
/// use %0
318+
/// ```
319+
///
320+
private func optimizePackElement(_ context: SimplifyContext) -> Bool {
321+
guard let concreteType = concreteTypeOfDependentPackElementArchetype else {
322+
return false
323+
}
324+
325+
let builder = Builder(before: self, context)
326+
let newAlloc = builder.createAllocStack(concreteType.loweredType(in: parentFunction),
327+
hasDynamicLifetime: hasDynamicLifetime,
328+
isLexical: isLexical,
329+
isFromVarDecl: isFromVarDecl,
330+
usesMoveableValueDebugInfo: usesMoveableValueDebugInfo)
331+
for use in uses {
332+
// FIXME: Are there any specific cases to handle?
333+
use.set(to: newAlloc, context)
334+
}
335+
context.erase(instruction: self)
336+
return true
337+
}
338+
305339
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyUncheckedAddrCast.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ extension UncheckedAddrCastInst : OnoneSimplifiable, SILCombineSimplifiable {
4545
// %1 = vector_base_addr %0 : $*Builtin.FixedArray<N, Element>
4646
// ```
4747
_ = optimizeVectorBaseCast(context)
48+
49+
// ```
50+
// %1 = unchecked_addr_cast %0 to $*pack_element("...") ...
51+
// ```
52+
// ->
53+
// ```
54+
// %1 = unchecked_addr_cast %0 to $T
55+
// ```
56+
_ = optimizePackElement(context)
57+
4858
}
4959
}
5060

@@ -78,4 +88,16 @@ private extension UncheckedAddrCastInst {
7888
}
7989
return false
8090
}
91+
92+
private func optimizePackElement(_ context: SimplifyContext) -> Bool {
93+
guard let concreteType = concreteTypeOfDependentPackElementArchetype else {
94+
return false
95+
}
96+
97+
let builder = Builder(before: self, context)
98+
let newCast = builder.createUncheckedAddrCast(from: fromAddress,
99+
to:concreteType.loweredType(in: parentFunction).addressType)
100+
self.replace(with: newCast, context)
101+
return true
102+
}
81103
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyWitnessMethod.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import SIL
1616
extension WitnessMethodInst : Simplifiable, SILCombineSimplifiable {
1717
func simplify(_ context: SimplifyContext) {
1818
_ = tryReplaceExistentialArchetype(of: self, context)
19+
_ = tryReplacePackElementArchetype(of: self, context)
1920
}
2021
}
2122

@@ -46,3 +47,31 @@ private func tryReplaceExistentialArchetype(of witnessMethod: WitnessMethodInst,
4647
witnessMethod.replace(with: newWmi, context)
4748
return true
4849
}
50+
51+
/// If the witness_method operates on a pack element archetype (`@pack_element("...")`) and the concrete
52+
/// type is known, replace the pack element archetype with the concrete type.
53+
/// For example:
54+
/// ```
55+
/// %3 = witness_method $@pack_element("...") Self, #P.foo, %2
56+
/// ```
57+
/// ->
58+
/// ```
59+
/// %3 = witness_method $ConcreteType, #P.foo, %2
60+
/// ```
61+
private func tryReplacePackElementArchetype(of witnessMethod: WitnessMethodInst, _ context: SimplifyContext) -> Bool {
62+
guard let concreteType = witnessMethod.concreteTypeOfDependentPackElementArchetype else {
63+
return false
64+
}
65+
let conf = concreteType.checkConformance(to: witnessMethod.lookupProtocol)
66+
guard conf.isValid else {
67+
return false
68+
}
69+
70+
let builder = Builder(before: witnessMethod, context)
71+
let newWmi = builder.createWitnessMethod(lookupType: concreteType,
72+
conformance: conf,
73+
member: witnessMethod.member,
74+
methodType: witnessMethod.type)
75+
witnessMethod.replace(with: newWmi, context)
76+
return true
77+
}

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,24 @@ extension Instruction {
547547
return nil
548548
}
549549

550+
var concreteTypeOfDependentPackElementArchetype: CanonicalType? {
551+
// For simplicity only support a single type dependent operand, which is true in most of the cases anyway.
552+
if let openArchetypeOp = typeDependentOperands.singleElement,
553+
// Match the sequence
554+
// %1 = integer_literal $Builtin.Word, (integer value)
555+
// %2 = dynamic_pack_index %1 of $Pack{...}
556+
// %3 = open_pack_element %2 of ...
557+
// this_instruction_which_uses $*@pack_element(...) // type-defs: %3
558+
let ope = openArchetypeOp.value as? OpenPackElementInst,
559+
let dpi = ope.operands.first?.value as? DynamicPackIndexInst,
560+
let ili = dpi.operands.first?.value as? IntegerLiteralInst,
561+
let index = ili.value
562+
{
563+
return dpi.indexedPackType.getPackElementType(index).canonical
564+
}
565+
return nil
566+
}
567+
550568
/// Returns true if a destroy of `type` must not be moved across this instruction.
551569
func isBarrierForDestroy(of type: Type, _ context: some Context) -> Bool {
552570
let instEffects = memoryEffects

include/swift/AST/ASTBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,7 @@ struct BridgedASTType {
29942994
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance checkConformance(BridgedDeclObj proto) const;
29952995
BRIDGED_INLINE bool containsSILPackExpansionType() const;
29962996
BRIDGED_INLINE bool isSILPackElementAddress() const;
2997+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getPackElementType(SwiftInt index) const;
29972998
};
29982999

29993000
class BridgedCanType {

include/swift/AST/ASTBridgingImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,11 @@ bool BridgedASTType::isSILPackElementAddress() const {
656656
return unbridged()->castTo<swift::SILPackType>()->isElementAddress();
657657
}
658658

659+
BridgedASTType BridgedASTType::getPackElementType(SwiftInt index) const {
660+
ASSERT(index >= 0);
661+
return {unbridged()->castTo<swift::PackType>()->getElementType(index).getPointer()};
662+
}
663+
659664
static_assert((int)BridgedASTType::TraitResult::IsNot == (int)swift::TypeTraitResult::IsNot);
660665
static_assert((int)BridgedASTType::TraitResult::CanBe == (int)swift::TypeTraitResult::CanBe);
661666
static_assert((int)BridgedASTType::TraitResult::Is == (int)swift::TypeTraitResult::Is);

0 commit comments

Comments
 (0)