Skip to content

Commit 0634bab

Browse files
authored
Merge pull request #78412 from meg-gupta/fixsilcombine
Fix SILCombine of existential applies
2 parents 979599d + ed0483b commit 0634bab

File tree

3 files changed

+53
-25
lines changed

3 files changed

+53
-25
lines changed

include/swift/SILOptimizer/Utils/Existential.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ struct ConcreteExistentialInfo {
7474
SILValue ConcreteValue;
7575
// True if the ConcreteValue is copied from another stack location
7676
bool isConcreteValueCopied = false;
77+
// True if the ConcreteValue should replace all uses of the opened
78+
// existential.
79+
bool ConcreteValueNeedsFixup = false;
7780
// When ConcreteType is itself an opened existential, record the type
7881
// definition. May be nullptr for a valid AppliedConcreteType.
7982
SingleValueInstruction *ConcreteTypeDef = nullptr;

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,7 +2855,21 @@ bb0(%0 : @owned $Klass):
28552855
%2 = open_existential_ref %1 : $AnyObject to $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
28562856
%f = function_ref @use_generic_obj_guaranteed : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
28572857
apply %f<@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self>(%2) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
2858+
%3 = unchecked_ref_cast %2 : $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
2859+
return %3 : $Builtin.NativeObject
2860+
}
28582861

2862+
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned4 :
2863+
// CHECK: apply {{.*}}<Klass>
2864+
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned4'
2865+
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned4 : $@convention(thin) (@owned Klass) -> @owned Builtin.NativeObject {
2866+
bb0(%0 : @owned $Klass):
2867+
%1 = init_existential_ref %0 : $Klass : $Klass, $AnyObject
2868+
%f1 = function_ref @use_anyobject_guaranteed : $@convention(thin) (@guaranteed AnyObject) -> ()
2869+
apply %f1(%1) : $@convention(thin) (@guaranteed AnyObject) -> ()
2870+
%2 = open_existential_ref %1 : $AnyObject to $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
2871+
%f2 = function_ref @use_generic_obj_guaranteed : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
2872+
apply %f2<@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self>(%2) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
28592873
%3 = unchecked_ref_cast %2 : $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
28602874
return %3 : $Builtin.NativeObject
28612875
}

0 commit comments

Comments
 (0)