16
16
#include " swift/SIL/SILModule.h"
17
17
#include " swift/SIL/SILUndef.h"
18
18
#include " swift/SIL/DynamicCasts.h"
19
+ #include " swift/SIL/Consumption.h"
20
+ #include " swift/SIL/SILInstruction.h"
19
21
#include " llvm/Support/Debug.h"
20
22
21
23
using namespace swift ;
@@ -1545,12 +1547,13 @@ bool swift::memInstMustInitialize(Operand *memOper) {
1545
1547
}
1546
1548
}
1547
1549
1548
- bool swift::isSingleInitAllocStack (AllocStackInst *asi,
1549
- SmallVectorImpl<Operand *> &destroyingUses) {
1550
+ Operand *
1551
+ swift::getSingleInitAllocStackUse (AllocStackInst *asi,
1552
+ SmallVectorImpl<Operand *> *destroyingUses) {
1550
1553
// For now, we just look through projections and rely on memInstMustInitialize
1551
1554
// to classify all other uses as init or not.
1552
1555
SmallVector<Operand *, 32 > worklist (asi->getUses ());
1553
- bool foundInit = false ;
1556
+ Operand *singleInit = nullptr ;
1554
1557
1555
1558
while (!worklist.empty ()) {
1556
1559
auto *use = worklist.pop_back_val ();
@@ -1571,14 +1574,42 @@ bool swift::isSingleInitAllocStack(AllocStackInst *asi,
1571
1574
continue ;
1572
1575
}
1573
1576
// Treat load [take] as a write.
1574
- return false ;
1577
+ return nullptr ;
1575
1578
}
1576
1579
1577
1580
switch (user->getKind ()) {
1578
1581
default :
1579
1582
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
+ }
1580
1610
case SILInstructionKind::DestroyAddrInst:
1581
- destroyingUses.push_back (use);
1611
+ if (destroyingUses)
1612
+ destroyingUses->push_back (use);
1582
1613
continue ;
1583
1614
case SILInstructionKind::DeallocStackInst:
1584
1615
case SILInstructionKind::LoadBorrowInst:
@@ -1589,21 +1620,21 @@ bool swift::isSingleInitAllocStack(AllocStackInst *asi,
1589
1620
// See if we have an initializer and that such initializer is in the same
1590
1621
// block.
1591
1622
if (memInstMustInitialize (use)) {
1592
- if (user->getParent () != asi->getParent () || foundInit ) {
1593
- return false ;
1623
+ if (user->getParent () != asi->getParent () || singleInit ) {
1624
+ return nullptr ;
1594
1625
}
1595
1626
1596
- foundInit = true ;
1627
+ singleInit = use ;
1597
1628
continue ;
1598
1629
}
1599
1630
1600
1631
// Otherwise, if we have found something not in our allowlist, return false.
1601
- return false ;
1632
+ return nullptr ;
1602
1633
}
1603
1634
1604
1635
// 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 ;
1607
1638
}
1608
1639
1609
1640
// / Return true if the given address value is produced by a special address
0 commit comments