@@ -1751,7 +1751,9 @@ SILInstruction *SILCombiner::visitUncheckedTakeEnumDataAddrInst(
17511751 SILType payloadType = tedai->getType ().getObjectType ();
17521752
17531753 // Go back through a second time now that we know all of our users are
1754- // loads. Perform the transformation on each load.
1754+ // loads. Perform the transformation on each load at the load's use site. The
1755+ // reason that we have to do this is that otherwise we would be hoisting the
1756+ // loads causing us to need to consider additional ARC issues.
17551757 while (!tedai->use_empty ()) {
17561758 auto *use = *tedai->use_begin ();
17571759 auto *user = use->getUser ();
@@ -1763,40 +1765,52 @@ SILInstruction *SILCombiner::visitUncheckedTakeEnumDataAddrInst(
17631765 }
17641766
17651767 // Insert a new Load of the enum and extract the data from that.
1768+ //
1769+ // NOTE: This is potentially hoisting the load, so we need to insert
1770+ // compensating destroys.
17661771 auto *svi = cast<SingleValueInstruction>(user);
17671772 SILValue newValue;
17681773 if (auto *oldLoad = dyn_cast<LoadInst>(svi)) {
1774+ SILBuilderWithScope localBuilder (oldLoad, Builder);
17691775 // If the old load is trivial and our enum addr is non-trivial, we need to
17701776 // use a load_borrow here. We know that the unchecked_enum_data will
17711777 // produce a trivial value meaning that we can just do a
17721778 // load_borrow/immediately end the lifetime here.
17731779 if (oldLoad->getOwnershipQualifier () == LoadOwnershipQualifier::Trivial &&
17741780 !enumAddr->getType ().isTrivial (Builder.getFunction ())) {
1775- Builder.emitScopedBorrowOperation (loc, enumAddr, [&](SILValue newLoad) {
1776- newValue = Builder.createUncheckedEnumData (loc, newLoad, enumElt,
1777- payloadType);
1778- });
1781+ localBuilder.emitScopedBorrowOperation (
1782+ loc, enumAddr, [&](SILValue newLoad) {
1783+ newValue = localBuilder.createUncheckedEnumData (
1784+ loc, newLoad, enumElt, payloadType);
1785+ });
17791786 } else {
1780- auto newLoad = Builder .emitLoadValueOperation (
1787+ auto newLoad = localBuilder .emitLoadValueOperation (
17811788 loc, enumAddr, oldLoad->getOwnershipQualifier ());
1782- newValue =
1783- Builder. createUncheckedEnumData (loc, newLoad, enumElt, payloadType);
1789+ newValue = localBuilder. createUncheckedEnumData (loc, newLoad, enumElt,
1790+ payloadType);
17841791 }
17851792 } else if (auto *lbi = cast<LoadBorrowInst>(svi)) {
1786- auto newLoad = Builder.emitLoadBorrowOperation (loc, enumAddr);
1793+ SILBuilderWithScope localBuilder (lbi, Builder);
1794+ auto newLoad = localBuilder.emitLoadBorrowOperation (loc, enumAddr);
17871795 for (auto ui = lbi->consuming_use_begin (), ue = lbi->consuming_use_end ();
17881796 ui != ue; ui = lbi->consuming_use_begin ()) {
17891797 // We already checked that all of our uses here are end_borrow above.
17901798 assert (isa<EndBorrowInst>(ui->getUser ()) &&
17911799 " Expected only end_borrow consuming uses" );
17921800 ui->set (newLoad);
17931801 }
1794- newValue =
1795- Builder.createUncheckedEnumData (loc, newLoad, enumElt, payloadType);
1802+ // Any lifetime ending uses of our original load_borrow have been
1803+ // rewritten by the previous loop to be on the new load_borrow. The reason
1804+ // that we must do this is end_borrows only are placed on borrow
1805+ // introducing guaranteed values and our unchecked_enum_data (unlike the
1806+ // old load_borrow of the same type) is not one.
1807+ newValue = localBuilder.createUncheckedEnumData (loc, newLoad, enumElt,
1808+ payloadType);
17961809 }
17971810 assert (newValue);
17981811
1799- // Replace all uses of the old load with the data and erase the old load.
1812+ // Replace all uses of the old load with the newValue and erase the old
1813+ // load.
18001814 replaceInstUsesWith (*svi, newValue);
18011815 eraseInstFromFunction (*svi);
18021816 }
0 commit comments