Skip to content

Commit 29374cb

Browse files
committed
SILOptimizer: Skip unreachable cases optimization when elements are available.
Cache a bit on `EnumDecl` indicating whether there are any elements that are unavailable during lowering and then use that bit to decided whether to attempt optimization for `switch_enum`/`switch_enum_addr` instructions.
1 parent be02038 commit 29374cb

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,13 +650,16 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
650650
/// address diversified ptrauth qualified field.
651651
IsNonTrivialPtrAuth : 1);
652652

653-
SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+1,
653+
SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+1+1,
654654
/// True if the enum has cases and at least one case has associated values.
655655
HasAssociatedValues : 2,
656656
/// True if the enum has at least one case that has some availability
657657
/// attribute. A single bit because it's lazily computed along with the
658658
/// HasAssociatedValues bit.
659-
HasAnyUnavailableValues : 1
659+
HasAnyUnavailableValues : 1,
660+
/// True if \c isAvailableDuringLowering() is false for any cases. Lazily
661+
/// computed along with HasAssociatedValues.
662+
HasAnyUnavailableDuringLoweringValues : 1
660663
);
661664

662665
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1,
@@ -4294,6 +4297,11 @@ class EnumDecl final : public NominalTypeDecl {
42944297
/// Note that this is false for enums with absolutely no cases.
42954298
bool hasPotentiallyUnavailableCaseValue() const;
42964299

4300+
/// True if \c isAvailableDuringLowering() is false for any cases.
4301+
///
4302+
/// Note that this is false for enums with absolutely no cases.
4303+
bool hasCasesUnavailableDuringLowering() const;
4304+
42974305
/// True if the enum has cases.
42984306
bool hasCases() const {
42994307
return !getAllElements().empty();

lib/AST/Decl.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5945,12 +5945,23 @@ EnumCaseDecl *EnumCaseDecl::create(SourceLoc CaseLoc,
59455945

59465946
bool EnumDecl::hasPotentiallyUnavailableCaseValue() const {
59475947
switch (static_cast<AssociatedValueCheck>(Bits.EnumDecl.HasAssociatedValues)) {
5948-
case AssociatedValueCheck::Unchecked:
5949-
// Compute below
5950-
this->hasOnlyCasesWithoutAssociatedValues();
5951-
LLVM_FALLTHROUGH;
5952-
default:
5953-
return static_cast<bool>(Bits.EnumDecl.HasAnyUnavailableValues);
5948+
case AssociatedValueCheck::Unchecked:
5949+
this->hasOnlyCasesWithoutAssociatedValues();
5950+
LLVM_FALLTHROUGH;
5951+
default:
5952+
return static_cast<bool>(Bits.EnumDecl.HasAnyUnavailableValues);
5953+
}
5954+
}
5955+
5956+
bool EnumDecl::hasCasesUnavailableDuringLowering() const {
5957+
switch (
5958+
static_cast<AssociatedValueCheck>(Bits.EnumDecl.HasAssociatedValues)) {
5959+
case AssociatedValueCheck::Unchecked:
5960+
this->hasOnlyCasesWithoutAssociatedValues();
5961+
LLVM_FALLTHROUGH;
5962+
default:
5963+
return static_cast<bool>(
5964+
Bits.EnumDecl.HasAnyUnavailableDuringLoweringValues);
59545965
}
59555966
}
59565967

@@ -5970,6 +5981,7 @@ bool EnumDecl::hasOnlyCasesWithoutAssociatedValues() const {
59705981
}
59715982

59725983
bool hasAnyUnavailableValues = false;
5984+
bool hasAnyUnavailableDuringLoweringValues = false;
59735985
bool hasAssociatedValues = false;
59745986

59755987
for (auto elt : getAllElements()) {
@@ -5980,13 +5992,18 @@ bool EnumDecl::hasOnlyCasesWithoutAssociatedValues() const {
59805992
}
59815993
}
59825994

5995+
if (!elt->isAvailableDuringLowering())
5996+
hasAnyUnavailableDuringLoweringValues = true;
5997+
59835998
if (elt->hasAssociatedValues())
59845999
hasAssociatedValues = true;
59856000
}
59866001

59876002
EnumDecl *enumDecl = const_cast<EnumDecl *>(this);
59886003

59896004
enumDecl->Bits.EnumDecl.HasAnyUnavailableValues = hasAnyUnavailableValues;
6005+
enumDecl->Bits.EnumDecl.HasAnyUnavailableDuringLoweringValues =
6006+
hasAnyUnavailableDuringLoweringValues;
59906007
enumDecl->Bits.EnumDecl.HasAssociatedValues = static_cast<unsigned>(
59916008
hasAssociatedValues ? AssociatedValueCheck::HasAssociatedValues
59926009
: AssociatedValueCheck::NoAssociatedValues);

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,8 +890,12 @@ static bool eliminateSwitchDispatchOnUnavailableElements(
890890
if (!SWI)
891891
return false;
892892

893-
// FIXME: Return early if EnumDecl doesn't have any elements that are
894-
// unavailable.
893+
EnumDecl *ED = SWI->getOperand(0)->getType().getEnumOrBoundGenericEnum();
894+
assert(ED && "operand is not an enum");
895+
896+
// No need to check the instruction if all elements are available.
897+
if (!ED->hasCasesUnavailableDuringLowering())
898+
return false;
895899

896900
ASTContext &ctx = BB.getModule().getASTContext();
897901
SILLocation Loc = SWI->getLoc();

0 commit comments

Comments
 (0)