@@ -292,8 +292,8 @@ LoadBorrowImmutabilityAnalysis::LoadBorrowImmutabilityAnalysis(
292292// \p address may be an address, pointer, or box type.
293293bool LoadBorrowImmutabilityAnalysis::isImmutableInScope (
294294 LoadBorrowInst *lbi, ArrayRef<Operand *> endBorrowUses,
295- AccessPath accessPath ) {
296-
295+ AccessPathWithBase accessPathWithBase ) {
296+ auto accessPath = accessPathWithBase. accessPath ;
297297 LinearLifetimeChecker checker (deadEndBlocks);
298298 auto writes = cache.get (accessPath);
299299
@@ -303,12 +303,21 @@ bool LoadBorrowImmutabilityAnalysis::isImmutableInScope(
303303 accessPath.getStorage ().print (llvm::errs ());
304304 return false ;
305305 }
306+ auto ownershipRoot = accessPath.getStorage ().isReference ()
307+ ? findOwnershipReferenceRoot (accessPathWithBase.base )
308+ : SILValue ();
306309 // Then for each write...
307310 for (auto *op : *writes) {
308311 // First see if the write is a dead end block. In such a case, just skip it.
309312 if (deadEndBlocks.isDeadEnd (op->getUser ()->getParent ())) {
310313 continue ;
311314 }
315+ // A destroy_value will be a definite write only when the destroy is on the
316+ // ownershipRoot
317+ if (isa<DestroyValueInst>(op->getUser ())) {
318+ if (op->get () != ownershipRoot)
319+ continue ;
320+ }
312321 // See if the write is within the load borrow's lifetime. If it isn't, we
313322 // don't have to worry about it.
314323 if (!checker.validateLifetime (lbi, endBorrowUses, op)) {
@@ -326,7 +335,9 @@ bool LoadBorrowImmutabilityAnalysis::isImmutableInScope(
326335// ===----------------------------------------------------------------------===//
327336
328337bool LoadBorrowImmutabilityAnalysis::isImmutable (LoadBorrowInst *lbi) {
329- AccessPath accessPath = AccessPath::computeInScope (lbi->getOperand ());
338+ auto accessPathWithBase = AccessPathWithBase::compute (lbi->getOperand ());
339+ auto accessPath = accessPathWithBase.accessPath ;
340+
330341 // Bail on an invalid AccessPath. AccessPath completeness is verified
331342 // independently--it may be invalid in extraordinary situations. When
332343 // AccessPath is valid, we know all its uses are recognizable.
@@ -358,15 +369,15 @@ bool LoadBorrowImmutabilityAnalysis::isImmutable(LoadBorrowInst *lbi) {
358369 //
359370 // TODO: As a separate analysis, verify that the load_borrow scope is always
360371 // nested within the begin_access scope (to ensure no aliasing access).
361- return isImmutableInScope (lbi, endBorrowUses, accessPath );
372+ return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase );
362373 }
363374 case AccessedStorage::Argument: {
364375 auto *arg =
365376 cast<SILFunctionArgument>(accessPath.getStorage ().getArgument ());
366377 if (arg->hasConvention (SILArgumentConvention::Indirect_In_Guaranteed)) {
367378 return true ;
368379 }
369- return isImmutableInScope (lbi, endBorrowUses, accessPath );
380+ return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase );
370381 }
371382 // FIXME: A yielded address could overlap with another in this function.
372383 case AccessedStorage::Yield:
@@ -376,7 +387,7 @@ bool LoadBorrowImmutabilityAnalysis::isImmutable(LoadBorrowInst *lbi) {
376387 case AccessedStorage::Tail:
377388 case AccessedStorage::Global:
378389 case AccessedStorage::Unidentified:
379- return isImmutableInScope (lbi, endBorrowUses, accessPath );
390+ return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase );
380391 }
381392 llvm_unreachable (" Covered switch isn't covered?!" );
382393}
0 commit comments