Skip to content

Commit f524f3d

Browse files
committed
[NFC] Support instructions that define multiple opened archetypes
I've also fixed this so that it should work on instructions that define multiple values. Someday we'll change all the open_existential instructions to produce different values for the type dependency and the value result; today is not that day, though.
1 parent abe37fe commit f524f3d

File tree

6 files changed

+136
-74
lines changed

6 files changed

+136
-74
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,14 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
685685
return getResultsImpl().getTypes();
686686
}
687687

688+
/// Run the given function for each opened archetype this instruction
689+
/// defines, passing the value that should be used to record the
690+
/// dependency.
691+
void forEachDefinedOpenedArchetype(
692+
llvm::function_ref<void(CanOpenedArchetypeType archetype,
693+
SILValue typeDependency)> function) const;
694+
bool definesOpenedArchetypes() const;
695+
688696
MemoryBehavior getMemoryBehavior() const;
689697
ReleasingBehavior getReleasingBehavior() const;
690698

@@ -1096,10 +1104,6 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
10961104
node->getKind() <= SILNodeKind::Last_SingleValueInstruction;
10971105
}
10981106

1099-
/// If this is an instruction which "defines" a root opened archetype, it is
1100-
/// returned.
1101-
CanOpenedArchetypeType getDefinedOpenedArchetype() const;
1102-
11031107
SILInstruction *getPreviousInstruction() {
11041108
return SILInstruction::getPreviousInstruction();
11051109
}
@@ -7137,6 +7141,13 @@ class OpenExistentialAddrInst
71377141
}
71387142

71397143
OpenedExistentialAccess getAccessKind() const { return ForAccess; }
7144+
7145+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7146+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7147+
assert(archetype && archetype->isRoot() &&
7148+
"Type should be a root opened archetype");
7149+
return archetype;
7150+
}
71407151
};
71417152

71427153
/// Given an opaque value referring to an existential, "opens" the
@@ -7150,6 +7161,14 @@ class OpenExistentialValueInst
71507161
OpenExistentialValueInst(SILDebugLocation debugLoc, SILValue operand,
71517162
SILType selfTy,
71527163
ValueOwnershipKind forwardingOwnershipKind);
7164+
7165+
public:
7166+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7167+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7168+
assert(archetype && archetype->isRoot() &&
7169+
"Type should be a root opened archetype");
7170+
return archetype;
7171+
}
71537172
};
71547173

71557174
/// Given a class existential, "opens" the
@@ -7163,6 +7182,14 @@ class OpenExistentialRefInst
71637182
OpenExistentialRefInst(SILDebugLocation DebugLoc, SILValue Operand,
71647183
SILType Ty,
71657184
ValueOwnershipKind forwardingOwnershipKind);
7185+
7186+
public:
7187+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7188+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7189+
assert(archetype && archetype->isRoot() &&
7190+
"Type should be a root opened archetype");
7191+
return archetype;
7192+
}
71667193
};
71677194

71687195
/// Given an existential metatype,
@@ -7177,6 +7204,14 @@ class OpenExistentialMetatypeInst
71777204

71787205
OpenExistentialMetatypeInst(SILDebugLocation DebugLoc, SILValue operand,
71797206
SILType ty);
7207+
7208+
public:
7209+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7210+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7211+
assert(archetype && archetype->isRoot() &&
7212+
"Type should be a root opened archetype");
7213+
return archetype;
7214+
}
71807215
};
71817216

71827217
/// Given a boxed existential container,
@@ -7190,6 +7225,14 @@ class OpenExistentialBoxInst
71907225

71917226
OpenExistentialBoxInst(SILDebugLocation DebugLoc, SILValue operand,
71927227
SILType ty);
7228+
7229+
public:
7230+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7231+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7232+
assert(archetype && archetype->isRoot() &&
7233+
"Type should be a root opened archetype");
7234+
return archetype;
7235+
}
71937236
};
71947237

71957238
/// Given a boxed existential container, "opens" the existential by returning a
@@ -7203,6 +7246,14 @@ class OpenExistentialBoxValueInst
72037246
OpenExistentialBoxValueInst(SILDebugLocation DebugLoc, SILValue operand,
72047247
SILType ty,
72057248
ValueOwnershipKind forwardingOwnershipKind);
7249+
7250+
public:
7251+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7252+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7253+
assert(archetype && archetype->isRoot() &&
7254+
"Type should be a root opened archetype");
7255+
return archetype;
7256+
}
72067257
};
72077258

72087259
/// Given an address to an uninitialized buffer of

lib/SIL/IR/SILInstruction.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,24 +1528,37 @@ const ValueBase *SILInstructionResultArray::back() const {
15281528
}
15291529

15301530
//===----------------------------------------------------------------------===//
1531-
// SingleValueInstruction
1531+
// Defined opened archetypes
15321532
//===----------------------------------------------------------------------===//
15331533

1534-
CanOpenedArchetypeType
1535-
SingleValueInstruction::getDefinedOpenedArchetype() const {
1534+
bool SILInstruction::definesOpenedArchetypes() const {
1535+
bool definesAny = false;
1536+
forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType type,
1537+
SILValue dependency) {
1538+
definesAny = true;
1539+
});
1540+
return definesAny;
1541+
}
1542+
1543+
void SILInstruction::forEachDefinedOpenedArchetype(
1544+
llvm::function_ref<void(CanOpenedArchetypeType, SILValue)> fn) const {
15361545
switch (getKind()) {
1537-
case SILInstructionKind::OpenExistentialAddrInst:
1538-
case SILInstructionKind::OpenExistentialRefInst:
1539-
case SILInstructionKind::OpenExistentialBoxInst:
1540-
case SILInstructionKind::OpenExistentialBoxValueInst:
1541-
case SILInstructionKind::OpenExistentialMetatypeInst:
1542-
case SILInstructionKind::OpenExistentialValueInst: {
1543-
const auto Ty = getOpenedArchetypeOf(getType().getASTType());
1544-
assert(Ty && Ty->isRoot() && "Type should be a root opened archetype");
1545-
return Ty;
1546+
#define SINGLE_VALUE_SINGLE_OPEN(TYPE) \
1547+
case SILInstructionKind::TYPE: { \
1548+
auto I = cast<TYPE>(this); \
1549+
auto archetype = I->getDefinedOpenedArchetype(); \
1550+
assert(archetype); \
1551+
return fn(archetype, I); \
15461552
}
1553+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialAddrInst)
1554+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialRefInst)
1555+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialBoxInst)
1556+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialBoxValueInst)
1557+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialMetatypeInst)
1558+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialValueInst)
1559+
#undef SINGLE_VALUE_SINGLE_OPEN
15471560
default:
1548-
return CanOpenedArchetypeType();
1561+
return;
15491562
}
15501563
}
15511564

lib/SIL/IR/SILModule.cpp

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -260,17 +260,15 @@ void *SILModule::allocateInst(unsigned Size, unsigned Align) const {
260260

261261
void SILModule::willDeleteInstruction(SILInstruction *I) {
262262
// Update RootOpenedArchetypeDefs.
263-
if (auto *svi = dyn_cast<SingleValueInstruction>(I)) {
264-
if (const CanOpenedArchetypeType archeTy =
265-
svi->getDefinedOpenedArchetype()) {
266-
OpenedArchetypeKey key = {archeTy, svi->getFunction()};
267-
// In case `willDeleteInstruction` is called twice for the same instruction,
268-
// we need to check if the archetype is really still in the map for this
269-
// instruction.
270-
if (RootOpenedArchetypeDefs.lookup(key) == svi)
271-
RootOpenedArchetypeDefs.erase(key);
272-
}
273-
}
263+
I->forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType archeTy,
264+
SILValue dependency) {
265+
OpenedArchetypeKey key = {archeTy, I->getFunction()};
266+
// In case `willDeleteInstruction` is called twice for the
267+
// same instruction, we need to check if the archetype is really
268+
// still in the map for this instruction.
269+
if (RootOpenedArchetypeDefs.lookup(key) == dependency)
270+
RootOpenedArchetypeDefs.erase(key);
271+
});
274272
}
275273

276274
void SILModule::scheduleForDeletion(SILInstruction *I) {
@@ -766,45 +764,41 @@ unsigned SILModule::getCaseIndex(EnumElementDecl *enumElement) {
766764
}
767765

768766
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
769-
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
770-
if (const CanOpenedArchetypeType archeTy =
771-
svi->getDefinedOpenedArchetype()) {
772-
SILValue &val = RootOpenedArchetypeDefs[{archeTy, inst->getFunction()}];
773-
if (val) {
774-
if (!isa<PlaceholderValue>(val)) {
775-
// Print a useful error message (and not just abort with an assert).
776-
llvm::errs() << "re-definition of root opened archetype in function "
777-
<< svi->getFunction()->getName() << ":\n";
778-
svi->print(llvm::errs());
779-
llvm::errs() << "previously defined in function "
780-
<< val->getFunction()->getName() << ":\n";
781-
val->print(llvm::errs());
782-
abort();
783-
}
784-
// The opened archetype was unresolved so far. Replace the placeholder
785-
// by inst.
786-
auto *placeholder = cast<PlaceholderValue>(val);
787-
placeholder->replaceAllUsesWith(svi);
788-
::delete placeholder;
789-
numUnresolvedOpenedArchetypes--;
767+
inst->forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType archeTy,
768+
SILValue dependency) {
769+
SILValue &val = RootOpenedArchetypeDefs[{archeTy, inst->getFunction()}];
770+
if (val) {
771+
if (!isa<PlaceholderValue>(val)) {
772+
// Print a useful error message (and not just abort with an assert).
773+
llvm::errs() << "re-definition of root opened archetype in function "
774+
<< inst->getFunction()->getName() << ":\n";
775+
inst->print(llvm::errs());
776+
llvm::errs() << "previously defined in function "
777+
<< val->getFunction()->getName() << ":\n";
778+
val->print(llvm::errs());
779+
abort();
790780
}
791-
val = svi;
781+
// The opened archetype was unresolved so far. Replace the placeholder
782+
// by inst.
783+
auto *placeholder = cast<PlaceholderValue>(val);
784+
placeholder->replaceAllUsesWith(dependency);
785+
::delete placeholder;
786+
numUnresolvedOpenedArchetypes--;
792787
}
793-
}
788+
val = dependency;
789+
});
794790
}
795791

796792
void SILModule::notifyMovedInstruction(SILInstruction *inst,
797793
SILFunction *fromFunction) {
798-
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
799-
if (const CanOpenedArchetypeType archeTy =
800-
svi->getDefinedOpenedArchetype()) {
801-
OpenedArchetypeKey key = {archeTy, fromFunction};
802-
assert(RootOpenedArchetypeDefs.lookup(key) == svi &&
803-
"archetype def was not registered");
804-
RootOpenedArchetypeDefs.erase(key);
805-
RootOpenedArchetypeDefs[{archeTy, svi->getFunction()}] = svi;
806-
}
807-
}
794+
inst->forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType archeTy,
795+
SILValue dependency) {
796+
OpenedArchetypeKey key = {archeTy, fromFunction};
797+
assert(RootOpenedArchetypeDefs.lookup(key) == dependency &&
798+
"archetype def was not registered");
799+
RootOpenedArchetypeDefs.erase(key);
800+
RootOpenedArchetypeDefs[{archeTy, inst->getFunction()}] = dependency;
801+
});
808802
}
809803

810804
// TODO: We should have an "isNoReturn" bit on Swift's BuiltinInfo, but for

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,13 +1645,20 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16451645
require((ValueBase *)V == AI->getFunction()->getDynamicSelfMetadata(),
16461646
"wrong self metadata operand");
16471647
} else {
1648-
require(isa<SingleValueInstruction>(V),
1648+
auto DI = V->getDefiningInstruction();
1649+
require(DI,
16491650
"opened archetype operand should refer to a SIL instruction");
1650-
auto Archetype =
1651-
cast<SingleValueInstruction>(V)->getDefinedOpenedArchetype();
1652-
require(Archetype,
1651+
bool definesFoundArchetype = false;
1652+
bool definesAnyArchetype = false;
1653+
DI->forEachDefinedOpenedArchetype(
1654+
[&](CanOpenedArchetypeType archetype, SILValue dependency) {
1655+
definesAnyArchetype = true;
1656+
if (FoundRootOpenedArchetypes.count(archetype))
1657+
definesFoundArchetype = true;
1658+
});
1659+
require(definesAnyArchetype,
16531660
"opened archetype operand should define an opened archetype");
1654-
require(FoundRootOpenedArchetypes.count(Archetype),
1661+
require(definesFoundArchetype,
16551662
"opened archetype operand does not correspond to any opened "
16561663
"archetype from the substitutions list");
16571664
}

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,8 +1301,8 @@ AllocStackInst *OpaqueStorageAllocation::createStackAllocation(SILValue value) {
13011301
// Instructions that produce an opened type never reach here because they
13021302
// have guaranteed ownership--they project their storage. We reach this
13031303
// point after the opened value has been copied.
1304-
assert((!isa<SingleValueInstruction>(value)
1305-
|| !cast<SingleValueInstruction>(value)->getDefinedOpenedArchetype())
1304+
assert((!value->getDefiningInstruction() ||
1305+
!value->getDefiningInstruction()->definesOpenedArchetypes())
13061306
&& "owned open_existential is unsupported");
13071307

13081308
SILType allocTy = value->getType();

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,8 @@ class CSE {
665665
};
666666

667667
bool processNode(DominanceInfoNode *Node);
668-
bool processOpenExistentialRef(OpenExistentialRefInst *Inst, ValueBase *V);
668+
bool processOpenExistentialRef(OpenExistentialRefInst *Inst,
669+
OpenExistentialRefInst *V);
669670
};
670671
} // namespace swift
671672

@@ -802,11 +803,7 @@ static void updateBasicBlockArgTypes(SILBasicBlock *BB,
802803
/// \Inst is the open_existential_ref instruction
803804
/// \V is the dominating open_existential_ref instruction
804805
bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst,
805-
ValueBase *V) {
806-
// All the open instructions are single-value instructions.
807-
auto VI = dyn_cast<SingleValueInstruction>(V);
808-
if (!VI) return false;
809-
806+
OpenExistentialRefInst *VI) {
810807
llvm::SmallSetVector<SILInstruction *, 16> Candidates;
811808
const auto OldOpenedArchetype = Inst->getDefinedOpenedArchetype();
812809
const auto NewOpenedArchetype = VI->getDefinedOpenedArchetype();

0 commit comments

Comments
 (0)