Skip to content

Commit 30accb0

Browse files
committed
[temp-immut-rv-forward] Handle open_existential_addr immutable_access.
Now we handle this case: %stack = alloc_stack $Protocol copy_addr %var to [initialization] %stack open_existential_addr immutable_access %stack ... destroy_addr %stack dealloc_stack %stack We only do this if we have immutable_access. To be conservative I still only let the normal whitelist of other instructions through. I am adding this optimization since I am going to be eliminating a SILGen peephole so I can enable SIL ownership verification everywhere.
1 parent 09847e6 commit 30accb0

File tree

2 files changed

+37
-34
lines changed

2 files changed

+37
-34
lines changed

Diff for: lib/SILOptimizer/Transforms/CopyForwarding.cpp

+16-1
Original file line numberDiff line numberDiff line change
@@ -1689,12 +1689,26 @@ bool TempRValueOptPass::collectLoads(
16891689
loadInsts.insert(user);
16901690
return true;
16911691
}
1692+
case SILInstructionKind::OpenExistentialAddrInst: {
1693+
// We only support open existential addr if the access is immutable.
1694+
auto *oeai = cast<OpenExistentialAddrInst>(user);
1695+
if (oeai->getAccessKind() != OpenedExistentialAccess::Immutable) {
1696+
LLVM_DEBUG(llvm::dbgs() << " Temp consuming use may write/destroy "
1697+
"its source" << *user);
1698+
return false;
1699+
}
1700+
return true;
1701+
}
16921702
case SILInstructionKind::StructElementAddrInst:
16931703
case SILInstructionKind::TupleElementAddrInst: {
16941704
// Transitively look through projections on stack addresses.
16951705
auto proj = cast<SingleValueInstruction>(user);
16961706
for (auto *projUseOper : proj->getUses()) {
1697-
if (!collectLoads(projUseOper, projUseOper->getUser(), proj, srcObject,
1707+
auto *user = projUseOper->getUser();
1708+
if (user->isTypeDependentOperand(*projUseOper))
1709+
continue;
1710+
1711+
if (!collectLoads(projUseOper, user, proj, srcObject,
16981712
loadInsts))
16991713
return false;
17001714
}
@@ -1813,6 +1827,7 @@ bool TempRValueOptPass::tryOptimizeCopyIntoTemp(CopyAddrInst *copyInst) {
18131827
case SILInstructionKind::LoadInst:
18141828
case SILInstructionKind::LoadBorrowInst:
18151829
case SILInstructionKind::ApplyInst:
1830+
case SILInstructionKind::OpenExistentialAddrInst:
18161831
use->set(copyInst->getSrc());
18171832
break;
18181833

Diff for: test/SILOptimizer/sil_combine_protocol_conf.swift

+21-33
Original file line numberDiff line numberDiff line change
@@ -235,36 +235,26 @@ internal class OtherClass {
235235
}
236236

237237
// CHECK-LABEL: sil hidden [noinline] @$s25sil_combine_protocol_conf10OtherClassC12doWorkStructSiyF : $@convention(method) (@guaranteed OtherClass) -> Int {
238-
// CHECK: bb0
238+
// CHECK: bb0([[ARG:%.*]] :
239239
// CHECK: debug_value
240-
// CHECK: [[A1:%.*]] = alloc_stack $PropProtocol
241-
// CHECK: [[R1:%.*]] = ref_element_addr %0 : $OtherClass, #OtherClass.arg1
242-
// CHECK: copy_addr [[R1]] to [initialization] [[A1]] : $*PropProtocol
243-
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[A1]] : $*PropProtocol to $*@opened("{{.*}}") PropProtocol
240+
// CHECK: [[R1:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg1
241+
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[R1]] : $*PropProtocol to $*@opened("{{.*}}") PropProtocol
244242
// CHECK: [[U1:%.*]] = unchecked_addr_cast [[O1]] : $*@opened("{{.*}}") PropProtocol to $*PropClass
245243
// CHECK: [[S1:%.*]] = struct_element_addr [[U1]] : $*PropClass, #PropClass.val
246244
// CHECK: [[S11:%.*]] = struct_element_addr [[S1]] : $*Int, #Int._value
247245
// CHECK: load [[S11]]
248-
// CHECK: destroy_addr [[A1]] : $*PropProtocol
249-
// CHECK: [[A2:%.*]] = alloc_stack $GenericPropProtocol
250-
// CHECK: [[R2:%.*]] = ref_element_addr %0 : $OtherClass, #OtherClass.arg2
251-
// CHECK: copy_addr [[R2]] to [initialization] [[A2]] : $*GenericPropProtocol
252-
// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[A2]] : $*GenericPropProtocol to $*@opened("{{.*}}") GenericPropProtocol
246+
// CHECK: [[R2:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg2
247+
// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[R2]] : $*GenericPropProtocol to $*@opened("{{.*}}") GenericPropProtocol
253248
// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}") GenericPropProtocol, #GenericPropProtocol.val!getter.1 : <Self where Self : GenericPropProtocol> (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}") GenericPropProtocol : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int
254249
// CHECK: apply [[W2]]<@opened("{{.*}}") GenericPropProtocol>([[O2]]) : $@convention(witness_method: GenericPropProtocol) <τ_0_0 where τ_0_0 : GenericPropProtocol> (@in_guaranteed τ_0_0) -> Int
255-
// CHECK: destroy_addr [[A2]] : $*GenericPropProtocol
256250
// CHECK: struct_extract
257251
// CHECK: integer_literal
258252
// CHECK: builtin
259253
// CHECK: tuple_extract
260254
// CHECK: tuple_extract
261255
// CHECK: cond_fail
262-
// CHECK: dealloc_stack [[A2]] : $*GenericPropProtocol
263-
// CHECK: dealloc_stack [[A1]] : $*PropProtocol
264-
// CHECK: [[A4:%.*]] = alloc_stack $NestedPropProtocol
265-
// CHECK: [[R4:%.*]] = ref_element_addr %0 : $OtherClass, #OtherClass.arg3
266-
// CHECK: copy_addr [[R4]] to [initialization] [[A4]] : $*NestedPropProtocol
267-
// CHECK: [[O4:%.*]] = open_existential_addr immutable_access [[A4]] : $*NestedPropProtocol to $*@opened("{{.*}}") NestedPropProtocol
256+
// CHECK: [[R4:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg3
257+
// CHECK: [[O4:%.*]] = open_existential_addr immutable_access [[R4]] : $*NestedPropProtocol to $*@opened("{{.*}}") NestedPropProtocol
268258
// CHECK: [[U4:%.*]] = unchecked_addr_cast [[O4]] : $*@opened("{{.*}}") NestedPropProtocol to $*Outer.Inner
269259
// CHECK: [[S4:%.*]] = struct_element_addr [[U4]] : $*Outer.Inner, #Outer.Inner.val
270260
// CHECK: [[S41:%.*]] = struct_element_addr [[S4]] : $*Int, #Int._value
@@ -273,11 +263,8 @@ internal class OtherClass {
273263
// CHECK: tuple_extract
274264
// CHECK: tuple_extract
275265
// CHECK: cond_fail
276-
// CHECK: dealloc_stack [[A4]] : $*NestedPropProtocol
277-
// CHECK: [[A5:%.*]] = alloc_stack $GenericNestedPropProtocol
278-
// CHECK: [[R5:%.*]] = ref_element_addr %0 : $OtherClass, #OtherClass.arg4
279-
// CHECK: copy_addr [[R5]] to [initialization] [[A5]] : $*GenericNestedPropProtocol
280-
// CHECK: [[O5:%.*]] = open_existential_addr immutable_access [[A5]] : $*GenericNestedPropProtocol to $*@opened("{{.*}}") GenericNestedPropProtocol
266+
// CHECK: [[R5:%.*]] = ref_element_addr [[ARG]] : $OtherClass, #OtherClass.arg4
267+
// CHECK: [[O5:%.*]] = open_existential_addr immutable_access [[R5]] : $*GenericNestedPropProtocol to $*@opened("{{.*}}") GenericNestedPropProtocol
281268
// CHECK: [[W5:%.*]] = witness_method $@opened("{{.*}}") GenericNestedPropProtocol, #GenericNestedPropProtocol.val!getter.1 : <Self where Self : GenericNestedPropProtocol> (Self) -> () -> Int, [[O5:%.*]] : $*@opened("{{.*}}") GenericNestedPropProtocol : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int
282269
// CHECK: apply [[W5]]<@opened("{{.*}}") GenericNestedPropProtocol>([[O5]]) : $@convention(witness_method: GenericNestedPropProtocol) <τ_0_0 where τ_0_0 : GenericNestedPropProtocol> (@in_guaranteed τ_0_0) -> Int
283270
// CHECK: struct_extract
@@ -286,8 +273,6 @@ internal class OtherClass {
286273
// CHECK: tuple_extract
287274
// CHECK: cond_fail
288275
// CHECK: struct
289-
// CHECK: destroy_addr [[A5]] : $*GenericNestedPropProtocol
290-
// CHECK: dealloc_stack [[A5]] : $*GenericNestedPropProtocol
291276
// CHECK: return
292277
// CHECK: } // end sil function '$s25sil_combine_protocol_conf10OtherClassC12doWorkStructSiyF'
293278
@inline(never) func doWorkStruct () -> Int{
@@ -301,6 +286,7 @@ internal class OtherClass {
301286
// case 1: enum -- optimize
302287
internal protocol AProtocol {
303288
var val: Int { get }
289+
mutating func getVal() -> Int
304290
}
305291
internal enum AnEnum : AProtocol {
306292
case avalue
@@ -309,12 +295,14 @@ internal enum AnEnum : AProtocol {
309295
case .avalue:
310296
return 10
311297
}
312-
}
298+
}
299+
mutating func getVal() -> Int { return self.val }
313300
}
314301

315302
// case 2: generic enum -- do not optimize
316303
internal protocol AGenericProtocol {
317304
var val: Int { get }
305+
mutating func getVal() -> Int
318306
}
319307
internal enum AGenericEnum<T> : AGenericProtocol {
320308
case avalue
@@ -323,7 +311,11 @@ internal enum AGenericEnum<T> : AGenericProtocol {
323311
case .avalue:
324312
return 10
325313
}
326-
}
314+
}
315+
316+
mutating func getVal() -> Int {
317+
return self.val
318+
}
327319
}
328320

329321
internal class OtherKlass {
@@ -336,13 +328,11 @@ internal class OtherKlass {
336328
}
337329

338330
// CHECK-LABEL: sil hidden [noinline] @$s25sil_combine_protocol_conf10OtherKlassC10doWorkEnumSiyF : $@convention(method) (@guaranteed OtherKlass) -> Int {
339-
// CHECK: bb0
331+
// CHECK: bb0([[ARG:%.*]] :
340332
// CHECK: debug_value
341333
// CHECK: integer_literal
342-
// CHECK: [[A1:%.*]] = alloc_stack $AGenericProtocol
343-
// CHECK: [[R1:%.*]] = ref_element_addr %0 : $OtherKlass, #OtherKlass.arg2
344-
// CHECK: copy_addr [[R1]] to [initialization] [[A1]] : $*AGenericProtocol
345-
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[A1]] : $*AGenericProtocol to $*@opened("{{.*}}") AGenericProtocol
334+
// CHECK: [[R1:%.*]] = ref_element_addr [[ARG]] : $OtherKlass, #OtherKlass.arg2
335+
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[R1]] : $*AGenericProtocol to $*@opened("{{.*}}") AGenericProtocol
346336
// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}") AGenericProtocol, #AGenericProtocol.val!getter.1 : <Self where Self : AGenericProtocol> (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}") AGenericProtocol : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int
347337
// CHECK: apply [[W1]]<@opened("{{.*}}") AGenericProtocol>([[O1]]) : $@convention(witness_method: AGenericProtocol) <τ_0_0 where τ_0_0 : AGenericProtocol> (@in_guaranteed τ_0_0) -> Int
348338
// CHECK: struct_extract
@@ -352,8 +342,6 @@ internal class OtherKlass {
352342
// CHECK: tuple_extract
353343
// CHECK: cond_fail
354344
// CHECK: struct
355-
// CHECK: destroy_addr [[A1]] : $*AGenericProtocol
356-
// CHECK: dealloc_stack [[A1]] : $*AGenericProtocol
357345
// CHECK: return
358346
// CHECK: } // end sil function '$s25sil_combine_protocol_conf10OtherKlassC10doWorkEnumSiyF'
359347
@inline(never) func doWorkEnum() -> Int {

0 commit comments

Comments
 (0)