Skip to content

Commit 9c9345e

Browse files
author
Joe Shajrawi
authored
Merge pull request swiftlang#14863 from shajrawi/in_guaranteed_to_guaranteed
Teach the generic specializer how to convert @in_guaranteed parameters to @guaranteed parameters.
2 parents 34e77c0 + 7dc017c commit 9c9345e

File tree

4 files changed

+94
-26
lines changed

4 files changed

+94
-26
lines changed

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -679,11 +679,18 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
679679
// Try to convert indirect incoming parameters to direct parameters.
680680
unsigned IdxForParam = NumFormalIndirectResults;
681681
for (SILParameterInfo PI : SubstitutedType->getParameters()) {
682-
if (substConv.getSILType(PI).isLoadable(M) &&
683-
PI.getConvention() == ParameterConvention::Indirect_In) {
684-
Conversions.set(IdxForParam);
685-
}
682+
auto IdxToInsert = IdxForParam;
686683
++IdxForParam;
684+
if (!substConv.getSILType(PI).isLoadable(M)) {
685+
continue;
686+
}
687+
if (PI.getConvention() == ParameterConvention::Indirect_In) {
688+
Conversions.set(IdxToInsert);
689+
}
690+
if ((PI.getConvention() == ParameterConvention::Indirect_In_Guaranteed) &&
691+
substConv.getSILType(PI).isTrivial(M)) {
692+
Conversions.set(IdxToInsert);
693+
}
687694
}
688695

689696
// Produce a specialized type, which is the substituted type with
@@ -763,18 +770,26 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
763770
}
764771
unsigned ParamIdx = 0;
765772
for (SILParameterInfo PI : SubstFTy->getParameters()) {
766-
if (isParamConverted(ParamIdx++)) {
767-
// Convert the indirect parameter to a direct parameter.
768-
SILType SILParamTy = SILType::getPrimitiveObjectType(PI.getType());
769-
// Indirect parameters are passed as owned, so we also need to pass the
770-
// direct parameter as owned (except it's a trivial type).
771-
auto C = (SILParamTy.isTrivial(M) ? ParameterConvention::Direct_Unowned :
772-
ParameterConvention::Direct_Owned);
773-
SpecializedParams.push_back(SILParameterInfo(PI.getType(), C));
774-
} else {
773+
if (!isParamConverted(ParamIdx++)) {
775774
// No conversion: re-use the original, substituted parameter info.
776775
SpecializedParams.push_back(PI);
776+
continue;
777+
}
778+
779+
// Convert the indirect parameter to a direct parameter.
780+
SILType SILParamTy = SILType::getPrimitiveObjectType(PI.getType());
781+
// Indirect parameters are passed as owned/guaranteed, so we also
782+
// need to pass the direct/guaranteed parameter as
783+
// owned/guaranteed (except it's a trivial type).
784+
auto C = ParameterConvention::Direct_Unowned;
785+
if (!SILParamTy.isTrivial(M)) {
786+
if (PI.isGuaranteed()) {
787+
C = ParameterConvention::Direct_Guaranteed;
788+
} else {
789+
C = ParameterConvention::Direct_Owned;
790+
}
777791
}
792+
SpecializedParams.push_back(SILParameterInfo(PI.getType(), C));
778793
}
779794
for (SILYieldInfo YI : SubstFTy->getYields()) {
780795
// For now, always just use the original, substituted parameter info.

test/SILOptimizer/specialize.sil

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,14 +637,14 @@ bb0:
637637

638638
// Test a specialization of a self-recursive generic closure.
639639

640-
// CHECK-LABEL: sil shared @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnny_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, @in_guaranteed Builtin.Int64, Builtin.Int64) -> ()
641-
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnny_Tp5
642-
// CHECK: partial_apply [[SPECIALIZED_FN]]{{.*}}({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, @in_guaranteed Builtin.Int64, Builtin.Int64) -> ()
640+
// CHECK-LABEL: sil shared @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> () {
641+
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5
642+
// CHECK: partial_apply [[SPECIALIZED_FN]]{{.*}}({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> ()
643643

644644
// CHECK-LABEL: sil @selfReferringGenericClosure : $@convention(thin) <R, S> (@in_guaranteed R, @in_guaranteed S, Builtin.Int64) -> ()
645645
// Refer to the specialized version of the function
646-
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnny_Tp5
647-
// CHECK: partial_apply [[SPECIALIZED_FN]]<R>({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, @in_guaranteed Builtin.Int64, Builtin.Int64) -> ()
646+
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$S27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5
647+
// CHECK: partial_apply [[SPECIALIZED_FN]]<R>({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> ()
648648
sil @selfReferringGenericClosure : $@convention(thin) <R, S> (@in_guaranteed R, @in_guaranteed S, Builtin.Int64) -> () {
649649
bb0(%0 : $*R, %1 : $*S, %2 : $Builtin.Int64):
650650
%4 = integer_literal $Builtin.Int64, 100

test/SILOptimizer/specialize_default_witness.sil

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ struct ConformingStruct : ResilientProtocol {
1616
}
1717

1818
// CHECK-LABEL: sil shared @$S8defaultA4main16ConformingStructV_Tg5
19-
// CHECK: bb0(%0 : $*ConformingStruct):
19+
// CHECK: bb0(%0 : $ConformingStruct):
2020
// CHECK: [[FN:%.*]] = function_ref @$S8defaultB4main16ConformingStructV_Tg5
21-
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]](%0)
22-
// CHECK-NEXT: return [[RESULT]]
21+
// CHECK: [[RESULT:%.*]] = apply [[FN]]
22+
// CHECK: return [[RESULT]]
2323

2424
sil @defaultA : $@convention(witness_method: ResilientProtocol) <Self where Self : ResilientProtocol> (@in_guaranteed Self) -> () {
2525
bb0(%0 : $*Self):
@@ -29,9 +29,9 @@ bb0(%0 : $*Self):
2929
}
3030

3131
// CHECK-LABEL: sil shared @$S8defaultB4main16ConformingStructV_Tg5
32-
// CHECK: bb0(%0 : $*ConformingStruct):
33-
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
34-
// CHECK-NEXT: return [[RESULT]]
32+
// CHECK: bb0(%0 : $ConformingStruct):
33+
// CHECK: [[RESULT:%.*]] = tuple ()
34+
// CHECK: return [[RESULT]]
3535

3636
sil @defaultB : $@convention(witness_method: ResilientProtocol) <Self where Self : ResilientProtocol> (@in_guaranteed Self) -> () {
3737
bb0(%0 : $*Self):
@@ -42,8 +42,8 @@ bb0(%0 : $*Self):
4242
// CHECK-LABEL: sil hidden @test_specialize_default_witness_method
4343
// CHECK: bb0(%0 : $*ConformingStruct):
4444
// CHECK: [[FN:%.*]] = function_ref @$S8defaultA4main16ConformingStructV_Tg5
45-
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]](%0)
46-
// CHECK-NEXT: return [[RESULT]]
45+
// CHECK: [[RESULT:%.*]] = apply [[FN]]
46+
// CHECK: return [[RESULT]]
4747

4848
sil hidden @test_specialize_default_witness_method : $@convention(thin) (@in_guaranteed ConformingStruct) -> () {
4949
bb0(%0 : $*ConformingStruct):
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-resilience -enable-sil-verify-all -generic-specializer %s | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
public protocol ResilientProtocol {
9+
func defaultA()
10+
func defaultB()
11+
}
12+
13+
public struct ConformingStruct : ResilientProtocol {
14+
public func defaultA()
15+
public func defaultB()
16+
}
17+
18+
// CHECK-LABEL: sil shared @$S8defaultA4main16ConformingStructV_Tg5
19+
// CHECK: bb0(%0 : $*ConformingStruct):
20+
// CHECK: [[FN:%.*]] = function_ref @$S8defaultB4main16ConformingStructV_Tg5
21+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]](%0)
22+
// CHECK-NEXT: return [[RESULT]]
23+
24+
sil @defaultA : $@convention(witness_method: ResilientProtocol) <Self where Self : ResilientProtocol> (@in_guaranteed Self) -> () {
25+
bb0(%0 : $*Self):
26+
%fn = function_ref @defaultB : $@convention(witness_method: ResilientProtocol) <T where T : ResilientProtocol> (@in_guaranteed T) -> ()
27+
%result = apply %fn<Self>(%0) : $@convention(witness_method: ResilientProtocol) <T where T : ResilientProtocol> (@in_guaranteed T) -> ()
28+
return %result : $()
29+
}
30+
31+
// CHECK-LABEL: sil shared @$S8defaultB4main16ConformingStructV_Tg5
32+
// CHECK: bb0(%0 : $*ConformingStruct):
33+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
34+
// CHECK-NEXT: return [[RESULT]]
35+
36+
sil @defaultB : $@convention(witness_method: ResilientProtocol) <Self where Self : ResilientProtocol> (@in_guaranteed Self) -> () {
37+
bb0(%0 : $*Self):
38+
%result = tuple ()
39+
return %result : $()
40+
}
41+
42+
// CHECK-LABEL: sil hidden @test_specialize_default_witness_method
43+
// CHECK: bb0(%0 : $*ConformingStruct):
44+
// CHECK: [[FN:%.*]] = function_ref @$S8defaultA4main16ConformingStructV_Tg5
45+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]](%0)
46+
// CHECK-NEXT: return [[RESULT]]
47+
48+
sil hidden @test_specialize_default_witness_method : $@convention(thin) (@in_guaranteed ConformingStruct) -> () {
49+
bb0(%0 : $*ConformingStruct):
50+
%fn = function_ref @defaultA : $@convention(witness_method: ResilientProtocol) <T where T : ResilientProtocol> (@in_guaranteed T) -> ()
51+
%result = apply %fn<ConformingStruct>(%0) : $@convention(witness_method: ResilientProtocol) <T where T : ResilientProtocol> (@in_guaranteed T) -> ()
52+
return %result : $()
53+
}

0 commit comments

Comments
 (0)