Skip to content

Commit ddd8c01

Browse files
committed
[region-isolation] Do not treat mark_dependence as an ignore. Treat it as an assign from op 0 -> result and a require of op 1.
Semantically a mark_dependence returns a value that is equal to its first parameter with the extra semantics that any destroys of the 2nd operand cannot occur before any uses of the result of the instruction. From a region perspective this suggests that the instruction should be an assign from the first operand onto the result and act as a require on the result. Semantically the requirement that the 2nd operand cannot be destroyed before any uses of the result does not expose any memory or state from the first operand implying that we don't need to merge it into the result region. The restriction is purely to tell the optimizer what it can/cannot do rather.
1 parent 71a8c8e commit ddd8c01

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2399,7 +2399,6 @@ CONSTANT_TRANSLATION(EndLifetimeInst, Ignored)
23992399
CONSTANT_TRANSLATION(HopToExecutorInst, Ignored)
24002400
CONSTANT_TRANSLATION(InjectEnumAddrInst, Ignored)
24012401
CONSTANT_TRANSLATION(IsEscapingClosureInst, Ignored)
2402-
CONSTANT_TRANSLATION(MarkDependenceInst, Ignored)
24032402
CONSTANT_TRANSLATION(MetatypeInst, Ignored)
24042403
CONSTANT_TRANSLATION(EndApplyInst, Ignored)
24052404
CONSTANT_TRANSLATION(AbortApplyInst, Ignored)
@@ -2598,6 +2597,13 @@ IGNORE_IF_SENDABLE_RESULT_ASSIGN_OTHERWISE(StructExtractInst)
25982597
// Custom Handling
25992598
//
26002599

2600+
TranslationSemantics
2601+
PartitionOpTranslator::visitMarkDependenceInst(MarkDependenceInst *mdi) {
2602+
translateSILAssign(mdi, mdi->getValue());
2603+
translateSILRequire(mdi->getBase());
2604+
return TranslationSemantics::Special;
2605+
}
2606+
26012607
TranslationSemantics
26022608
PartitionOpTranslator::visitPointerToAddressInst(PointerToAddressInst *ptai) {
26032609
if (!isNonSendableType(ptai->getType())) {

test/Concurrency/transfernonsendable_instruction_matching.sil

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,79 @@ bb0(%0 : $*NonSendableKlass):
367367
%9999 = tuple ()
368368
return %9999 : $()
369369
}
370+
371+
// Make sure that we error when we transfer the result of the mark_dependence.
372+
sil [ossa] @mark_dependence_test_result_assigns_from_value : $@convention(thin) @async () -> () {
373+
bb0:
374+
%0 = alloc_ref $NonSendableKlass
375+
%1 = alloc_ref $NonSendableKlass
376+
377+
%1a = begin_borrow %1 : $NonSendableKlass
378+
%2 = mark_dependence %1a : $NonSendableKlass on %0 : $NonSendableKlass
379+
380+
%transferKlass = function_ref @transferKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
381+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferKlass(%2) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
382+
// expected-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
383+
384+
// No error here since just a requires on the first.
385+
%useKlass = function_ref @useKlass : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
386+
apply %useKlass(%0) : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
387+
388+
// But we have an error here since we store through the value.c
389+
apply %useKlass(%1) : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
390+
// expected-note @-1 {{access here could race}}
391+
392+
end_borrow %1a : $NonSendableKlass
393+
destroy_value %0 : $NonSendableKlass
394+
destroy_value %1 : $NonSendableKlass
395+
396+
%9999 = tuple ()
397+
return %9999 : $()
398+
}
399+
400+
sil [ossa] @mark_dependence_test_base_has_a_require : $@convention(thin) @async () -> () {
401+
%0 = alloc_ref $NonSendableKlass
402+
%1 = alloc_ref $NonSendableKlass
403+
404+
%1a = begin_borrow %1 : $NonSendableKlass
405+
%2 = mark_dependence %1a : $NonSendableKlass on %0 : $NonSendableKlass
406+
407+
%transferKlass = function_ref @transferKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
408+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferKlass(%2) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
409+
// expected-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
410+
411+
// No error here since just a requires on the first.
412+
%useKlass = function_ref @useKlass : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
413+
apply %useKlass(%0) : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
414+
415+
// But we have an error here since we store through the value.c
416+
apply %useKlass(%1) : $@convention(thin) (@guaranteed NonSendableKlass) -> ()
417+
// expected-note @-1 {{access here could race}}
418+
419+
end_borrow %1a : $NonSendableKlass
420+
destroy_value %0 : $NonSendableKlass
421+
destroy_value %1 : $NonSendableKlass
422+
423+
%9999 = tuple ()
424+
return %9999 : $()
425+
}
426+
427+
sil [ossa] @mark_dependence_test_base_is_a_require : $@convention(thin) @async () -> () {
428+
%0 = alloc_ref $NonSendableKlass
429+
%1 = alloc_ref $NonSendableKlass
430+
431+
%transferKlass = function_ref @transferKlass : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
432+
apply [caller_isolation=nonisolated] [callee_isolation=global_actor] %transferKlass(%0) : $@convention(thin) @async (@guaranteed NonSendableKlass) -> ()
433+
// expected-warning @-1 {{passing argument of non-sendable type 'NonSendableKlass' from nonisolated context to global actor '<null>'-isolated context at this call site could yield a race with accesses later in this function}}
434+
435+
%1a = begin_borrow %1 : $NonSendableKlass
436+
%2 = mark_dependence %1a : $NonSendableKlass on %0 : $NonSendableKlass
437+
// expected-note @-1 {{access here could race}}
438+
439+
end_borrow %1a : $NonSendableKlass
440+
destroy_value %0 : $NonSendableKlass
441+
destroy_value %1 : $NonSendableKlass
442+
443+
%9999 = tuple ()
444+
return %9999 : $()
445+
}

0 commit comments

Comments
 (0)