Skip to content

Commit 6bfbaa1

Browse files
authored
[SILOpt] Fix layout based pre-specialization with marker protocols (#71038)
Marker protocols can be ignored in the specialization, because they have no witness and the conformance will be checked before the specialization is applied. Also fixes an issue where multiple requirements on the same type caused type mismatches in the erased signature.
1 parent 3a511e0 commit 6bfbaa1

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2984,7 +2984,8 @@ bool usePrespecialized(
29842984

29852985
if (specializedReInfo.getSpecializedType() != reInfo.getSpecializedType()) {
29862986
SmallVector<Type, 4> newSubs;
2987-
auto specializedSig = SA->getUnerasedSpecializedSignature();
2987+
auto specializedSig =
2988+
SA->getUnerasedSpecializedSignature().withoutMarkerProtocols();
29882989

29892990
auto erasedParams = SA->getTypeErasedParams();
29902991
if(!ctxt.LangOpts.hasFeature(Feature::LayoutPrespecialization) || erasedParams.empty()) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,13 +3101,18 @@ SerializeAttrGenericSignatureRequest::evaluate(Evaluator &evaluator,
31013101

31023102
if (Ctx.LangOpts.hasFeature(Feature::LayoutPrespecialization)) {
31033103
llvm::SmallVector<Type, 4> typeErasedParams;
3104-
for (const auto &pair : llvm::zip(attr->getTrailingWhereClause()->getRequirements(), specializedSig.getRequirements())) {
3105-
auto &reqRepr = std::get<0>(pair);
3106-
auto &req = std::get<1>(pair);
3104+
for (const auto &reqRepr :
3105+
attr->getTrailingWhereClause()->getRequirements()) {
31073106
if (reqRepr.getKind() == RequirementReprKind::LayoutConstraint) {
31083107
if (auto *attributedTy = dyn_cast<AttributedTypeRepr>(reqRepr.getSubjectRepr())) {
31093108
if (attributedTy->getAttrs().has(TAK__noMetadata)) {
3110-
typeErasedParams.push_back(req.getFirstType());
3109+
const auto resolution = TypeResolution::forInterface(
3110+
FD->getDeclContext(), genericSig, llvm::None,
3111+
/*unboundTyOpener*/ nullptr,
3112+
/*placeholderHandler*/ nullptr,
3113+
/*packElementOpener*/ nullptr);
3114+
const auto ty = resolution.resolveType(attributedTy);
3115+
typeErasedParams.push_back(ty);
31113116
}
31123117
}
31133118
}

test/SILOptimizer/Inputs/pre_specialized_module_layouts.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ public struct SomeData {
33
public init() {}
44
}
55

6-
public class SomeClass {
6+
public final class SomeClass: Sendable {
77
public init() {}
88
}
99

@@ -17,6 +17,11 @@ public class SomeClass {
1717
public func publicPrespecialized<T>(_ t: T) {
1818
}
1919

20+
@_specialize(exported: true, where @_noMetadata T : _Class)
21+
public func publicPrespecializedWithMarkerProtocol<T: Sendable>(_ t: T) -> T {
22+
return t
23+
}
24+
2025
@_specialize(exported: true, where T == Int)
2126
@_specialize(exported: true, where @_noMetadata T : _Class)
2227
@_specialize(exported: true, availability: macOS 10.50, *; where T == SomeData)
@@ -135,6 +140,11 @@ public func useInternalThing<T>(_ t: T) {
135140

136141
@_specialize(exported: true, where @_noMetadata T : _Class, @_noMetadata V : _Class)
137142
@_specialize(exported: true, where @_noMetadata T : _BridgeObject, @_noMetadata V : _BridgeObject)
138-
public func publicPresepcializedMultipleIndirectResults<T, V>(_ t: T, _ v: V, _ x: Int64)-> (V, Int64, T) {
143+
public func publicPresepcializedMultipleIndirectResults<T, V>(_ t: T, _ v: V, _ x: Int64) -> (V, Int64, T) {
144+
return (v, x, t)
145+
}
146+
147+
@_specialize(exported: true, where @_noMetadata T : _Class, @_noMetadata V : _Class)
148+
public func publicPresepcializedMultipleIndirectResultsWithMarkerProtocol<T: Sendable, V>(_ t: T, _ v: V, _ x: Int64) -> (V, Int64, T) {
139149
return (v, x, t)
140150
}

test/SILOptimizer/pre_specialize_layouts.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,24 @@ public func usePrespecializedEntryPoints(wrapperStruct: ReferenceWrapperStruct,
179179
useInternalThing(SomeClass())
180180
}
181181

182+
// OPT: sil @$s22pre_specialize_layouts46usePrespecializedEntryPointsWithMarkerProtocol1ty0a20_specialized_module_C09SomeClassC_tF : $@convention(thin) (@guaranteed SomeClass) -> () {
183+
// OPT: bb0([[P1:%.*]] : $SomeClass):
184+
// OPT: [[R1:%.*]] = alloc_stack $SomeClass
185+
// OPT: [[F1:%.*]] = function_ref @$s30pre_specialized_module_layouts38publicPrespecializedWithMarkerProtocolyxxs8SendableRzlFyXl_Ts5 : $@convention(thin) (@guaranteed AnyObject) -> @owned AnyObject
186+
// OPT: [[R2:%.*]] = unchecked_addr_cast [[R1]] : $*SomeClass to $*AnyObject
187+
// OPT: [[A1:%.*]] = unchecked_ref_cast [[P1]] : $SomeClass to $AnyObject
188+
// OPT: [[R3:%.*]] = apply [[F1]]([[A1]]) : $@convention(thin) (@guaranteed AnyObject) -> @owned AnyObject
189+
// OPT: store [[R3]] to [[R2]] : $*AnyObject
190+
// OPT: [[A2:%.*]] = load [[R1]] : $*SomeClass
191+
// OPT: [[F2:%.*]] = function_ref @$s22pre_specialize_layouts7consumeyyxlF0a20_specialized_module_C09SomeClassC_Tg5 : $@convention(thin) (@guaranteed SomeClass) -> ()
192+
// OPT: apply [[F2]]([[A2]]) : $@convention(thin) (@guaranteed SomeClass) -> ()
193+
// OPT: strong_release [[A2]] : $SomeClass
194+
// OPT: dealloc_stack [[R1]] : $*SomeClass
195+
// OPT: } // end sil function '$s22pre_specialize_layouts46usePrespecializedEntryPointsWithMarkerProtocol1ty0a20_specialized_module_C09SomeClassC_tF'
196+
public func usePrespecializedEntryPointsWithMarkerProtocol(t: SomeClass) {
197+
consume(publicPrespecializedWithMarkerProtocol(t))
198+
}
199+
182200
// OPT: sil @$s22pre_specialize_layouts34usePrespecializedThrowsEntryPointsyyKF : $@convention(thin) () -> @error any Error {
183201
// OPT: [[F1:%.*]] = function_ref @$s30pre_specialized_module_layouts26publicPrespecializedThrowsyxxKlFSi_Ts5 : $@convention(thin) (Int) -> (Int, @error any Error)
184202
// OPT: try_apply [[F1]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error any Error)
@@ -222,6 +240,21 @@ public func usePresepcializedMultipleIndirectResults(_ c: SomeClass, _ d: SomeOt
222240
consume(publicPresepcializedMultipleIndirectResults(xs, ys, x))
223241
}
224242

243+
// OPT: sil @$s22pre_specialize_layouts58usePresepcializedMultipleIndirectResultsWithMarkerProtocolyy0a20_specialized_module_C09SomeClassC_AA0n5OtherO0Cs5Int64VtF : $@convention(thin) (@guaranteed SomeClass, @guaranteed SomeOtherClass, Int64) -> () {
244+
// OPT: {{bb.*}}([[P1:%.*]] : $SomeClass, [[P2:%.*]] : $SomeOtherClass, [[P3:%.*]] : $Int64):
245+
// OPT: [[R1:%.*]] = alloc_stack $SomeOtherClass
246+
// OPT: [[R2:%.*]] = alloc_stack $SomeClass
247+
// OPT: [[F1:%.*]] = function_ref @$s30pre_specialized_module_layouts61publicPresepcializedMultipleIndirectResultsWithMarkerProtocolyq__s5Int64Vxtx_q_ADts8SendableRzr0_lFyXl_yXlTs5 : $@convention(thin) (@guaranteed AnyObject, @guaranteed AnyObject, Int64) -> (@out AnyObject, Int64, @out AnyObject)
248+
// OPT: [[R3:%.*]] = unchecked_addr_cast [[R1]] : $*SomeOtherClass to $*AnyObject
249+
// OPT: [[R4:%.*]] = unchecked_addr_cast [[R2]] : $*SomeClass to $*AnyObject
250+
// OPT: [[A1:%.*]] = unchecked_ref_cast [[P1]] : $SomeClass to $AnyObject
251+
// OPT: [[A2:%.*]] = unchecked_ref_cast [[P2]] : $SomeOtherClass to $AnyObject
252+
// OPT: apply [[F1]]([[R3]], [[R4]], [[A1]], [[A2]], [[P3]]) : $@convention(thin) (@guaranteed AnyObject, @guaranteed AnyObject, Int64) -> (@out AnyObject, Int64, @out AnyObject)
253+
// OPT: } // end sil function '$s22pre_specialize_layouts58usePresepcializedMultipleIndirectResultsWithMarkerProtocolyy0a20_specialized_module_C09SomeClassC_AA0n5OtherO0Cs5Int64VtF'
254+
public func usePresepcializedMultipleIndirectResultsWithMarkerProtocol(_ c: SomeClass, _ d: SomeOtherClass, _ x: Int64) {
255+
consume(publicPresepcializedMultipleIndirectResultsWithMarkerProtocol(c, d, x))
256+
}
257+
225258
// OPT: sil [noinline] @$s22pre_specialize_layouts15usePartialApply1y0a20_specialized_module_C09SomeClassCAFcAF_tF : $@convention(thin) (@guaranteed SomeClass) -> @owned @callee_guaranteed (@guaranteed SomeClass) -> @owned SomeClass {
226259
// OPT: [[F1:%.*]] = function_ref @$s22pre_specialize_layouts15usePartialApply1y0a20_specialized_module_C09SomeClassCAFcAF_tF0deF5InnerL_1xxx_tlFyXl_Ts5 : $@convention(thin) (@guaranteed AnyObject, @guaranteed SomeClass) -> @owned AnyObject
227260
// OPT: [[R1:%.*]] = partial_apply [callee_guaranteed] [[F1]]({{%.*}}) : $@convention(thin) (@guaranteed AnyObject, @guaranteed SomeClass) -> @owned AnyObject

0 commit comments

Comments
 (0)