Skip to content

Commit 14089c1

Browse files
committed
Fixes for OpaqueArchetypeSpecializer
Look at all instructions whether we have to cast. Return/YieldInst must not change the returned type.
1 parent 612a87f commit 14089c1

File tree

3 files changed

+178
-17
lines changed

3 files changed

+178
-17
lines changed

lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp

Lines changed: 96 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "swift/SIL/TypeSubstCloner.h"
55
#include "swift/SIL/SILInstruction.h"
66
#include "swift/SILOptimizer/PassManager/Transforms.h"
7+
#include "swift/SILOptimizer/Utils/CFG.h"
78

89

910
using namespace swift;
@@ -21,6 +22,8 @@ class OpaqueSpecializerCloner
2122

2223
public:
2324
friend class SILCloner<OpaqueSpecializerCloner>;
25+
friend class SILInstructionVisitor<OpaqueSpecializerCloner>;
26+
2427
OpaqueSpecializerCloner(SubstitutionMap opaqueArchetypeSubs, SILFunction &fun)
2528
: SuperTy(fun, fun, opaqueArchetypeSubs) {
2629
entryBlock = fun.getEntryBlock();
@@ -38,8 +41,50 @@ class OpaqueSpecializerCloner
3841
insertOpaqueToConcreteAddressCasts(orig, cloned);
3942
}
4043

41-
void visitTerminator(SILBasicBlock *BB) { visit(BB->getTerminator()); }
44+
void visitTerminator(SILBasicBlock *BB) {
45+
visit(BB->getTerminator());
46+
}
47+
48+
void visitReturnInst(ReturnInst *Inst) {
49+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
50+
auto origResult = Inst->getOperand();
51+
auto clonedResult = getOpValue(Inst->getOperand());
52+
if (clonedResult->getType().getASTType() != origResult->getType().getASTType())
53+
clonedResult = getBuilder().createUncheckedRefCast(
54+
RegularLocation::getAutoGeneratedLocation(), clonedResult,
55+
origResult->getType());
56+
recordClonedInstruction(
57+
Inst,
58+
getBuilder().createReturn(getOpLocation(Inst->getLoc()), clonedResult));
59+
}
60+
61+
void visitYieldInst(YieldInst *Inst) {
62+
auto OrigValues = Inst->getYieldedValues();
63+
auto Values = getOpValueArray<8>(Inst->getYieldedValues());
64+
auto ResumeBB = getOpBasicBlock(Inst->getResumeBB());
65+
auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB());
66+
for (auto idx : indices(Values)) {
67+
if (OrigValues[idx]->getType().getASTType() !=
68+
Values[idx]->getType().getASTType()) {
69+
if (!Values[idx]->getType().isAddress()) {
70+
Values[idx] = getBuilder().createUncheckedRefCast(
71+
RegularLocation::getAutoGeneratedLocation(), Values[idx],
72+
OrigValues[idx]->getType());
73+
} else {
74+
Values[idx] = getBuilder().createUncheckedAddrCast(
75+
RegularLocation::getAutoGeneratedLocation(), Values[idx],
76+
OrigValues[idx]->getType());
77+
}
78+
}
79+
}
80+
81+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
82+
recordClonedInstruction(
83+
Inst, getBuilder().createYield(getOpLocation(Inst->getLoc()), Values,
84+
ResumeBB, UnwindBB));
85+
}
4286

87+
protected:
4388
SILType remapType(SILType Ty) {
4489
SILType &Sty = TypeCache[Ty];
4590
if (!Sty) {
@@ -97,26 +142,52 @@ void OpaqueSpecializerCloner::clone() {
97142
void OpaqueSpecializerCloner::insertOpaqueToConcreteAddressCasts(
98143
SILInstruction *orig, SILInstruction *cloned) {
99144

145+
if (isa<ReturnInst>(cloned) || isa<YieldInst>(cloned))
146+
return;
147+
100148
// Replace apply operands.
101-
auto apply = ApplySite::isa(cloned);
102-
if (!apply)
149+
if (auto apply = ApplySite::isa(cloned)) {
150+
SavedInsertionPointRAII restore(getBuilder());
151+
getBuilder().setInsertionPoint(apply.getInstruction());
152+
auto substConv = apply.getSubstCalleeConv();
153+
unsigned idx = 0;
154+
for (auto &opd : apply.getArgumentOperands()) {
155+
auto argConv = apply.getArgumentConvention(opd);
156+
auto argIdx = apply.getCalleeArgIndex(opd);
157+
auto argType = substConv.getSILArgumentType(argIdx);
158+
if (argType.getASTType() != opd.get()->getType().getASTType()) {
159+
if (argConv.isIndirectConvention()) {
160+
auto cast = getBuilder().createUncheckedAddrCast(apply.getLoc(),
161+
opd.get(), argType);
162+
opd.set(cast);
163+
} else {
164+
auto cast = getBuilder().createUncheckedRefCast(apply.getLoc(),
165+
opd.get(), argType);
166+
opd.set(cast);
167+
}
168+
}
169+
++idx;
170+
}
103171
return;
172+
}
104173

105-
SavedInsertionPointRAII restore(getBuilder());
106-
getBuilder().setInsertionPoint(apply.getInstruction());
107-
auto substConv = apply.getSubstCalleeConv();
108174
unsigned idx = 0;
109-
for (auto &opd : apply.getArgumentOperands()) {
110-
auto argConv = apply.getArgumentConvention(opd);
111-
auto argIdx = apply.getCalleeArgIndex(opd);
112-
auto argType = substConv.getSILArgumentType(argIdx);
113-
if (argConv.isIndirectConvention() &&
114-
argType.getASTType() != opd.get()->getType().getASTType()) {
115-
auto cast = getBuilder().createUncheckedAddrCast(apply.getLoc(),
116-
opd.get(), argType);
117-
opd.set(cast);
175+
for (auto &opd : cloned->getAllOperands()) {
176+
auto origType = orig->getOperand(idx)->getType();
177+
auto clonedType = opd.get()->getType();
178+
if (clonedType.getASTType() != origType.getASTType()) {
179+
SavedInsertionPointRAII restore(getBuilder());
180+
getBuilder().setInsertionPoint(cloned);
181+
if (origType.isAddress()) {
182+
auto cast = getBuilder().createUncheckedAddrCast(cloned->getLoc(),
183+
opd.get(), clonedType);
184+
opd.set(cast);
185+
} else {
186+
auto cast = getBuilder().createUncheckedRefCast(cloned->getLoc(),
187+
opd.get(), clonedType);
188+
opd.set(cast);
189+
}
118190
}
119-
++idx;
120191
}
121192
}
122193

@@ -128,6 +199,14 @@ class OpaqueArchetypeSpecializer : public SILFunctionTransform {
128199
bool foundOpaqueArchetype = false;
129200
for (auto &BB : *getFunction()) {
130201
for (auto &inst : BB) {
202+
for (auto &opd : inst.getAllOperands()) {
203+
if (!opd.get()->getType().getASTType()->hasOpaqueArchetype())
204+
continue;
205+
foundOpaqueArchetype = true;
206+
break;
207+
}
208+
if (foundOpaqueArchetype)
209+
break;
131210
auto *allocStack = dyn_cast<AllocStackInst>(&inst);
132211
if (!allocStack ||
133212
!allocStack->getElementType().getASTType()->hasOpaqueArchetype())
@@ -141,6 +220,7 @@ class OpaqueArchetypeSpecializer : public SILFunctionTransform {
141220
SubstitutionMap subsMap = getFunction()->getForwardingSubstitutionMap();
142221
OpaqueSpecializerCloner s(subsMap, *getFunction());
143222
s.clone();
223+
removeUnreachableBlocks(*getFunction());
144224
}
145225

146226
if (foundOpaqueArchetype)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
public protocol ExternalP {
2+
func myValue2() -> Int64
3+
}
4+
5+
extension Int64 : ExternalP {
6+
public func myValue2() -> Int64 {
7+
return self + 2
8+
}
9+
}
10+
11+
public func external() -> some ExternalP {
12+
return Int64(5)
13+
}

test/SILOptimizer/specialize_opaque_type_archetypes.swift

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
// RUN: %target-swift-frontend -module-name A -enforce-exclusivity=checked -Osize -emit-sil %s | %FileCheck %s
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_2.swift -module-name External -emit-module -emit-module-path %t/External.swiftmodule
3+
// RUN: %target-swift-frontend %S/Inputs/specialize_opaque_type_archetypes_3.swift -enable-library-evolution -module-name External2 -emit-module -emit-module-path %t/External2.swiftmodule
4+
// RUN: %target-swift-frontend -I %t -module-name A -enforce-exclusivity=checked -Osize -emit-sil %s | %FileCheck %s
5+
import External
6+
import External2
7+
28
public protocol P {
39
func myValue() -> Int64
410
}
@@ -72,3 +78,65 @@ public func testAddressOnlyFoobar() {
7278
useP(x.myValue())
7379
useP(y.myValue())
7480
}
81+
82+
public protocol CP : class {
83+
func myValue() -> Int64
84+
}
85+
86+
class C : CP {
87+
func myValue() -> Int64 {
88+
return 0
89+
}
90+
}
91+
92+
public func returnC() -> some CP {
93+
return C()
94+
}
95+
96+
// CHECK-LABEL: sil @$s1A4useCyyF
97+
// CHECK: [[INT:%.*]] = struct $Int64 (
98+
// CHECK: // function_ref specialized useP<A>(_:)
99+
// CHECK: [[FUN:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
100+
// CHECK: = apply [[FUN]]([[INT]])
101+
public func useC() {
102+
let c = returnC()
103+
useP(c.myValue())
104+
}
105+
106+
// CHECK-LABEL: sil @$s1A11useExternalyyF
107+
// CHECK: // function_ref Int64.myValue2()
108+
// CHECK: [[FUN:%.*]] = function_ref @$ss5Int64V8ExternalE8myValue2AByF
109+
// CHECK: apply [[FUN]]
110+
public func useExternal() {
111+
let e = external()
112+
useP(e.myValue2())
113+
}
114+
115+
// This should change once opaque types support resilience.
116+
117+
// CHECK-LABEL: sil @$s1A20useExternalResilientyyF
118+
// CHECK: // function_ref Int64.myValue3()
119+
// CHECK: [[FUN:%.*]] = function_ref @$ss5Int64V9External2E8myValue3AByF
120+
// CHECK: apply [[FUN]]
121+
public func useExternalResilient() {
122+
let e = externalResilient()
123+
useP(e.myValue3())
124+
}
125+
126+
struct Container {
127+
var x : some P {
128+
get {
129+
return Int64(1)
130+
}
131+
}
132+
}
133+
134+
// CHECK-LABEL: sil @$s1A11usePropertyyyF
135+
// CHECK: [[VAL:%.*]] = struct $Int64
136+
// CHECK: // function_ref specialized useP<A>(_:)
137+
// CHECK: [[FUN:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
138+
// CHECK: apply [[FUN]]([[VAL]])
139+
public func useProperty() {
140+
let p = Container().x
141+
useP(p.myValue())
142+
}

0 commit comments

Comments
 (0)