Skip to content

Commit ef9fe8e

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 762a093 commit ef9fe8e

File tree

6 files changed

+134
-72
lines changed

6 files changed

+134
-72
lines changed

include/swift/SIL/SILInstruction.h

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

639+
/// Run the given function for each opened archetype this instruction
640+
/// defines, passing the value that should be used to record the
641+
/// dependency.
642+
void forEachDefinedOpenedArchetype(
643+
llvm::function_ref<void(CanOpenedArchetypeType archetype,
644+
SILValue typeDependency)> function) const;
645+
bool definesOpenedArchetypes() const;
646+
639647
MemoryBehavior getMemoryBehavior() const;
640648
ReleasingBehavior getReleasingBehavior() const;
641649

@@ -1047,10 +1055,6 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
10471055
node->getKind() <= SILNodeKind::Last_SingleValueInstruction;
10481056
}
10491057

1050-
/// If this is an instruction which "defines" a root opened archetype, it is
1051-
/// returned.
1052-
CanOpenedArchetypeType getDefinedOpenedArchetype() const;
1053-
10541058
SILInstruction *getPreviousInstruction() {
10551059
return SILInstruction::getPreviousInstruction();
10561060
}
@@ -7088,6 +7092,13 @@ class OpenExistentialAddrInst
70887092
}
70897093

70907094
OpenedExistentialAccess getAccessKind() const { return ForAccess; }
7095+
7096+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7097+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7098+
assert(archetype && archetype->isRoot() &&
7099+
"Type should be a root opened archetype");
7100+
return archetype;
7101+
}
70917102
};
70927103

70937104
/// Given an opaque value referring to an existential, "opens" the
@@ -7101,6 +7112,14 @@ class OpenExistentialValueInst
71017112
OpenExistentialValueInst(SILDebugLocation debugLoc, SILValue operand,
71027113
SILType selfTy,
71037114
ValueOwnershipKind forwardingOwnershipKind);
7115+
7116+
public:
7117+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7118+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7119+
assert(archetype && archetype->isRoot() &&
7120+
"Type should be a root opened archetype");
7121+
return archetype;
7122+
}
71047123
};
71057124

71067125
/// Given a class existential, "opens" the
@@ -7114,6 +7133,14 @@ class OpenExistentialRefInst
71147133
OpenExistentialRefInst(SILDebugLocation DebugLoc, SILValue Operand,
71157134
SILType Ty,
71167135
ValueOwnershipKind forwardingOwnershipKind);
7136+
7137+
public:
7138+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7139+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7140+
assert(archetype && archetype->isRoot() &&
7141+
"Type should be a root opened archetype");
7142+
return archetype;
7143+
}
71177144
};
71187145

71197146
/// Given an existential metatype,
@@ -7128,6 +7155,14 @@ class OpenExistentialMetatypeInst
71287155

71297156
OpenExistentialMetatypeInst(SILDebugLocation DebugLoc, SILValue operand,
71307157
SILType ty);
7158+
7159+
public:
7160+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7161+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7162+
assert(archetype && archetype->isRoot() &&
7163+
"Type should be a root opened archetype");
7164+
return archetype;
7165+
}
71317166
};
71327167

71337168
/// Given a boxed existential container,
@@ -7141,6 +7176,14 @@ class OpenExistentialBoxInst
71417176

71427177
OpenExistentialBoxInst(SILDebugLocation DebugLoc, SILValue operand,
71437178
SILType ty);
7179+
7180+
public:
7181+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7182+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7183+
assert(archetype && archetype->isRoot() &&
7184+
"Type should be a root opened archetype");
7185+
return archetype;
7186+
}
71447187
};
71457188

71467189
/// Given a boxed existential container, "opens" the existential by returning a
@@ -7154,6 +7197,14 @@ class OpenExistentialBoxValueInst
71547197
OpenExistentialBoxValueInst(SILDebugLocation DebugLoc, SILValue operand,
71557198
SILType ty,
71567199
ValueOwnershipKind forwardingOwnershipKind);
7200+
7201+
public:
7202+
CanOpenedArchetypeType getDefinedOpenedArchetype() const {
7203+
const auto archetype = getOpenedArchetypeOf(getType().getASTType());
7204+
assert(archetype && archetype->isRoot() &&
7205+
"Type should be a root opened archetype");
7206+
return archetype;
7207+
}
71577208
};
71587209

71597210
/// 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
@@ -1549,24 +1549,37 @@ const ValueBase *SILInstructionResultArray::back() const {
15491549
}
15501550

15511551
//===----------------------------------------------------------------------===//
1552-
// SingleValueInstruction
1552+
// Defined opened archetypes
15531553
//===----------------------------------------------------------------------===//
15541554

1555-
CanOpenedArchetypeType
1556-
SingleValueInstruction::getDefinedOpenedArchetype() const {
1555+
bool SILInstruction::definesOpenedArchetypes() const {
1556+
bool definesAny = false;
1557+
forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType type,
1558+
SILValue dependency) {
1559+
definesAny = true;
1560+
});
1561+
return definesAny;
1562+
}
1563+
1564+
void SILInstruction::forEachDefinedOpenedArchetype(
1565+
llvm::function_ref<void(CanOpenedArchetypeType, SILValue)> fn) const {
15571566
switch (getKind()) {
1558-
case SILInstructionKind::OpenExistentialAddrInst:
1559-
case SILInstructionKind::OpenExistentialRefInst:
1560-
case SILInstructionKind::OpenExistentialBoxInst:
1561-
case SILInstructionKind::OpenExistentialBoxValueInst:
1562-
case SILInstructionKind::OpenExistentialMetatypeInst:
1563-
case SILInstructionKind::OpenExistentialValueInst: {
1564-
const auto Ty = getOpenedArchetypeOf(getType().getASTType());
1565-
assert(Ty && Ty->isRoot() && "Type should be a root opened archetype");
1566-
return Ty;
1567+
#define SINGLE_VALUE_SINGLE_OPEN(TYPE) \
1568+
case SILInstructionKind::TYPE: { \
1569+
auto I = cast<TYPE>(this); \
1570+
auto archetype = I->getDefinedOpenedArchetype(); \
1571+
assert(archetype); \
1572+
return fn(archetype, I); \
15671573
}
1574+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialAddrInst)
1575+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialRefInst)
1576+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialBoxInst)
1577+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialBoxValueInst)
1578+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialMetatypeInst)
1579+
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialValueInst)
1580+
#undef SINGLE_VALUE_SINGLE_OPEN
15681581
default:
1569-
return CanOpenedArchetypeType();
1582+
return;
15701583
}
15711584
}
15721585

lib/SIL/IR/SILModule.cpp

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,13 @@ 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-
assert(RootOpenedArchetypeDefs.lookup(key) == svi &&
268-
"archetype def was not registered");
269-
RootOpenedArchetypeDefs.erase(key);
270-
}
271-
}
263+
I->forEachDefinedOpenedArchetype([&](CanOpenedArchetypeType archeTy,
264+
SILValue dependency) {
265+
OpenedArchetypeKey key = {archeTy, I->getFunction()};
266+
assert(RootOpenedArchetypeDefs.lookup(key) == dependency &&
267+
"archetype def was not registered");
268+
RootOpenedArchetypeDefs.erase(key);
269+
});
272270
}
273271

274272
void SILModule::scheduleForDeletion(SILInstruction *I) {
@@ -765,45 +763,41 @@ unsigned SILModule::getCaseIndex(EnumElementDecl *enumElement) {
765763
}
766764

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

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

809803
// 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)