1616#include " swift/SIL/SILModule.h"
1717#include " swift/SIL/SILUndef.h"
1818#include " swift/SIL/DynamicCasts.h"
19+ #include " swift/SIL/Consumption.h"
20+ #include " swift/SIL/SILInstruction.h"
1921#include " llvm/Support/Debug.h"
2022
2123using namespace swift ;
@@ -1545,12 +1547,13 @@ bool swift::memInstMustInitialize(Operand *memOper) {
15451547 }
15461548}
15471549
1548- bool swift::isSingleInitAllocStack (AllocStackInst *asi,
1549- SmallVectorImpl<Operand *> &destroyingUses) {
1550+ Operand *
1551+ swift::getSingleInitAllocStackUse (AllocStackInst *asi,
1552+ SmallVectorImpl<Operand *> *destroyingUses) {
15501553 // For now, we just look through projections and rely on memInstMustInitialize
15511554 // to classify all other uses as init or not.
15521555 SmallVector<Operand *, 32 > worklist (asi->getUses ());
1553- bool foundInit = false ;
1556+ Operand *singleInit = nullptr ;
15541557
15551558 while (!worklist.empty ()) {
15561559 auto *use = worklist.pop_back_val ();
@@ -1571,14 +1574,42 @@ bool swift::isSingleInitAllocStack(AllocStackInst *asi,
15711574 continue ;
15721575 }
15731576 // Treat load [take] as a write.
1574- return false ;
1577+ return nullptr ;
15751578 }
15761579
15771580 switch (user->getKind ()) {
15781581 default :
15791582 break ;
1583+ case SILInstructionKind::UnconditionalCheckedCastAddrInst: {
1584+ auto *uccai = cast<UnconditionalCheckedCastAddrInst>(user);
1585+ // Only handle the case where we are doing a take of our alloc_stack as a
1586+ // source value. If we are the dest, then something else is happening!
1587+ // Break!
1588+ if (use->get () == uccai->getDest ())
1589+ break ;
1590+ // Ok, we are the Src and are performing a take. Treat it as a destroy!
1591+ if (destroyingUses)
1592+ destroyingUses->push_back (use);
1593+ continue ;
1594+ }
1595+ case SILInstructionKind::CheckedCastAddrBranchInst: {
1596+ auto *ccabi = cast<CheckedCastAddrBranchInst>(user);
1597+ // We only handle the case where we are doing a take of our alloc_stack as
1598+ // a source.
1599+ //
1600+ // TODO: Can we expand this?
1601+ if (use->get () == ccabi->getDest ())
1602+ break ;
1603+ if (ccabi->getConsumptionKind () != CastConsumptionKind::TakeAlways)
1604+ break ;
1605+ // Ok, we are the Src and are performing a take. Treat it as a destroy!
1606+ if (destroyingUses)
1607+ destroyingUses->push_back (use);
1608+ continue ;
1609+ }
15801610 case SILInstructionKind::DestroyAddrInst:
1581- destroyingUses.push_back (use);
1611+ if (destroyingUses)
1612+ destroyingUses->push_back (use);
15821613 continue ;
15831614 case SILInstructionKind::DeallocStackInst:
15841615 case SILInstructionKind::LoadBorrowInst:
@@ -1589,21 +1620,21 @@ bool swift::isSingleInitAllocStack(AllocStackInst *asi,
15891620 // See if we have an initializer and that such initializer is in the same
15901621 // block.
15911622 if (memInstMustInitialize (use)) {
1592- if (user->getParent () != asi->getParent () || foundInit ) {
1593- return false ;
1623+ if (user->getParent () != asi->getParent () || singleInit ) {
1624+ return nullptr ;
15941625 }
15951626
1596- foundInit = true ;
1627+ singleInit = use ;
15971628 continue ;
15981629 }
15991630
16001631 // Otherwise, if we have found something not in our allowlist, return false.
1601- return false ;
1632+ return nullptr ;
16021633 }
16031634
16041635 // We did not find any users that we did not understand. So we can
1605- // conservatively return true here .
1606- return true ;
1636+ // conservatively return the single initializing write that we found .
1637+ return singleInit ;
16071638}
16081639
16091640// / Return true if the given address value is produced by a special address
0 commit comments