Skip to content

Commit 12e4e8d

Browse files
committed
[region-isolation] Add support for all pack instructions.
1 parent feec25c commit 12e4e8d

File tree

4 files changed

+215
-13
lines changed

4 files changed

+215
-13
lines changed

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ inline bool isNonSendableType(SILType type, SILFunction *fn) {
4141
return true;
4242
}
4343

44+
// Treat Builtin.SILToken as Sendable. It cannot escape from the current
45+
// function. We should change isSendable to hardwire this.
46+
if (type.getASTType()->is<SILTokenType>()) {
47+
return false;
48+
}
49+
4450
// Otherwise, delegate to seeing if type conforms to the Sendable protocol.
4551
return !type.isSendable(fn);
4652
}

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,8 +2190,11 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
21902190
assert(trackableValue);
21912191
llvm::dbgs() << "State: %%" << opArg << ". ";
21922192
trackableValue->getValueState().print(llvm::dbgs());
2193-
llvm::dbgs() << "\n Value: "
2193+
llvm::dbgs() << "\n Rep Value: "
21942194
<< trackableValue->getRepresentative();
2195+
if (auto value = trackableValue->getRepresentative().maybeGetValue()) {
2196+
llvm::dbgs() << " Type: " << value->getType() << '\n';
2197+
}
21952198
}
21962199
#endif
21972200
}
@@ -2473,16 +2476,12 @@ CONSTANT_TRANSLATION(EndUnpairedAccessInst, Unhandled)
24732476
// Packs
24742477
//
24752478

2476-
CONSTANT_TRANSLATION(DeallocPackInst, Unhandled)
2477-
CONSTANT_TRANSLATION(DynamicPackIndexInst, Unhandled)
2478-
CONSTANT_TRANSLATION(OpenPackElementInst, Unhandled)
2479-
CONSTANT_TRANSLATION(PackElementGetInst, Unhandled)
2480-
CONSTANT_TRANSLATION(PackElementSetInst, Unhandled)
2481-
CONSTANT_TRANSLATION(PackLengthInst, Unhandled)
2482-
CONSTANT_TRANSLATION(PackPackIndexInst, Unhandled)
2483-
CONSTANT_TRANSLATION(ScalarPackIndexInst, Unhandled)
2484-
CONSTANT_TRANSLATION(TuplePackElementAddrInst, Unhandled)
2485-
CONSTANT_TRANSLATION(TuplePackExtractInst, Unhandled)
2479+
CONSTANT_TRANSLATION(DeallocPackInst, Ignored)
2480+
CONSTANT_TRANSLATION(DynamicPackIndexInst, Ignored)
2481+
CONSTANT_TRANSLATION(OpenPackElementInst, Ignored)
2482+
CONSTANT_TRANSLATION(PackLengthInst, Ignored)
2483+
CONSTANT_TRANSLATION(PackPackIndexInst, Ignored)
2484+
CONSTANT_TRANSLATION(ScalarPackIndexInst, Ignored)
24862485

24872486
//===---
24882487
// Apply
@@ -2605,6 +2604,46 @@ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
26052604
// Custom Handling
26062605
//
26072606

2607+
TranslationSemantics
2608+
PartitionOpTranslator::visitPackElementGetInst(PackElementGetInst *r) {
2609+
if (!isNonSendableType(r->getType()))
2610+
return TranslationSemantics::Require;
2611+
translateSILAssign(SILValue(r), r->getPack());
2612+
return TranslationSemantics::Special;
2613+
}
2614+
2615+
TranslationSemantics PartitionOpTranslator::visitTuplePackElementAddrInst(
2616+
TuplePackElementAddrInst *r) {
2617+
if (!isNonSendableType(r->getType())) {
2618+
translateSILRequire(r->getTuple());
2619+
} else {
2620+
translateSILAssign(SILValue(r), r->getTuple());
2621+
}
2622+
return TranslationSemantics::Special;
2623+
}
2624+
2625+
TranslationSemantics
2626+
PartitionOpTranslator::visitTuplePackExtractInst(TuplePackExtractInst *r) {
2627+
if (!isNonSendableType(r->getType())) {
2628+
translateSILRequire(r->getTuple());
2629+
} else {
2630+
translateSILAssign(SILValue(r), r->getTuple());
2631+
}
2632+
return TranslationSemantics::Special;
2633+
}
2634+
2635+
TranslationSemantics
2636+
PartitionOpTranslator::visitPackElementSetInst(PackElementSetInst *r) {
2637+
// If the value we are storing is sendable, treat this as a require.
2638+
if (!isNonSendableType(r->getValue()->getType())) {
2639+
return TranslationSemantics::Require;
2640+
}
2641+
2642+
// Otherwise, this is a store.
2643+
translateSILStore(r->getPackOperand(), r->getValueOperand());
2644+
return TranslationSemantics::Special;
2645+
}
2646+
26082647
TranslationSemantics
26092648
PartitionOpTranslator::visitRawPointerToRefInst(RawPointerToRefInst *r) {
26102649
assert(isLookThroughIfResultNonSendable(r) && "Out of sync");

test/Concurrency/transfernonsendable_instruction_matching.sil

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,4 +1406,138 @@ bb0:
14061406
%5 = rebind_memory %1 : $Builtin.RawPointer to %4 : $Builtin.Word // expected-note {{access here could race}}
14071407
%9999 = tuple ()
14081408
return %9999 : $()
1409+
}
1410+
1411+
// Make sure it is look through.
1412+
sil [ossa] @pack_element_get_test_nonsendable : $@convention(thin) @async <each T> () -> () {
1413+
bb0:
1414+
%c = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1415+
%0 = apply %c() : $@convention(thin) () -> @owned NonSendableKlass
1416+
1417+
%pack = alloc_pack $Pack{NonSendableKlass, repeat each T}
1418+
%index = scalar_pack_index 0 of $Pack{NonSendableKlass, repeat each T}
1419+
1420+
%addr = pack_element_get %index of %pack : $*Pack{NonSendableKlass, repeat each T} as $*NonSendableKlass
1421+
store %0 to [init] %addr : $*NonSendableKlass
1422+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1423+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%addr) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1424+
1425+
%addr2 = pack_element_get %index of %pack : $*Pack{NonSendableKlass, repeat each T} as $*NonSendableKlass // expected-note {{access here could race}}
1426+
%f2 = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1427+
apply %f2<NonSendableKlass>(%addr2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1428+
1429+
dealloc_pack %pack : $*Pack{NonSendableKlass, repeat each T}
1430+
1431+
%9999 = tuple ()
1432+
return %9999 : $()
1433+
}
1434+
1435+
// A pack_element_get that produces a Sendable address is just a require.
1436+
sil [ossa] @pack_element_get_test_sendable : $@convention(thin) @async <each T> () -> () {
1437+
bb0:
1438+
%c = function_ref @constructSendableKlass : $@convention(thin) () -> @owned SendableKlass
1439+
%0 = apply %c() : $@convention(thin) () -> @owned SendableKlass
1440+
%c2 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1441+
%0a = apply %c2() : $@convention(thin) () -> @owned NonSendableKlass
1442+
1443+
%pack = alloc_pack $Pack{NonSendableKlass, SendableKlass, repeat each T}
1444+
1445+
%index0 = scalar_pack_index 0 of $Pack{NonSendableKlass, SendableKlass, repeat each T}
1446+
%addr0 = pack_element_get %index0 of %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T} as $*NonSendableKlass
1447+
store %0a to [init] %addr0 : $*NonSendableKlass
1448+
1449+
%index1 = scalar_pack_index 1 of $Pack{NonSendableKlass, SendableKlass, repeat each T}
1450+
%addr1 = pack_element_get %index1 of %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T} as $*SendableKlass
1451+
store %0 to [init] %addr1 : $*SendableKlass
1452+
1453+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1454+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%addr0) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1455+
1456+
%addr2 = pack_element_get %index1 of %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T} as $*SendableKlass // expected-note {{access here could race}}
1457+
dealloc_pack %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T}
1458+
1459+
%9999 = tuple ()
1460+
return %9999 : $()
1461+
}
1462+
1463+
// Make sure we treat it as an assign by testing that we both create a new
1464+
// variable and treat it as a require of the older value.
1465+
sil [ossa] @pack_element_set_test_nonsendable : $@convention(thin) @async <each T> () -> () {
1466+
bb0:
1467+
%c = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1468+
%0 = apply %c() : $@convention(thin) () -> @owned NonSendableKlass
1469+
1470+
%pack = alloc_pack $Pack{NonSendableKlass, repeat each T}
1471+
%pack2 = alloc_pack $Pack{NonSendableKlass, repeat each T}
1472+
%index = scalar_pack_index 0 of $Pack{NonSendableKlass, repeat each T}
1473+
1474+
%addr = pack_element_get %index of %pack : $*Pack{NonSendableKlass, repeat each T} as $*NonSendableKlass
1475+
store %0 to [init] %addr : $*NonSendableKlass
1476+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1477+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%addr) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1478+
1479+
pack_element_set %addr : $*NonSendableKlass into %index of %pack2 : $*Pack{NonSendableKlass, repeat each T}
1480+
// expected-note @-1 {{access here could race}}
1481+
1482+
// Now transfer %addr and use it.
1483+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%addr) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1484+
%f2 = function_ref @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1485+
apply %f2<NonSendableKlass>(%addr) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-note {{access here could race}}
1486+
1487+
dealloc_pack %pack2 : $*Pack{NonSendableKlass, repeat each T}
1488+
dealloc_pack %pack : $*Pack{NonSendableKlass, repeat each T}
1489+
1490+
%9999 = tuple ()
1491+
return %9999 : $()
1492+
}
1493+
1494+
// A pack_element_set that produces a Sendable address is just a require.
1495+
sil [ossa] @pack_element_set_test_sendable : $@convention(thin) @async <each T> () -> () {
1496+
bb0:
1497+
%c1 = function_ref @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlass
1498+
%ns = apply %c1() : $@convention(thin) () -> @owned NonSendableKlass
1499+
%c2 = function_ref @constructSendableKlass : $@convention(thin) () -> @owned SendableKlass
1500+
%s = apply %c2() : $@convention(thin) () -> @owned SendableKlass
1501+
%alloc = alloc_stack $SendableKlass
1502+
store %s to [init] %alloc : $*SendableKlass
1503+
1504+
%pack = alloc_pack $Pack{NonSendableKlass, SendableKlass, repeat each T}
1505+
%index0 = scalar_pack_index 0 of $Pack{NonSendableKlass, SendableKlass, repeat each T}
1506+
%index1 = scalar_pack_index 1 of $Pack{NonSendableKlass, SendableKlass, repeat each T}
1507+
1508+
%addr = pack_element_get %index0 of %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T} as $*NonSendableKlass
1509+
store %ns to [init] %addr : $*NonSendableKlass
1510+
1511+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1512+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<NonSendableKlass>(%addr) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1513+
1514+
pack_element_set %alloc : $*SendableKlass into %index1 of %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T} // expected-note {{access here could race}}
1515+
1516+
dealloc_pack %pack : $*Pack{NonSendableKlass, SendableKlass, repeat each T}
1517+
destroy_addr %alloc : $*SendableKlass
1518+
dealloc_stack %alloc : $*SendableKlass
1519+
1520+
%9999 = tuple ()
1521+
return %9999 : $()
1522+
}
1523+
1524+
// Make sure tuple_pack_element_addr is LookThrough.
1525+
sil [ossa] @tuple_pack_element_addr_test : $@async @convention(thin) <T> (Builtin.Word) -> () {
1526+
bb0(%index : $Builtin.Word):
1527+
%tuple = alloc_stack $(NonSendableKlass, T, T, Int)
1528+
%initIndirect = function_ref @initIndirect : $@convention(thin) <T> () -> @out T
1529+
apply %initIndirect<(NonSendableKlass, T, T, Int)>(%tuple) : $@convention(thin) <T> () -> @out T
1530+
1531+
%pi = dynamic_pack_index %index of $Pack{NonSendableKlass, T, T, Int}
1532+
open_pack_element %pi of <each U_1> at <Pack{NonSendableKlass, T, T, Int}>, shape $U_1, uuid "31FF306C-BF88-11ED-A03F-ACDE48001122"
1533+
%elt = tuple_pack_element_addr %pi of %tuple : $*(NonSendableKlass, T, T, Int) as $*@pack_element("31FF306C-BF88-11ED-A03F-ACDE48001122") U_1
1534+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1535+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<@pack_element("31FF306C-BF88-11ED-A03F-ACDE48001122") U_1>(%elt) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'τ_1_0' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
1536+
1537+
%elt2 = tuple_pack_element_addr %pi of %tuple : $*(NonSendableKlass, T, T, Int) as $*@pack_element("31FF306C-BF88-11ED-A03F-ACDE48001122") U_1 // expected-note {{access here could race}}
1538+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<@pack_element("31FF306C-BF88-11ED-A03F-ACDE48001122") U_1>(%elt2) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
1539+
1540+
dealloc_stack %tuple : $*(NonSendableKlass, T, T, Int)
1541+
%9999 = tuple ()
1542+
return %9999 : $()
14091543
}

test/Concurrency/transfernonsendable_instruction_matching_opaquevalues.sil

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -transfer-non-sendable -enable-sil-opaque-values -enable-experimental-feature RegionBasedIsolation -strict-concurrency=complete %s -verify
1+
// RUN: %target-sil-opt -transfer-non-sendable -enable-sil-opaque-values -enable-experimental-feature RegionBasedIsolation -strict-concurrency=complete %s -verify -o /dev/null
22

33
// REQUIRES: concurrency
44
// REQUIRES: asserts
@@ -43,6 +43,7 @@ sil @constructNonSendableKlass : $@convention(thin) () -> @owned NonSendableKlas
4343

4444
sil @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
4545
sil @useIndirect : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
46+
sil @initIndirect : $@convention(thin) <τ_0_0> () -> @out τ_0_0
4647

4748
sil @constructMoveOnlyStruct : $@convention(thin) () -> @owned NonSendableMoveOnlyStruct
4849

@@ -68,4 +69,26 @@ bb0(%owned_value : @owned $T):
6869

6970
%9999 = tuple ()
7071
return %9999 : $()
71-
}
72+
}
73+
74+
// Make sure that tuple_pack_extract is look through.
75+
sil [ossa] @tuple_pack_extract_test : $@async @convention(thin) <each T> () -> () {
76+
bb0:
77+
%initIndirect = function_ref @initIndirect : $@convention(thin) <τ_0_0> () -> @out τ_0_0
78+
%0 = apply %initIndirect<(repeat each T)>() : $@convention(thin) <τ_0_0> () -> @out τ_0_0
79+
%1 = begin_borrow %0 : $(repeat each T)
80+
%zero = integer_literal $Builtin.Word, 0
81+
%index = dynamic_pack_index %zero of $Pack{repeat each T}
82+
open_pack_element %index of <each U_1> at <Pack{repeat each T}>, shape $U_1, uuid "00000000-0000-0000-0000-000000000000"
83+
%elt = tuple_pack_extract %index of %1 : $(repeat each T) as $@pack_element("00000000-0000-0000-0000-000000000000") U_1
84+
%f = function_ref @transferIndirect : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
85+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<@pack_element("00000000-0000-0000-0000-000000000000") U_1>(%elt) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> () // expected-warning {{transferring value of non-Sendable type 'τ_1_0' from nonisolated context to global actor '<null>'-isolated context; later accesses could race}}
86+
87+
%elt2 = tuple_pack_extract %index of %1 : $(repeat each T) as $@pack_element("00000000-0000-0000-0000-000000000000") U_1 // expected-note {{access here could race}}
88+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %f<@pack_element("00000000-0000-0000-0000-000000000000") U_1>(%elt) : $@convention(thin) @async <τ_0_0> (@in_guaranteed τ_0_0) -> ()
89+
90+
end_borrow %1 : $(repeat each T)
91+
destroy_value %0 : $(repeat each T)
92+
%9999 = tuple ()
93+
return %9999 : $()
94+
}

0 commit comments

Comments
 (0)