2727#include " swift/SIL/LinearLifetimeChecker.h"
2828#include " swift/SIL/MemAccessUtils.h"
2929#include " swift/SIL/OwnershipUtils.h"
30+ #include " swift/SIL/PrunedLiveness.h"
3031#include " swift/SIL/Projection.h"
3132#include " swift/SIL/SILInstruction.h"
3233#include " llvm/Support/Debug.h"
@@ -302,7 +303,7 @@ LoadBorrowImmutabilityAnalysis::LoadBorrowImmutabilityAnalysis(
302303
303304// \p address may be an address, pointer, or box type.
304305bool LoadBorrowImmutabilityAnalysis::isImmutableInScope (
305- LoadBorrowInst *lbi, ArrayRef<Operand *> endBorrowUses,
306+ LoadBorrowInst *lbi,
306307 AccessPathWithBase accessPathWithBase) {
307308 auto accessPath = accessPathWithBase.accessPath ;
308309 LinearLifetimeChecker checker (deadEndBlocks);
@@ -317,25 +318,29 @@ bool LoadBorrowImmutabilityAnalysis::isImmutableInScope(
317318 auto ownershipRoot = accessPath.getStorage ().isReference ()
318319 ? findOwnershipReferenceRoot (accessPathWithBase.base )
319320 : SILValue ();
321+
322+ BorrowedValue borrowedValue (lbi);
323+ PrunedLiveness borrowLiveness;
324+ borrowedValue.computeLiveness (borrowLiveness);
325+
320326 // Then for each write...
321327 for (auto *op : *writes) {
328+ auto *write = op->getUser ();
322329 // First see if the write is a dead end block. In such a case, just skip it.
323- if (deadEndBlocks.isDeadEnd (op-> getUser () ->getParent ())) {
330+ if (deadEndBlocks.isDeadEnd (write ->getParent ())) {
324331 continue ;
325332 }
326333 // A destroy_value will be a definite write only when the destroy is on the
327334 // ownershipRoot
328- if (isa<DestroyValueInst>(op-> getUser () )) {
335+ if (isa<DestroyValueInst>(write )) {
329336 if (op->get () != ownershipRoot)
330337 continue ;
331338 }
332- // See if the write is within the load borrow's lifetime. If it isn't, we
333- // don't have to worry about it.
334- if (!checker. validateLifetime (lbi, endBorrowUses, op)) {
335- continue ;
339+
340+ if (borrowLiveness. isWithinBoundaryOfDef (write, lbi)) {
341+ llvm::errs () << " Write: " << *write;
342+ return false ;
336343 }
337- llvm::errs () << " Write: " << *op->getUser ();
338- return false ;
339344 }
340345 // Ok, we are good.
341346 return true ;
@@ -359,13 +364,6 @@ bool LoadBorrowImmutabilityAnalysis::isImmutable(LoadBorrowInst *lbi) {
359364 if (accessPath.getStorage ().isLetAccess ()) {
360365 return true ;
361366 }
362- // At this point, we know that we /may/ have writes. Now we go through various
363- // cases to try and exhaustively identify if those writes overlap with our
364- // load_borrow.
365- SmallVector<Operand *, 8 > endBorrowUses;
366- visitTransitiveEndBorrows (lbi, [&](EndBorrowInst *endBorrow) {
367- endBorrowUses.push_back (&endBorrow->getOperandRef ());
368- });
369367
370368 switch (accessPath.getStorage ().getKind ()) {
371369 case AccessStorage::Nested: {
@@ -380,15 +378,15 @@ bool LoadBorrowImmutabilityAnalysis::isImmutable(LoadBorrowInst *lbi) {
380378 //
381379 // TODO: As a separate analysis, verify that the load_borrow scope is always
382380 // nested within the begin_access scope (to ensure no aliasing access).
383- return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase);
381+ return isImmutableInScope (lbi, accessPathWithBase);
384382 }
385383 case AccessStorage::Argument: {
386384 auto *arg =
387385 cast<SILFunctionArgument>(accessPath.getStorage ().getArgument ());
388386 if (arg->hasConvention (SILArgumentConvention::Indirect_In_Guaranteed)) {
389387 return true ;
390388 }
391- return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase);
389+ return isImmutableInScope (lbi, accessPathWithBase);
392390 }
393391 // FIXME: A yielded address could overlap with another in this function.
394392 case AccessStorage::Yield:
@@ -398,7 +396,7 @@ bool LoadBorrowImmutabilityAnalysis::isImmutable(LoadBorrowInst *lbi) {
398396 case AccessStorage::Tail:
399397 case AccessStorage::Global:
400398 case AccessStorage::Unidentified:
401- return isImmutableInScope (lbi, endBorrowUses, accessPathWithBase);
399+ return isImmutableInScope (lbi, accessPathWithBase);
402400 }
403401 llvm_unreachable (" Covered switch isn't covered?!" );
404402}
0 commit comments