SIL: cache case indices in enum instructions.

As we do with field indices for struct instructions.
This avoids quadratic behavior in case of enums with lots of cases.
Also: cache field and enum case indices in the SILModule.
This commit is contained in:
Erik Eckstein
2022-05-15 17:24:22 +02:00
parent f4a1dac792
commit f3adbd5c0e
8 changed files with 184 additions and 77 deletions

View File

@@ -667,6 +667,48 @@ bool SILModule::hasUnresolvedOpenedArchetypeDefinitions() {
return numUnresolvedOpenedArchetypes != 0;
}
/// Get a unique index for a struct or class field in layout order.
unsigned SILModule::getFieldIndex(NominalTypeDecl *decl, VarDecl *field) {
auto iter = fieldIndices.find({decl, field});
if (iter != fieldIndices.end())
return iter->second;
unsigned index = 0;
if (auto *classDecl = dyn_cast<ClassDecl>(decl)) {
for (auto *superDecl = classDecl->getSuperclassDecl(); superDecl != nullptr;
superDecl = superDecl->getSuperclassDecl()) {
index += superDecl->getStoredProperties().size();
}
}
for (VarDecl *property : decl->getStoredProperties()) {
if (field == property) {
fieldIndices[{decl, field}] = index;
return index;
}
++index;
}
llvm_unreachable("The field decl for a struct_extract, struct_element_addr, "
"or ref_element_addr must be an accessible stored "
"property of the operand type");
}
unsigned SILModule::getCaseIndex(EnumElementDecl *enumElement) {
auto iter = enumCaseIndices.find(enumElement);
if (iter != enumCaseIndices.end())
return iter->second;
unsigned idx = 0;
for (EnumElementDecl *e : enumElement->getParentEnum()->getAllElements()) {
if (e == enumElement) {
enumCaseIndices[enumElement] = idx;
return idx;
}
++idx;
}
llvm_unreachable("enum element not found in enum decl");
}
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
if (const CanOpenedArchetypeType archeTy =