Skip to content

Commit 8b11e7c

Browse files
committed
SILOptimizer: handle copy_addr [take] in TempRValueOpt
1 parent f0f95f1 commit 8b11e7c

File tree

2 files changed

+30
-19
lines changed

2 files changed

+30
-19
lines changed

lib/SILOptimizer/Transforms/CopyForwarding.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,10 +1604,7 @@ void TempRValueOptPass::run() {
16041604
++II;
16051605

16061606
// Remove identity copies which are a result of this optimization.
1607-
if (CopyInst && CopyInst->getSrc() == CopyInst->getDest() &&
1608-
// Identity copies cannot take the source. This check is just here
1609-
// to be on the safe side.
1610-
!CopyInst->isTakeOfSrc()) {
1607+
if (CopyInst && CopyInst->getSrc() == CopyInst->getDest()) {
16111608
// This is either the CopyInst which just got optimized or it is a
16121609
// follow-up from an earlier iteration, where another copy_addr copied
16131610
// the temporary back to the source location.
@@ -1725,9 +1722,8 @@ bool TempRValueOptPass::collectLoads(
17251722

17261723
case SILInstructionKind::CopyAddrInst: {
17271724
// copy_addr which read from the temporary are like loads.
1728-
// TODO: Handle copy_addr [take]. But this doesn't seem to be important.
17291725
auto *copyFromTmp = cast<CopyAddrInst>(user);
1730-
if (copyFromTmp->getDest() == address || copyFromTmp->isTakeOfSrc()) {
1726+
if (copyFromTmp->getDest() == address) {
17311727
LLVM_DEBUG(llvm::dbgs() << " Temp written or taken" << *user);
17321728
return false;
17331729
}
@@ -1774,7 +1770,7 @@ bool TempRValueOptPass::checkNoSourceModification(CopyAddrInst *copyInst,
17741770

17751771
/// Tries to perform the temporary rvalue copy elimination for \p copyInst
17761772
bool TempRValueOptPass::tryOptimizeCopyIntoTemp(CopyAddrInst *copyInst) {
1777-
if (copyInst->isTakeOfSrc() || !copyInst->isInitializationOfDest())
1773+
if (!copyInst->isInitializationOfDest())
17781774
return false;
17791775

17801776
auto *tempObj = dyn_cast<AllocStackInst>(copyInst->getDest());
@@ -1818,10 +1814,25 @@ bool TempRValueOptPass::tryOptimizeCopyIntoTemp(CopyAddrInst *copyInst) {
18181814
SILInstruction *user = use->getUser();
18191815
switch (user->getKind()) {
18201816
case SILInstructionKind::DestroyAddrInst:
1817+
if (copyInst->isTakeOfSrc()) {
1818+
use->set(copyInst->getSrc());
1819+
} else {
1820+
user->eraseFromParent();
1821+
}
1822+
break;
18211823
case SILInstructionKind::DeallocStackInst:
18221824
user->eraseFromParent();
18231825
break;
1824-
case SILInstructionKind::CopyAddrInst:
1826+
case SILInstructionKind::CopyAddrInst: {
1827+
auto *CAI = cast<CopyAddrInst>(user);
1828+
if (CAI != copyInst) {
1829+
assert(CAI->getSrc() == tempObj);
1830+
if (CAI->isTakeOfSrc() && !copyInst->isTakeOfSrc())
1831+
CAI->setIsTakeOfSrc(IsNotTake);
1832+
}
1833+
use->set(copyInst->getSrc());
1834+
break;
1835+
}
18251836
case SILInstructionKind::StructElementAddrInst:
18261837
case SILInstructionKind::TupleElementAddrInst:
18271838
case SILInstructionKind::LoadInst:

test/SILOptimizer/temp_rvalue_opt.sil

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,10 @@ bb0(%0 : $*GS<B>, %1 : $*GS<B>):
102102
return %9999 : $()
103103
}
104104

105-
// Currently not supported
106105
// CHECK-LABEL: sil @take_from_temp
107106
// CHECK: bb0(%0 : $*B, %1 : $*GS<B>):
108-
// CHECK-NEXT: alloc_stack
109-
// CHECK-NEXT: copy_addr
110107
// CHECK-NEXT: struct_element_addr
111-
// CHECK-NEXT: copy_addr
112-
// CHECK-NEXT: dealloc_stack
108+
// CHECK-NEXT: copy_addr [take]
113109
// CHECK-NEXT: tuple
114110
// CHECK-NEXT: return
115111
sil @take_from_temp : $@convention(thin) <B> (@inout B, @inout GS<B>) -> () {
@@ -416,13 +412,17 @@ bb0(%0 : $*Klass):
416412
return %9 : $()
417413
}
418414

419-
// Make sure that we do not optimize this case.
420-
//
421415
// CHECK-LABEL: sil @non_overlapping_lifetime : $@convention(thin) (@in Klass) -> () {
422-
// CHECK: destroy_addr
423-
// CHECK: destroy_addr
424-
// CHECK: destroy_addr
425-
// CHECK: } // end sil function 'non_overlapping_lifetime'
416+
// CHECK: bb0([[ARG:%.*]] : $*Klass):
417+
// CHECK-NEXT: [[TMP:%.*]] = alloc_stack $Klass
418+
// CHECK-NEXT: copy_addr [[ARG]] to [initialization] [[TMP]]
419+
// CHECK-NEXT: destroy_addr [[ARG]]
420+
// CHECK: apply %{{[0-9]*}}([[TMP]])
421+
// CHECK-NEXT: destroy_addr [[TMP]]
422+
// CHECK-NEXT: dealloc_stack [[TMP]]
423+
// CHECK-NEXT: tuple
424+
// CHECK-NEXT: return
425+
// CHECK-NEXT: } // end sil function 'non_overlapping_lifetime'
426426
sil @non_overlapping_lifetime : $@convention(thin) (@in Klass) -> () {
427427
bb0(%0 : $*Klass):
428428
%1a = alloc_stack $Klass

0 commit comments

Comments
 (0)