@@ -1008,6 +1008,17 @@ void DestroyAddrHoisting::run() {
10081008 // blocks and pushing begin_access as we see them and then popping them off
10091009 // the end will result in hoisting inner begin_access' destroy_addrs first.
10101010 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 ).
10111022 changed |= hoistDestroys (bai, /* ignoreDeinitBarriers=*/ true ,
10121023 remainingDestroyAddrs, deleter, calleeAnalysis);
10131024 }
@@ -1028,6 +1039,10 @@ void DestroyAddrHoisting::run() {
10281039 //
10291040 // but communicates the rationale: in order to ignore deinit barriers, the
10301041 // 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.
10311046 bool ignoredByConvention = convention.isInoutConvention () &&
10321047 convention.isExclusiveIndirectParameter ();
10331048 auto lifetime = arg->getLifetime ();
0 commit comments