Skip to content

Commit 2d8046a

Browse files
committed
PackSpecialization: Fix result & type parameter handling
We can avoid issues with loweredType failing by not calling it. We should also only get the SILType for results that we actually intend to explode. Attempting to explode packs containing generic type parameters lead to compiler crashes. It is preferable to wait until generic types have been replaced with concrete types to explode packs, since we can only pass exploded pack elements directly if we know they are loadable.
1 parent 1bb65d8 commit 2d8046a

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/PackSpecialization.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -633,10 +633,10 @@ private struct PackExplodedFunction {
633633

634634
var indirectResultIdx = 0
635635
for (resultIndex, resultInfo) in function.convention.results.enumerated() {
636-
let silType = resultInfo.type.loweredType(in: function)
637-
if silType.shouldExplode {
636+
if resultInfo.type.shouldExplode {
637+
let silType = function.arguments[indirectResultIdx].type
638+
638639
let mappedResultInfos = silType.packElements.map { elem in
639-
// TODO: Determine correct values for options and hasLoweredAddress
640640
ResultInfo(
641641
type: elem.canonicalType,
642642
convention: explodedPackElementResultConvention(in: function, type: elem),
@@ -1030,6 +1030,6 @@ extension TypeProperties {
10301030
/// A pack argument can explode if it contains no pack expansion types
10311031
fileprivate var shouldExplode: Bool {
10321032
// For now, we only attempt to explode indirect packs, since these are the most common and inefficient.
1033-
return isSILPack && !containsSILPackExpansionType && isSILPackElementAddress
1033+
return isSILPack && !hasTypeParameter && !containsSILPackExpansionType && isSILPackElementAddress
10341034
}
10351035
}

test/SILOptimizer/pack_specialization.sil

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,27 @@ bb0(%0 : $*Pack{any P}, %1 : $*Pack{any P}):
377377
return %17
378378
}
379379

380+
// Handling of generic type parameters in packs.
381+
// We should wait until these are fully specialized before exploding.
382+
sil [ossa] @copy_pack_generic : $@convention(thin) <T> (@pack_guaranteed Pack{T}) -> @pack_out Pack{T} {
383+
bb0(%0 : $*Pack{T}, %1 : $*Pack{T}):
384+
%2 = tuple ()
385+
return %2
386+
}
387+
388+
// CHECK-LABEL: sil [ossa] @call_copy_pack_generic : $@convention(thin) <T> (@pack_guaranteed Pack{T}) -> @pack_out Pack{T} {
389+
// CHECK: bb0(%0 : $*Pack{T}, %1 : $*Pack{T})
390+
// CHECK: [[CPG:%[0-9]+]] = function_ref @copy_pack_generic
391+
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[CPG]]
392+
// CHECK-NEXT: return [[RESULT]]
393+
// CHECK-LABEL: } // end sil function 'call_copy_pack_generic'
394+
sil [ossa] @call_copy_pack_generic : $@convention(thin) <T> (@pack_guaranteed Pack{T}) -> @pack_out Pack{T} {
395+
bb0(%0 : $*Pack{T}, %1 : $*Pack{T}):
396+
%16 = function_ref @copy_pack_generic : $@convention(thin) <T> (@pack_guaranteed Pack{T}) -> @pack_out Pack{T}
397+
%17 = apply %16<T>(%0, %1) : $@convention(thin) <T> (@pack_guaranteed Pack{T}) -> @pack_out Pack{T}
398+
return %17
399+
}
400+
380401
// INTERLEAVING PACK AND NON-PACK ARGUMENTS TESTS:
381402
//
382403
// The new function arguments and return values corresponding to pack parameters
@@ -699,7 +720,8 @@ bb0(%0 : $*Pack{Int}):
699720
// BAIL OUT CONDITION TESTS:
700721
//
701722
// Only perform pack specialization on functions that have indirect pack
702-
// parameters that contain no pack expansions.
723+
// parameters and/or results that contain no pack expansions or generic type
724+
// parameters.
703725
//
704726
// 2025-10-15: We currently only explode packs with address elements
705727
// (SILPackType::isElementAddress), because these are the most common (since
@@ -789,3 +811,54 @@ bb0(%0 : $*Pack{Int}):
789811
%2 = apply %1(%0) : $@convention(thin) (@pack_guaranteed Pack{Int}) -> ()
790812
return %2
791813
}
814+
815+
816+
sil [ossa] @indirect_result_pack : $@convention(thin) () -> @pack_out Pack{Int} {
817+
bb0(%0 : $*Pack{Int}):
818+
%1 = tuple ()
819+
return %1
820+
}
821+
822+
sil [ossa] @direct_result_pack : $@convention(thin) () -> @pack_out @direct Pack{Int} {
823+
bb0(%0 : $*@direct Pack{Int}):
824+
%1 = tuple ()
825+
return %1
826+
}
827+
828+
sil [ossa] @result_pack_expansion : $@convention(thin) <each A> () -> @pack_out Pack{repeat each A} {
829+
bb0(%0 : $*Pack{repeat each A}):
830+
%1 = tuple ()
831+
return %1
832+
}
833+
834+
sil [ossa] @mixed_result_packs : $@convention(thin) <each A> () -> (@pack_out Pack{Int}, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each A}) {
835+
bb0(%0 : $*Pack{Int}, %1 : $*@direct Pack{Int}, %2 : $*Pack{repeat each A}):
836+
%3 = tuple ()
837+
return %3
838+
}
839+
840+
// CHECK-LABEL: sil [ossa] @result_call_eligibility_tests : $@convention(thin) <each A> () -> (@pack_out Pack{Int}, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each A}) {
841+
// CHECK: bb0(%0 : $*Pack{Int}, %1 : $*@direct Pack{Int}, %2 : $*Pack{repeat each A}):
842+
// CHECK: function_ref @$s20indirect_result_packTf8x_n : $@convention(thin) () -> Int
843+
// CHECK: function_ref @direct_result_pack : $@convention(thin) () -> @pack_out @direct Pack{Int}
844+
// CHECK: function_ref @result_pack_expansion : $@convention(thin) <each τ_0_0> () -> @pack_out Pack{repeat each τ_0_0}
845+
// CHECK: function_ref @$s18mixed_result_packsTf8xnn_n : $@convention(thin) <each τ_0_0> () -> (Int, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each τ_0_0})
846+
// CHECK-LABEL: } // end sil function 'result_call_eligibility_tests'
847+
sil [ossa] @result_call_eligibility_tests : $@convention(thin) <each A> () -> (@pack_out Pack{Int}, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each A}) {
848+
bb0(%1 : $*Pack{Int}, %2 : $*@direct Pack{Int}, %3 : $*Pack{repeat each A}):
849+
850+
%4 = function_ref @indirect_result_pack : $@convention(thin) () -> @pack_out Pack{Int}
851+
%5 = apply %4(%1) : $@convention(thin) () -> @pack_out Pack{Int}
852+
853+
%8 = function_ref @direct_result_pack : $@convention(thin) () -> @pack_out @direct Pack{Int}
854+
%9 = apply %8(%2) : $@convention(thin) () -> @pack_out @direct Pack{Int}
855+
856+
%10 = function_ref @result_pack_expansion : $@convention(thin) <each A> () -> @pack_out Pack{repeat each A}
857+
%11 = apply %10<Pack{repeat each A}>(%3) : $@convention(thin) <each A> () -> @pack_out Pack{repeat each A}
858+
859+
%12 = function_ref @mixed_result_packs : $@convention(thin) <each A> () -> (@pack_out Pack{Int}, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each A})
860+
%13 = apply %12<Pack{repeat each A}>(%1, %2, %3) : $@convention(thin) <each A> () -> (@pack_out Pack{Int}, @pack_out @direct Pack{Int}, @pack_out Pack{repeat each A})
861+
862+
%99 = tuple ()
863+
return %99
864+
}

0 commit comments

Comments
 (0)