47
47
#include " swift/AST/DiagnosticsSIL.h"
48
48
#include " swift/AST/GenericEnvironment.h"
49
49
#include " swift/Basic/FrozenMultiMap.h"
50
+ #include " swift/SIL/OwnershipUtils.h"
50
51
#include " swift/SIL/SILCloner.h"
51
52
#include " swift/SIL/SILInstruction.h"
52
53
#include " swift/SIL/TypeSubstCloner.h"
@@ -313,11 +314,11 @@ class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
313
314
SILValue getProjectBoxMappedVal (SILValue operandValue);
314
315
315
316
void visitDebugValueAddrInst (DebugValueAddrInst *inst);
316
- void visitStrongReleaseInst (StrongReleaseInst *inst);
317
317
void visitDestroyValueInst (DestroyValueInst *inst);
318
318
void visitStructElementAddrInst (StructElementAddrInst *inst);
319
319
void visitLoadInst (LoadInst *inst);
320
320
void visitLoadBorrowInst (LoadBorrowInst *inst);
321
+ void visitEndBorrowInst (EndBorrowInst *inst);
321
322
void visitProjectBoxInst (ProjectBoxInst *inst);
322
323
void visitBeginAccessInst (BeginAccessInst *inst);
323
324
void visitEndAccessInst (EndAccessInst *inst);
@@ -467,9 +468,6 @@ ClosureCloner::initCloned(SILOptFunctionBuilder &functionBuilder,
467
468
orig->getEffectsKind (), orig, orig->getDebugScope ());
468
469
for (auto &attr : orig->getSemanticsAttrs ())
469
470
fn->addSemanticsAttr (attr);
470
- if (!orig->hasOwnership ()) {
471
- fn->setOwnershipEliminated ();
472
- }
473
471
return fn;
474
472
}
475
473
@@ -510,8 +508,7 @@ void ClosureCloner::populateCloned() {
510
508
// If SIL ownership is enabled, we need to perform a borrow here if we have
511
509
// a non-trivial value. We know that our value is not written to and it does
512
510
// not escape. The use of a borrow enforces this.
513
- if (cloned->hasOwnership () &&
514
- mappedValue.getOwnershipKind () != OwnershipKind::None) {
511
+ if (mappedValue.getOwnershipKind () != OwnershipKind::None) {
515
512
SILLocation loc (const_cast <ValueDecl *>((*ai)->getDecl ()));
516
513
mappedValue = getBuilder ().emitBeginBorrowOperation (loc, mappedValue);
517
514
}
@@ -565,7 +562,6 @@ SILFunction *ClosureCloner::constructClonedFunction(
565
562
SILValue ClosureCloner::getProjectBoxMappedVal (SILValue operandValue) {
566
563
if (auto *bai = dyn_cast<BeginAccessInst>(operandValue))
567
564
operandValue = bai->getSource ();
568
-
569
565
if (auto *pbi = dyn_cast<ProjectBoxInst>(operandValue)) {
570
566
auto iter = projectBoxArgumentMap.find (pbi);
571
567
if (iter != projectBoxArgumentMap.end ())
@@ -586,50 +582,25 @@ void ClosureCloner::visitDebugValueAddrInst(DebugValueAddrInst *inst) {
586
582
SILCloner<ClosureCloner>::visitDebugValueAddrInst (inst);
587
583
}
588
584
589
- // / Handle a strong_release instruction during cloning of a closure; if
590
- // / it is a strong release of a promoted box argument, then it is replaced with
591
- // / a ReleaseValue of the new object type argument, otherwise it is handled
592
- // / normally.
593
- void ClosureCloner::visitStrongReleaseInst (StrongReleaseInst *inst) {
594
- assert (
595
- !inst->getFunction ()->hasOwnership () &&
596
- " Should not see strong release in a function with qualified ownership" );
597
- SILValue operandValue = inst->getOperand ();
598
- if (auto *arg = dyn_cast<SILArgument>(operandValue)) {
599
- auto iter = boxArgumentMap.find (arg);
600
- if (iter != boxArgumentMap.end ()) {
601
- // Releases of the box arguments get replaced with ReleaseValue of the new
602
- // object type argument.
603
- auto &typeLowering =
604
- getBuilder ().getTypeLowering (iter->second ->getType ());
605
- SILBuilderWithPostProcess<ClosureCloner, 1 > b (this , inst);
606
- typeLowering.emitDestroyValue (b, inst->getLoc (), iter->second );
607
- return ;
608
- }
609
- }
610
-
611
- SILCloner<ClosureCloner>::visitStrongReleaseInst (inst);
612
- }
613
-
614
- // / Handle a destroy_value instruction during cloning of a closure; if
615
- // / it is a strong release of a promoted box argument, then it is replaced with
616
- // / a destroy_value of the new object type argument, otherwise it is handled
585
+ // / Handle a destroy_value instruction during cloning of a closure; if it is a
586
+ // / destroy_value of a promoted box argument, then it is replaced with a
587
+ // / destroy_value of the new object type argument, otherwise it is handled
617
588
// / normally.
618
589
void ClosureCloner::visitDestroyValueInst (DestroyValueInst *inst) {
619
590
SILValue operand = inst->getOperand ();
620
591
if (auto *arg = dyn_cast<SILArgument>(operand)) {
621
592
auto iter = boxArgumentMap.find (arg);
622
593
if (iter != boxArgumentMap.end ()) {
623
- // Releases of the box arguments get replaced with an end_borrow,
594
+ // destroy_value of the box arguments get replaced with an end_borrow,
624
595
// destroy_value of the new object type argument.
625
596
SILFunction &f = getBuilder ().getFunction ();
626
597
auto &typeLowering = f.getTypeLowering (iter->second ->getType ());
627
598
SILBuilderWithPostProcess<ClosureCloner, 1 > b (this , inst);
628
599
SILValue value = iter->second ;
629
600
630
- // If ownership is enabled, then we must emit a begin_borrow for any
631
- // non-trivial value .
632
- if (f. hasOwnership () && value.getOwnershipKind () != OwnershipKind::None) {
601
+ // We must have emitted a begin_borrow for any non-trivial value. Insert
602
+ // an end_borrow if so .
603
+ if (value.getOwnershipKind () != OwnershipKind::None) {
633
604
auto *bbi = cast<BeginBorrowInst>(value);
634
605
value = bbi->getOperand ();
635
606
b.emitEndBorrowOperation (inst->getLoc (), bbi);
@@ -643,6 +614,29 @@ void ClosureCloner::visitDestroyValueInst(DestroyValueInst *inst) {
643
614
SILCloner<ClosureCloner>::visitDestroyValueInst (inst);
644
615
}
645
616
617
+ // / Handle an end_borrow instruction during cloning of a closure; if it is a
618
+ // / end_borrow from a load_borrow of a promoted box argument, then it is
619
+ // / deleted, otherwise it is handled normally.
620
+ void ClosureCloner::visitEndBorrowInst (EndBorrowInst *inst) {
621
+ SILValue operand = inst->getOperand ();
622
+
623
+ if (auto *lbi = dyn_cast<LoadBorrowInst>(operand)) {
624
+ SILValue op = lbi->getOperand ();
625
+ // When we check if we can do this, we only need to look through a single
626
+ // struct_element_addr since when checking if this is safe, we only look
627
+ // through a single struct_element_addr.
628
+ if (auto *sea = dyn_cast<StructElementAddrInst>(op))
629
+ op = sea->getOperand ();
630
+
631
+ // If after optionally looking through a gep, we have our project_box, just
632
+ // eliminate the end_borrow.
633
+ if (getProjectBoxMappedVal (op))
634
+ return ;
635
+ }
636
+
637
+ SILCloner<ClosureCloner>::visitEndBorrowInst (inst);
638
+ }
639
+
646
640
// / Handle a struct_element_addr instruction during cloning of a closure.
647
641
// /
648
642
// / If its operand is the promoted address argument then ignore it, otherwise it
@@ -798,6 +792,8 @@ static SILArgument *getBoxFromIndex(SILFunction *f, unsigned index) {
798
792
}
799
793
800
794
static bool isNonMutatingLoad (SILInstruction *inst) {
795
+ if (isa<LoadBorrowInst>(inst))
796
+ return true ;
801
797
auto *li = dyn_cast<LoadInst>(inst);
802
798
if (!li)
803
799
return false ;
@@ -1573,14 +1569,17 @@ class CapturePromotionPass : public SILModuleTransform {
1573
1569
void run () override {
1574
1570
SmallVector<SILFunction *, 128 > worklist;
1575
1571
for (auto &f : *getModule ()) {
1576
- if (f.wasDeserializedCanonical ())
1572
+ if (f.wasDeserializedCanonical () || !f. hasOwnership () )
1577
1573
continue ;
1578
1574
1579
1575
processFunction (&f, worklist);
1580
1576
}
1581
1577
1582
1578
while (!worklist.empty ()) {
1583
- processFunction (worklist.pop_back_val (), worklist);
1579
+ auto *f = worklist.pop_back_val ();
1580
+ if (!f->hasOwnership ())
1581
+ continue ;
1582
+ processFunction (f, worklist);
1584
1583
}
1585
1584
}
1586
1585
@@ -1592,6 +1591,9 @@ class CapturePromotionPass : public SILModuleTransform {
1592
1591
1593
1592
void CapturePromotionPass::processFunction (
1594
1593
SILFunction *func, SmallVectorImpl<SILFunction *> &worklist) {
1594
+ assert (func->hasOwnership () &&
1595
+ " Only can perform capture promotion on functions with ownership. All "
1596
+ " functions in raw SIL should have OSSA now out of SILGen" );
1595
1597
LLVM_DEBUG (llvm::dbgs () << " ******** Performing Capture Promotion on: "
1596
1598
<< func->getName () << " ********\n " );
1597
1599
// This is a map from each partial apply to a set of indices of promotable
0 commit comments