@@ -798,30 +798,13 @@ SILCombiner::buildConcreteOpenedExistentialInfoFromSoleConformingType(
798798 // Prepare the code by adding UncheckedCast instructions that cast opened
799799 // existentials to concrete types. Set the ConcreteValue of CEI.
800800 if (auto *OER = dyn_cast<OpenExistentialRefInst>(OAI.OpenedArchetypeValue )) {
801- // If we have an owned open_existential_ref, we only optimize for now if our
802- // open_existential_ref has a single non-debug consuming use that is a
803- // destroy_value.
804- if (OER->getForwardingOwnershipKind () != OwnershipKind::Owned) {
805- // We use OER as the insertion point so that
806- SILBuilderWithScope b (std::next (OER->getIterator ()), Builder);
807- auto loc = RegularLocation::getAutoGeneratedLocation ();
808- SoleCEI.ConcreteValue =
809- b.createUncheckedRefCast (loc, OER, concreteSILType);
810- return COAI;
811- }
812-
813- auto *consumingUse = OER->getSingleConsumingUse ();
814- if (!consumingUse || !isa<DestroyValueInst>(consumingUse->getUser ())) {
815- return std::nullopt ;
816- }
817-
818- // We use std::next(OER) as the insertion point so that we can reuse the
819- // destroy_value of consumingUse.
820801 SILBuilderWithScope b (std::next (OER->getIterator ()), Builder);
821802 auto loc = RegularLocation::getAutoGeneratedLocation ();
822- auto *uri = b.createUncheckedRefCast (loc, OER, concreteSILType);
823- SoleCEI.ConcreteValue = uri;
824- replaceInstUsesWith (*OER, uri);
803+ SoleCEI.ConcreteValue = b.createUncheckedRefCast (loc, OER, concreteSILType);
804+ if (F->hasOwnership () &&
805+ SoleCEI.ConcreteValue ->getOwnershipKind () == OwnershipKind::Owned) {
806+ SoleCEI.ConcreteValueNeedsFixup = true ;
807+ }
825808 return COAI;
826809 }
827810
@@ -852,8 +835,19 @@ SILCombiner::buildConcreteOpenedExistentialInfo(Operand &ArgOperand) {
852835 // Build a ConcreteOpenedExistentialInfo following the data flow chain of the
853836 // ArgOperand through the open_existential backward to an init_existential.
854837 ConcreteOpenedExistentialInfo COEI (ArgOperand);
855- if (COEI.CEI )
838+ if (COEI.CEI ) {
839+ auto ConcreteValue = COEI.CEI ->ConcreteValue ;
840+ if (ConcreteValue->getFunction ()->hasOwnership () &&
841+ ConcreteValue->getOwnershipKind () == OwnershipKind::Owned) {
842+ SILBuilderWithScope b (COEI.OAI .OpenedArchetypeValue ->getNextInstruction (),
843+ Builder);
844+ auto loc = RegularLocation::getAutoGeneratedLocation ();
845+ COEI.CEI ->ConcreteValue = b.createUncheckedRefCast (
846+ loc, COEI.OAI .OpenedArchetypeValue , ConcreteValue->getType ());
847+ COEI.CEI ->ConcreteValueNeedsFixup = true ;
848+ }
856849 return COEI;
850+ }
857851
858852 // Use SoleConformingType information.
859853 return buildConcreteOpenedExistentialInfoFromSoleConformingType (ArgOperand);
@@ -1147,6 +1141,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
11471141
11481142 // Transform the parameter arguments.
11491143 SmallVector<ConcreteArgumentCopy, 4 > concreteArgCopies;
1144+ llvm::SmallMapVector<SILValue, SILValue, 4 > valuesToReplace;
11501145 for (unsigned EndIdx = Apply.getNumArguments (); ArgIdx < EndIdx; ++ArgIdx) {
11511146 auto ArgIt = COAIs.find (ArgIdx);
11521147 if (ArgIt == COAIs.end ()) {
@@ -1199,6 +1194,9 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
11991194 concreteArgCopies.push_back (*argSub);
12001195 NewArgs.push_back (argSub->tempArg );
12011196 } else {
1197+ if (CEI.ConcreteValueNeedsFixup ) {
1198+ valuesToReplace[OAI.OpenedArchetypeValue ] = CEI.ConcreteValue ;
1199+ }
12021200 NewArgs.push_back (CEI.ConcreteValue );
12031201 }
12041202
@@ -1260,9 +1258,8 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
12601258 // SILCombine Worklist.
12611259 InstructionDeleter deleter;
12621260 for (SILInstruction *inst : *Builder.getTrackingList ()) {
1263- deleter.trackIfDead (inst);
1261+ deleter.deleteIfDead (inst, false );
12641262 }
1265- deleter.cleanupDeadInstructions ();
12661263 Builder.getTrackingList ()->clear ();
12671264 return nullptr ;
12681265 }
@@ -1304,6 +1301,20 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
13041301 cleanupBuilder.createDeallocStack (cleanupLoc, argCopy.tempArg );
13051302 }
13061303 }
1304+ // Replace all uses of the opened existential with the unconditional cast to
1305+ // concrete type.
1306+ for (auto &valuePair : valuesToReplace) {
1307+ auto openedExistential = valuePair.first ;
1308+ auto uncheckedCast = valuePair.second ;
1309+ SmallVector<Operand *> uses (openedExistential->getNonTypeDependentUses ());
1310+ for (auto use : uses) {
1311+ auto *user = use->getUser ();
1312+ if (user == cast<SingleValueInstruction>(uncheckedCast)) {
1313+ continue ;
1314+ }
1315+ use->set (uncheckedCast);
1316+ }
1317+ }
13071318 return NewApply.getInstruction ();
13081319}
13091320
0 commit comments