@@ -631,25 +631,45 @@ static void replaceAllUsesAndFixLifetimes(SILValue foldedVal,
631
631
" cannot constant fold a terminator instruction" );
632
632
assert (foldedInst && " constant value does not have a defining instruction" );
633
633
634
- // First, replace all uses of originalVal by foldedVal, and then adjust their
635
- // lifetimes if necessary.
636
- originalVal->replaceAllUsesWith (foldedVal);
637
-
638
634
if (originalVal->getType ().isTrivial (*fun)) {
639
635
assert (foldedVal->getType ().isTrivial (*fun));
636
+ // Just replace originalVal by foldedVal.
637
+ originalVal->replaceAllUsesWith (foldedVal);
640
638
return ;
641
639
}
642
640
assert (!foldedVal->getType ().isTrivial (*fun));
643
641
644
642
if (!fun->hasOwnership ()) {
645
643
// In non-ownership SIL, handle only folding of struct_extract instruction,
646
644
// which is the only important instruction that should be folded by this
647
- // pass. Note that folding an arbitrary instruction in non-ownership SIL
648
- // makes updating reference counts of the original value much harder and
649
- // error prone .
645
+ // pass. The logic used here is not correct in general and overfits a
646
+ // specific form of SIL. This code should be removed once OSSA is enabled
647
+ // for this pass .
650
648
// TODO: this code can be safely removed once ownership SIL becomes the
651
649
// default SIL this pass works on.
652
- assert (isa<StructExtractInst>(originalInst));
650
+ assert (isa<StructExtractInst>(originalInst) &&
651
+ !originalVal->getType ().isAddress ());
652
+
653
+ // First, replace all uses of originalVal by foldedVal, and then adjust
654
+ // their lifetimes if necessary.
655
+ originalVal->replaceAllUsesWith (foldedVal);
656
+
657
+ unsigned retainCount = 0 ;
658
+ unsigned consumeCount = 0 ;
659
+ for (Operand *use : foldedVal->getUses ()) {
660
+ SILInstruction *user = use->getUser ();
661
+ if (isa<ReleaseValueInst>(user) || isa<StoreInst>(user))
662
+ consumeCount++;
663
+ if (isa<RetainValueInst>(user))
664
+ retainCount++;
665
+ // Note that there could other consuming operations but they are not
666
+ // handled here as this code should be phased out soon.
667
+ }
668
+ if (consumeCount > retainCount) {
669
+ // The original value was at +1 and therefore consumed at the end. Since
670
+ // the foldedVal is also at +1 there is nothing to be done.
671
+ return ;
672
+ }
653
673
cleanupAtEndOfLifetime (foldedInst, [&](SILInstruction *lifetimeEndInst) {
654
674
SILBuilderWithScope builder (lifetimeEndInst);
655
675
builder.emitReleaseValue (lifetimeEndInst->getLoc (), foldedVal);
@@ -661,6 +681,7 @@ static void replaceAllUsesAndFixLifetimes(SILValue foldedVal,
661
681
" constant value must have owned ownership kind" );
662
682
663
683
if (originalVal.getOwnershipKind () == ValueOwnershipKind::Owned) {
684
+ originalVal->replaceAllUsesWith (foldedVal);
664
685
// Destroy originalVal, which is now unused, immediately after its
665
686
// definition. Note that originalVal's destorys are now transferred to
666
687
// foldedVal.
@@ -671,10 +692,20 @@ static void replaceAllUsesAndFixLifetimes(SILValue foldedVal,
671
692
return ;
672
693
}
673
694
674
- // Here, originalVal is not owned. Hence, destroy foldedVal at the end of its
695
+ // Here, originalVal is not owned. Hence, borrow form foldedVal and use the
696
+ // borrow in place of originalVal. Also, destroy foldedVal at the end of its
675
697
// lifetime.
676
- cleanupAtEndOfLifetime (foldedInst, [&](SILInstruction *lifetimeEndInst) {
698
+ assert (originalVal.getOwnershipKind () == ValueOwnershipKind::Guaranteed);
699
+
700
+ SILBuilderWithScope builder (&*std::next (foldedInst->getIterator ()));
701
+ BeginBorrowInst *borrow =
702
+ builder.createBeginBorrow (foldedInst->getLoc (), foldedVal);
703
+
704
+ originalVal->replaceAllUsesWith (borrow);
705
+
706
+ cleanupAtEndOfLifetime (borrow, [&](SILInstruction *lifetimeEndInst) {
677
707
SILBuilderWithScope builder (lifetimeEndInst);
708
+ builder.createEndBorrow (lifetimeEndInst->getLoc (), borrow);
678
709
builder.emitDestroyValueOperation (lifetimeEndInst->getLoc (), foldedVal);
679
710
});
680
711
return ;
0 commit comments