Skip to content

Commit b68a78c

Browse files
committed
SIL: Track local environments instead of root local archetypes
1 parent e918422 commit b68a78c

File tree

6 files changed

+60
-63
lines changed

6 files changed

+60
-63
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,8 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
722722
/// Run the given function for each local archetype this instruction
723723
/// defines, passing the value that should be used to record the
724724
/// dependency.
725-
void forEachDefinedLocalArchetype(
726-
llvm::function_ref<void(CanLocalArchetypeType archetype,
725+
void forEachDefinedLocalEnvironment(
726+
llvm::function_ref<void(GenericEnvironment *genericEnv,
727727
SILValue typeDependency)> function) const;
728728
bool definesLocalArchetypes() const;
729729

@@ -8194,8 +8194,8 @@ class OpenPackElementInst final
81948194
public:
81958195
/// Call the given function for each element archetype that this
81968196
/// instruction opens.
8197-
void forEachDefinedLocalArchetype(
8198-
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const;
8197+
void forEachDefinedLocalEnvironment(
8198+
llvm::function_ref<void(GenericEnvironment *, SILValue)> fn) const;
81998199

82008200
GenericEnvironment *getOpenedGenericEnvironment() const {
82018201
return Env;

include/swift/SIL/SILModule.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,18 @@ class SILModule {
343343
/// projections, shared between all functions in the module.
344344
std::unique_ptr<IndexTrieNode> indexTrieRoot;
345345

346-
/// A mapping from root local archetypes to the instructions which define
346+
/// A mapping from local generic environments to the instructions which define
347347
/// them.
348348
///
349349
/// The value is either a SingleValueInstruction or a PlaceholderValue,
350350
/// in case a local archetype definition is looked up during parsing or
351351
/// deserializing SIL, where local archetypes can be forward referenced.
352352
///
353353
/// In theory we wouldn't need to have the SILFunction in the key, because
354-
/// local archetypes \em should be unique across the module. But currently
354+
/// local environments should be unique across the module. But currently
355355
/// in some rare cases SILGen re-uses the same local archetype for multiple
356356
/// functions.
357-
using LocalArchetypeKey = std::pair<LocalArchetypeType *, SILFunction *>;
357+
using LocalArchetypeKey = std::pair<GenericEnvironment *, SILFunction *>;
358358
llvm::DenseMap<LocalArchetypeKey, SILValue> RootLocalArchetypeDefs;
359359

360360
/// The number of PlaceholderValues in RootLocalArchetypeDefs.
@@ -451,6 +451,15 @@ class SILModule {
451451
hasAccessMarkerHandler = true;
452452
}
453453

454+
/// Returns the instruction which defines the given local generic environment,
455+
/// e.g. an open_existential_addr.
456+
///
457+
/// In case the generic environment is not defined yet (e.g. during parsing or
458+
/// deserialization), a PlaceholderValue is returned. This should not be the
459+
/// case outside of parsing or deserialization.
460+
SILValue getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
461+
SILFunction *inFunction);
462+
454463
/// Returns the instruction which defines the given root local archetype,
455464
/// e.g. an open_existential_addr.
456465
///

lib/SIL/IR/SILInstruction.cpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,22 +1676,21 @@ const ValueBase *SILInstructionResultArray::back() const {
16761676

16771677
bool SILInstruction::definesLocalArchetypes() const {
16781678
bool definesAny = false;
1679-
forEachDefinedLocalArchetype([&](CanLocalArchetypeType type,
1680-
SILValue dependency) {
1679+
forEachDefinedLocalEnvironment([&](GenericEnvironment *genericEnv,
1680+
SILValue dependency) {
16811681
definesAny = true;
16821682
});
16831683
return definesAny;
16841684
}
16851685

1686-
void SILInstruction::forEachDefinedLocalArchetype(
1687-
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const {
1686+
void SILInstruction::forEachDefinedLocalEnvironment(
1687+
llvm::function_ref<void(GenericEnvironment *, SILValue)> fn) const {
16881688
switch (getKind()) {
16891689
#define SINGLE_VALUE_SINGLE_OPEN(TYPE) \
16901690
case SILInstructionKind::TYPE: { \
16911691
auto I = cast<TYPE>(this); \
16921692
auto archetype = I->getDefinedOpenedArchetype(); \
1693-
assert(archetype); \
1694-
return fn(archetype, I); \
1693+
return fn(archetype->getGenericEnvironment(), I); \
16951694
}
16961695
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialAddrInst)
16971696
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialRefInst)
@@ -1700,22 +1699,15 @@ void SILInstruction::forEachDefinedLocalArchetype(
17001699
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialMetatypeInst)
17011700
SINGLE_VALUE_SINGLE_OPEN(OpenExistentialValueInst)
17021701
#undef SINGLE_VALUE_SINGLE_OPEN
1703-
case SILInstructionKind::OpenPackElementInst:
1704-
return cast<OpenPackElementInst>(this)->forEachDefinedLocalArchetype(fn);
1702+
case SILInstructionKind::OpenPackElementInst: {
1703+
auto I = cast<OpenPackElementInst>(this);
1704+
return fn(I->getOpenedGenericEnvironment(), I);
1705+
}
17051706
default:
17061707
return;
17071708
}
17081709
}
17091710

1710-
void OpenPackElementInst::forEachDefinedLocalArchetype(
1711-
llvm::function_ref<void(CanLocalArchetypeType, SILValue)> fn) const {
1712-
getOpenedGenericEnvironment()->forEachPackElementBinding(
1713-
[&](ElementArchetypeType *elementType,
1714-
PackType *packSubstitution) {
1715-
fn(CanElementArchetypeType(elementType), this);
1716-
});
1717-
}
1718-
17191711
//===----------------------------------------------------------------------===//
17201712
// Multiple Value Instruction
17211713
//===----------------------------------------------------------------------===//

lib/SIL/IR/SILInstructions.cpp

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
4747

4848
namespace {
4949
class TypeDependentOperandCollector {
50-
SmallVector<CanLocalArchetypeType, 4> rootLocalArchetypes;
50+
SmallVector<GenericEnvironment *, 4> genericEnvs;
5151
bool hasDynamicSelf = false;
5252
public:
5353
void collect(CanType type);
@@ -86,15 +86,15 @@ void TypeDependentOperandCollector::collect(CanType type) {
8686
return;
8787
type.visit([&](CanType t) {
8888
if (const auto local = dyn_cast<LocalArchetypeType>(t)) {
89-
const auto root = local.getRoot();
89+
auto *genericEnv = local->getGenericEnvironment();
9090

91-
// Add this root local archetype if it was not seen yet.
91+
// Add this local archetype's environment if it was not seen yet.
9292
// We don't use a set here, because the number of open archetypes
9393
// is usually very small and using a real set may introduce too
9494
// much overhead.
95-
if (std::find(rootLocalArchetypes.begin(), rootLocalArchetypes.end(),
96-
root) == rootLocalArchetypes.end())
97-
rootLocalArchetypes.push_back(root);
95+
if (std::find(genericEnvs.begin(), genericEnvs.end(),
96+
genericEnv) == genericEnvs.end())
97+
genericEnvs.push_back(genericEnv);
9898
}
9999
});
100100
}
@@ -113,20 +113,11 @@ void TypeDependentOperandCollector::collect(SubstitutionMap subs) {
113113
/// for those dependencies to the given vector.
114114
void TypeDependentOperandCollector::addTo(SmallVectorImpl<SILValue> &operands,
115115
SILFunction &F) {
116-
size_t firstArchetypeOperand = operands.size();
117-
for (CanLocalArchetypeType archetype : rootLocalArchetypes) {
118-
SILValue def = F.getModule().getRootLocalArchetypeDef(archetype, &F);
116+
for (GenericEnvironment *genericEnv : genericEnvs) {
117+
SILValue def = F.getModule().getLocalGenericEnvironmentDef(genericEnv, &F);
119118
assert(def->getFunction() == &F &&
120-
"def of root local archetype is in wrong function");
121-
122-
// The archetypes in rootLocalArchetypes have already been uniqued,
123-
// but a single instruction can open multiple archetypes (e.g.
124-
// open_pack_element), so we also unique the actual operand values.
125-
// As above, we assume there are very few values in practice and so
126-
// a linear scan is better than maintaining a set.
127-
if (std::find(operands.begin() + firstArchetypeOperand, operands.end(),
128-
def) == operands.end())
129-
operands.push_back(def);
119+
"def of local environment is in wrong function");
120+
operands.push_back(def);
130121
}
131122
if (hasDynamicSelf)
132123
operands.push_back(F.getDynamicSelfMetadata());

lib/SIL/IR/SILModule.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,9 @@ void *SILModule::allocateInst(unsigned Size, unsigned Align) const {
208208

209209
void SILModule::willDeleteInstruction(SILInstruction *I) {
210210
// Update RootLocalArchetypeDefs.
211-
I->forEachDefinedLocalArchetype([&](CanLocalArchetypeType archeTy,
212-
SILValue dependency) {
213-
LocalArchetypeKey key = {archeTy, I->getFunction()};
211+
I->forEachDefinedLocalEnvironment([&](GenericEnvironment *genericEnv,
212+
SILValue dependency) {
213+
LocalArchetypeKey key = {genericEnv, I->getFunction()};
214214
// In case `willDeleteInstruction` is called twice for the
215215
// same instruction, we need to check if the archetype is really
216216
// still in the map for this instruction.
@@ -674,20 +674,25 @@ void SILModule::registerDeserializationNotificationHandler(
674674
deserializationNotificationHandlers.add(std::move(handler));
675675
}
676676

677-
SILValue SILModule::getRootLocalArchetypeDef(CanLocalArchetypeType archetype,
678-
SILFunction *inFunction) {
679-
assert(archetype->isRoot());
680-
681-
SILValue &def = RootLocalArchetypeDefs[{archetype, inFunction}];
677+
SILValue SILModule::getLocalGenericEnvironmentDef(GenericEnvironment *genericEnv,
678+
SILFunction *inFunction) {
679+
SILValue &def = RootLocalArchetypeDefs[{genericEnv, inFunction}];
682680
if (!def) {
683681
numUnresolvedLocalArchetypes++;
684682
def = ::new PlaceholderValue(inFunction,
685-
SILType::getPrimitiveAddressType(archetype));
683+
SILType::getPrimitiveAddressType(
684+
inFunction->getASTContext().TheEmptyTupleType));
686685
}
687686

688687
return def;
689688
}
690689

690+
SILValue SILModule::getRootLocalArchetypeDef(CanLocalArchetypeType archetype,
691+
SILFunction *inFunction) {
692+
return getLocalGenericEnvironmentDef(archetype->getGenericEnvironment(),
693+
inFunction);
694+
}
695+
691696
void SILModule::reclaimUnresolvedLocalArchetypeDefinitions() {
692697
llvm::DenseMap<LocalArchetypeKey, SILValue> newLocalArchetypeDefs;
693698

@@ -757,21 +762,21 @@ unsigned SILModule::getCaseIndex(EnumElementDecl *enumElement) {
757762
}
758763

759764
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
760-
inst->forEachDefinedLocalArchetype([&](CanLocalArchetypeType archeTy,
761-
SILValue dependency) {
762-
SILValue &val = RootLocalArchetypeDefs[{archeTy, inst->getFunction()}];
765+
inst->forEachDefinedLocalEnvironment([&](GenericEnvironment *genericEnv,
766+
SILValue dependency) {
767+
SILValue &val = RootLocalArchetypeDefs[{genericEnv, inst->getFunction()}];
763768
if (val) {
764769
if (!isa<PlaceholderValue>(val)) {
765770
// Print a useful error message (and not just abort with an assert).
766-
llvm::errs() << "re-definition of root local archetype in function "
771+
llvm::errs() << "re-definition of local environment in function "
767772
<< inst->getFunction()->getName() << ":\n";
768773
inst->print(llvm::errs());
769774
llvm::errs() << "previously defined in function "
770775
<< val->getFunction()->getName() << ":\n";
771776
val->print(llvm::errs());
772777
abort();
773778
}
774-
// The local archetype was unresolved so far. Replace the placeholder
779+
// The local environment was unresolved so far. Replace the placeholder
775780
// by inst.
776781
auto *placeholder = cast<PlaceholderValue>(val);
777782
placeholder->replaceAllUsesWith(dependency);
@@ -792,13 +797,13 @@ void SILModule::notifyMovedInstruction(SILInstruction *inst,
792797
}
793798
}
794799

795-
inst->forEachDefinedLocalArchetype([&](CanLocalArchetypeType archeTy,
796-
SILValue dependency) {
797-
LocalArchetypeKey key = {archeTy, fromFunction};
800+
inst->forEachDefinedLocalEnvironment([&](GenericEnvironment *genericEnv,
801+
SILValue dependency) {
802+
LocalArchetypeKey key = {genericEnv, fromFunction};
798803
assert(RootLocalArchetypeDefs.lookup(key) == dependency &&
799804
"archetype def was not registered");
800805
RootLocalArchetypeDefs.erase(key);
801-
RootLocalArchetypeDefs[{archeTy, inst->getFunction()}] = dependency;
806+
RootLocalArchetypeDefs[{genericEnv, inst->getFunction()}] = dependency;
802807
});
803808
}
804809

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,8 +1944,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
19441944
"archetype from the substitutions list");
19451945

19461946
bool matchedDependencyResult = false;
1947-
DI->forEachDefinedLocalArchetype(
1948-
[&](CanLocalArchetypeType archetype, SILValue dependency) {
1947+
DI->forEachDefinedLocalEnvironment(
1948+
[&](GenericEnvironment *genericEnv, SILValue dependency) {
19491949
if (dependency == V)
19501950
matchedDependencyResult = true;
19511951
});

0 commit comments

Comments
 (0)