@@ -6479,52 +6479,11 @@ class UncheckedTakeEnumDataAddrInst
6479
6479
}
6480
6480
};
6481
6481
6482
- // Abstract base class of all select instructions like select_enum.
6483
- // The template parameter represents a type of case values
6484
- // to be compared with the operand of a select instruction.
6485
- //
6486
- // Subclasses must provide tail allocated storage.
6487
- // The first operand is the operand of select_xxx instruction. The rest of
6488
- // the operands are the case values and results of a select instruction.
6489
- template <class Derived , class T , class Base = SingleValueInstruction>
6490
- class SelectInstBase : public Base {
6491
- public:
6492
- template <typename ... Args>
6493
- SelectInstBase (SILInstructionKind kind, SILDebugLocation Loc, SILType type,
6494
- Args &&... otherArgs)
6495
- : Base(kind, Loc, type, std::forward<Args>(otherArgs)...) {}
6496
-
6497
- SILValue getOperand () const { return getAllOperands ()[0 ].get (); }
6498
-
6499
- ArrayRef<Operand> getAllOperands () const {
6500
- return static_cast <const Derived *>(this )->getAllOperands ();
6501
- }
6502
- MutableArrayRef<Operand> getAllOperands () {
6503
- return static_cast <Derived *>(this )->getAllOperands ();
6504
- }
6505
-
6506
- std::pair<T, SILValue> getCase (unsigned i) const {
6507
- return static_cast <const Derived *>(this )->getCase (i);
6508
- }
6509
-
6510
- unsigned getNumCases () const {
6511
- return static_cast <const Derived *>(this )->getNumCases ();
6512
- }
6513
-
6514
- bool hasDefault () const {
6515
- return static_cast <const Derived *>(this )->hasDefault ();
6516
- }
6517
-
6518
- SILValue getDefaultResult () const {
6519
- return static_cast <const Derived *>(this )->getDefaultResult ();
6520
- }
6521
- };
6522
-
6523
6482
// / Common base class for the select_enum and select_enum_addr instructions,
6524
6483
// / which select one of a set of possible results based on the case of an enum.
6525
- class SelectEnumInstBase
6526
- : public SelectInstBase<SelectEnumInstBase, EnumElementDecl *> {
6527
- USE_SHARED_UINT8 ;
6484
+ template < typename DerivedTy, typename BaseTy>
6485
+ class SelectEnumInstBase : public BaseTy {
6486
+ TEMPLATE_USE_SHARED_UINT8 (BaseTy) ;
6528
6487
6529
6488
// Tail-allocated after the operands is an array of `NumCases`
6530
6489
// EnumElementDecl* pointers, referencing the case discriminators for each
@@ -6536,20 +6495,22 @@ class SelectEnumInstBase
6536
6495
}
6537
6496
6538
6497
protected:
6498
+ template <typename ... Rest>
6539
6499
SelectEnumInstBase (SILInstructionKind kind, SILDebugLocation debugLoc,
6540
6500
SILType type, bool defaultValue,
6541
6501
llvm::Optional<ArrayRef<ProfileCounter>> CaseCounts,
6542
- ProfileCounter DefaultCount)
6543
- : SelectInstBase (kind, debugLoc, type) {
6502
+ ProfileCounter DefaultCount, Rest &&...rest )
6503
+ : BaseTy (kind, debugLoc, type, std::forward<Rest>(rest)... ) {
6544
6504
sharedUInt8 ().SelectEnumInstBase .hasDefault = defaultValue;
6545
6505
}
6546
- template <typename SELECT_ENUM_INST>
6547
- static SELECT_ENUM_INST *createSelectEnum (
6548
- SILDebugLocation DebugLoc, SILValue Enum, SILType Type,
6549
- SILValue DefaultValue,
6550
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues, SILModule &M,
6551
- llvm::Optional<ArrayRef<ProfileCounter>> CaseCounts,
6552
- ProfileCounter DefaultCount, ValueOwnershipKind forwardingOwnershipKind);
6506
+ template <typename ... RestTys>
6507
+ static DerivedTy *
6508
+ createSelectEnum (SILDebugLocation DebugLoc, SILValue Enum, SILType Type,
6509
+ SILValue DefaultValue,
6510
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
6511
+ SILModule &M,
6512
+ llvm::Optional<ArrayRef<ProfileCounter>> CaseCounts,
6513
+ ProfileCounter DefaultCount, RestTys &&...restArgs);
6553
6514
6554
6515
public:
6555
6516
ArrayRef<Operand> getAllOperands () const ;
@@ -6576,9 +6537,6 @@ class SelectEnumInstBase
6576
6537
// didn't find anything.
6577
6538
return getDefaultResult ();
6578
6539
}
6579
-
6580
- // / If the default refers to exactly one case decl, return it.
6581
- NullablePtr<EnumElementDecl> getUniqueCaseForDefault ();
6582
6540
6583
6541
bool hasDefault () const {
6584
6542
return sharedUInt8 ().SelectEnumInstBase .hasDefault ;
@@ -6593,58 +6551,82 @@ class SelectEnumInstBase
6593
6551
return getAllOperands ().size () - 1 - hasDefault ();
6594
6552
}
6595
6553
6554
+ // / If the default refers to exactly one case decl, return it.
6555
+ NullablePtr<EnumElementDecl> getUniqueCaseForDefault () {
6556
+ assert (this ->hasDefault () && " doesn't have a default" );
6557
+ auto enumValue = getEnumOperand ();
6558
+ SILType enumType = enumValue->getType ();
6559
+
6560
+ EnumDecl *decl = enumType.getEnumOrBoundGenericEnum ();
6561
+ assert (decl && " switch_enum operand is not an enum" );
6562
+
6563
+ if (!enumType.isEffectivelyExhaustiveEnumType (this ->getFunction ())) {
6564
+ return nullptr ;
6565
+ }
6566
+
6567
+ llvm::SmallPtrSet<EnumElementDecl *, 4 > unswitchedElts;
6568
+ for (auto elt : decl->getAllElements ())
6569
+ unswitchedElts.insert (elt);
6570
+
6571
+ for (unsigned i = 0 , e = this ->getNumCases (); i != e; ++i) {
6572
+ auto Entry = this ->getCase (i);
6573
+ unswitchedElts.erase (Entry.first );
6574
+ }
6575
+
6576
+ if (unswitchedElts.size () == 1 )
6577
+ return *unswitchedElts.begin ();
6578
+
6579
+ return nullptr ;
6580
+ }
6581
+
6596
6582
// / If there is a single case that returns a literal "true" value (an
6597
6583
// / "integer_literal $Builtin.Int1, 1" value), return it.
6598
6584
// /
6599
6585
// / FIXME: This is used to interoperate with passes that reasoned about the
6600
6586
// / old enum_is_tag insn. Ideally those passes would become general enough
6601
6587
// / not to need this.
6602
- NullablePtr<EnumElementDecl> getSingleTrueElement () const ;
6603
- };
6604
-
6605
- // / A select enum inst that produces a static OwnershipKind.
6606
- class OwnershipForwardingSelectEnumInstBase : public SelectEnumInstBase ,
6607
- public ForwardingInstruction {
6608
- protected:
6609
- OwnershipForwardingSelectEnumInstBase (
6610
- SILInstructionKind kind, SILDebugLocation debugLoc, SILType type,
6611
- bool defaultValue, llvm::Optional<ArrayRef<ProfileCounter>> caseCounts,
6612
- ProfileCounter defaultCount, ValueOwnershipKind ownershipKind)
6613
- : SelectEnumInstBase(kind, debugLoc, type, defaultValue, caseCounts,
6614
- defaultCount),
6615
- ForwardingInstruction (kind, ownershipKind) {
6616
- assert (classof (kind) && " classof missing subclass" );
6617
- }
6618
-
6619
- public:
6620
- static bool classof (SILNodePointer node) {
6621
- if (auto *i = dyn_cast<SILInstruction>(node.get ()))
6622
- return classof (i);
6623
- return false ;
6624
- }
6625
-
6626
- static bool classof (const SILInstruction *i) { return classof (i->getKind ()); }
6588
+ NullablePtr<EnumElementDecl> getSingleTrueElement () const {
6589
+ auto SEIType = static_cast <const DerivedTy *>(this )
6590
+ ->getType ()
6591
+ .template getAs <BuiltinIntegerType>();
6592
+ if (!SEIType)
6593
+ return nullptr ;
6594
+ if (SEIType->getWidth () != BuiltinIntegerWidth::fixed (1 ))
6595
+ return nullptr ;
6627
6596
6628
- static bool classof (SILInstructionKind kind) {
6629
- switch (kind) {
6630
- case SILInstructionKind::SelectEnumInst:
6631
- return true ;
6632
- default :
6633
- return false ;
6597
+ // Try to find a single literal "true" case.
6598
+ llvm::Optional<EnumElementDecl *> TrueElement;
6599
+ for (unsigned i = 0 , e = getNumCases (); i < e; ++i) {
6600
+ auto casePair = getCase (i);
6601
+ if (auto intLit = dyn_cast<IntegerLiteralInst>(casePair.second )) {
6602
+ if (intLit->getValue () == APInt (1 , 1 )) {
6603
+ if (!TrueElement)
6604
+ TrueElement = casePair.first ;
6605
+ else
6606
+ // Use Optional(nullptr) to represent more than one.
6607
+ TrueElement = llvm::Optional<EnumElementDecl *>(nullptr );
6608
+ }
6609
+ }
6634
6610
}
6611
+
6612
+ if (!TrueElement || !*TrueElement)
6613
+ return nullptr ;
6614
+ return *TrueElement;
6635
6615
}
6636
6616
};
6637
6617
6638
6618
// / Select one of a set of values based on the case of an enum.
6639
6619
class SelectEnumInst final
6640
6620
: public InstructionBaseWithTrailingOperands<
6641
6621
SILInstructionKind::SelectEnumInst, SelectEnumInst,
6642
- OwnershipForwardingSelectEnumInstBase, EnumElementDecl *> {
6622
+ SelectEnumInstBase<SelectEnumInst,
6623
+ OwnershipForwardingSingleValueInstruction>,
6624
+ EnumElementDecl *> {
6643
6625
friend SILBuilder;
6626
+ friend SelectEnumInstBase<SelectEnumInst,
6627
+ OwnershipForwardingSingleValueInstruction>;
6644
6628
6645
- private:
6646
- friend SelectEnumInstBase;
6647
-
6629
+ public:
6648
6630
SelectEnumInst (SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
6649
6631
bool DefaultValue, ArrayRef<SILValue> CaseValues,
6650
6632
ArrayRef<EnumElementDecl *> CaseDecls,
@@ -6671,20 +6653,20 @@ class SelectEnumInst final
6671
6653
class SelectEnumAddrInst final
6672
6654
: public InstructionBaseWithTrailingOperands<
6673
6655
SILInstructionKind::SelectEnumAddrInst, SelectEnumAddrInst,
6674
- SelectEnumInstBase, EnumElementDecl *> {
6656
+ SelectEnumInstBase<SelectEnumAddrInst, SingleValueInstruction>,
6657
+ EnumElementDecl *> {
6675
6658
friend SILBuilder;
6676
- friend SelectEnumInstBase;
6659
+ friend SelectEnumInstBase<SelectEnumAddrInst, SingleValueInstruction> ;
6677
6660
6661
+ public:
6678
6662
SelectEnumAddrInst (SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
6679
6663
bool DefaultValue, ArrayRef<SILValue> CaseValues,
6680
6664
ArrayRef<EnumElementDecl *> CaseDecls,
6681
6665
llvm::Optional<ArrayRef<ProfileCounter>> CaseCounts,
6682
- ProfileCounter DefaultCount,
6683
- ValueOwnershipKind forwardingOwnershipKind)
6666
+ ProfileCounter DefaultCount)
6684
6667
: InstructionBaseWithTrailingOperands(Operand, CaseValues, DebugLoc, Type,
6685
6668
bool (DefaultValue), CaseCounts,
6686
6669
DefaultCount) {
6687
- (void )forwardingOwnershipKind;
6688
6670
assert (CaseValues.size () - DefaultValue == CaseDecls.size ());
6689
6671
std::uninitialized_copy (CaseDecls.begin (), CaseDecls.end (),
6690
6672
getTrailingObjects<EnumElementDecl *>());
@@ -10528,6 +10510,7 @@ OwnershipForwardingSingleValueInstruction::classof(SILInstructionKind kind) {
10528
10510
case SILInstructionKind::BridgeObjectToRefInst:
10529
10511
case SILInstructionKind::ThinToThickFunctionInst:
10530
10512
case SILInstructionKind::UnconditionalCheckedCastInst:
10513
+ case SILInstructionKind::SelectEnumInst:
10531
10514
return true ;
10532
10515
default :
10533
10516
return false ;
@@ -10755,31 +10738,25 @@ inline MutableArrayRef<Operand> AllocRefInstBase::getAllOperands() {
10755
10738
llvm_unreachable (" Unhandled AllocRefInstBase subclass" );
10756
10739
}
10757
10740
10758
- inline ArrayRef<Operand> SelectEnumInstBase::getAllOperands () const {
10759
- // If the size of the subclasses are equal, then all of this compiles away.
10760
- if (auto I = dyn_cast<SelectEnumInst>(this ))
10761
- return I->getAllOperands ();
10762
- if (auto I = dyn_cast<SelectEnumAddrInst>(this ))
10763
- return I->getAllOperands ();
10764
- llvm_unreachable (" Unhandled SelectEnumInstBase subclass" );
10741
+ template <typename DerivedTy, typename BaseTy>
10742
+ inline ArrayRef<Operand>
10743
+ SelectEnumInstBase<DerivedTy, BaseTy>::getAllOperands() const {
10744
+ const auto &I = static_cast <const DerivedTy &>(*this );
10745
+ return I.getAllOperands ();
10765
10746
}
10766
10747
10767
- inline MutableArrayRef<Operand> SelectEnumInstBase::getAllOperands () {
10768
- // If the size of the subclasses are equal, then all of this compiles away.
10769
- if (auto I = dyn_cast<SelectEnumInst>(this ))
10770
- return I->getAllOperands ();
10771
- if (auto I = dyn_cast<SelectEnumAddrInst>(this ))
10772
- return I->getAllOperands ();
10773
- llvm_unreachable (" Unhandled SelectEnumInstBase subclass" );
10748
+ template <typename DerivedTy, typename BaseTy>
10749
+ inline MutableArrayRef<Operand>
10750
+ SelectEnumInstBase<DerivedTy, BaseTy>::getAllOperands() {
10751
+ auto &I = static_cast <DerivedTy &>(*this );
10752
+ return I.getAllOperands ();
10774
10753
}
10775
10754
10776
- inline EnumElementDecl **SelectEnumInstBase::getEnumElementDeclStorage () {
10777
- // If the size of the subclasses are equal, then all of this compiles away.
10778
- if (auto I = dyn_cast<SelectEnumInst>(this ))
10779
- return I->getTrailingObjects <EnumElementDecl*>();
10780
- if (auto I = dyn_cast<SelectEnumAddrInst>(this ))
10781
- return I->getTrailingObjects <EnumElementDecl*>();
10782
- llvm_unreachable (" Unhandled SelectEnumInstBase subclass" );
10755
+ template <typename DerivedTy, typename BaseTy>
10756
+ inline EnumElementDecl **
10757
+ SelectEnumInstBase<DerivedTy, BaseTy>::getEnumElementDeclStorage() {
10758
+ auto &I = static_cast <DerivedTy &>(*this );
10759
+ return I.template getTrailingObjects <EnumElementDecl *>();
10783
10760
}
10784
10761
10785
10762
inline void SILSuccessor::pred_iterator::cacheBasicBlock () {
@@ -10799,7 +10776,6 @@ inline bool Operand::isTypeDependent() const {
10799
10776
inline bool ForwardingInstruction::isa (SILInstructionKind kind) {
10800
10777
return OwnershipForwardingSingleValueInstruction::classof (kind) ||
10801
10778
OwnershipForwardingTermInst::classof (kind) ||
10802
- OwnershipForwardingSelectEnumInstBase::classof (kind) ||
10803
10779
OwnershipForwardingMultipleValueInstruction::classof (kind);
10804
10780
}
10805
10781
@@ -10812,8 +10788,6 @@ inline ForwardingInstruction *ForwardingInstruction::get(SILInstruction *inst) {
10812
10788
return result;
10813
10789
if (auto *result = dyn_cast<OwnershipForwardingTermInst>(inst))
10814
10790
return result;
10815
- if (auto *result = dyn_cast<OwnershipForwardingSelectEnumInstBase>(inst))
10816
- return result;
10817
10791
if (auto *result =
10818
10792
dyn_cast<OwnershipForwardingMultipleValueInstruction>(inst))
10819
10793
return result;
0 commit comments