@@ -1008,6 +1008,17 @@ void DestroyAddrHoisting::run() {
1008
1008
// blocks and pushing begin_access as we see them and then popping them off
1009
1009
// the end will result in hoisting inner begin_access' destroy_addrs first.
1010
1010
for (auto *bai : llvm::reverse (bais)) {
1011
+ // [exclusive_modify_scope_hoisting] Hoisting within modify access scopes
1012
+ // doesn't respect deinit barriers because
1013
+ //
1014
+ // Mutable variable lifetimes that are formally modified in the middle of
1015
+ // a lexical scope are anchored to the beginning of the lexical scope
1016
+ // rather than to the end.
1017
+ //
1018
+ // TODO: If the performance issues associated with failing to hoist
1019
+ // destroys within an exclusive modify scope are otherwise addressed,
1020
+ // it may be less confusing not to make use of the above rule and
1021
+ // respect deinit barriers here also ( rdar://116335154 ).
1011
1022
changed |= hoistDestroys (bai, /* ignoreDeinitBarriers=*/ true ,
1012
1023
remainingDestroyAddrs, deleter, calleeAnalysis);
1013
1024
}
@@ -1028,6 +1039,10 @@ void DestroyAddrHoisting::run() {
1028
1039
//
1029
1040
// but communicates the rationale: in order to ignore deinit barriers, the
1030
1041
// address must be exclusively accessed and be a modification.
1042
+ //
1043
+ // The situation with inout parameters is analogous to that with
1044
+ // mutable exclusive access scopes [exclusive_modify_scope_hoisting], so
1045
+ // deinit barriers are not respected.
1031
1046
bool ignoredByConvention = convention.isInoutConvention () &&
1032
1047
convention.isExclusiveIndirectParameter ();
1033
1048
auto lifetime = arg->getLifetime ();
0 commit comments