@@ -7437,31 +7437,34 @@ static bool simplifySwitchOfCmpIntrinsic(SwitchInst *SI, IRBuilderBase &Builder,
74377437 return true ;
74387438}
74397439
7440- // / Checking whether two CaseHandle.getCaseSuccessor() are equal depends on
7441- // / the BasicBlock and the incoming values of their successor PHINodes.
7440+ // / Checking whether two cases of SI are equal depends on the contents of the
7441+ // / BasicBlock and the incoming values of their successor PHINodes.
74427442// / PHINode::getIncomingValueForBlock is O(|Preds|), so we'd like to avoid
74437443// / calling this function on each BasicBlock every time isEqual is called,
74447444// / especially since the same BasicBlock may be passed as an argument multiple
74457445// / times. To do this, we can precompute a map of PHINode -> Pred BasicBlock ->
74467446// / IncomingValue and add it in the Wrapper so isEqual can do O(1) checking
74477447// / of the incoming values.
7448- struct CaseHandleWrapper {
7449- const SwitchInst::CaseHandle Case;
7448+ struct SwitchSuccWrapper {
7449+ // Keep so we can use SwitchInst::setSuccessor to do the replacement. It won't
7450+ // be important to equality though.
7451+ unsigned SuccNum;
7452+ BasicBlock *Dest;
74507453 DenseMap<PHINode *, DenseMap<BasicBlock *, Value *>> *PhiPredIVs;
74517454};
74527455
74537456namespace llvm {
7454- template <> struct DenseMapInfo <const CaseHandleWrapper *> {
7455- static const CaseHandleWrapper *getEmptyKey () {
7456- return static_cast <CaseHandleWrapper *>(
7457+ template <> struct DenseMapInfo <const SwitchSuccWrapper *> {
7458+ static const SwitchSuccWrapper *getEmptyKey () {
7459+ return static_cast <SwitchSuccWrapper *>(
74577460 DenseMapInfo<void *>::getEmptyKey ());
74587461 }
7459- static const CaseHandleWrapper *getTombstoneKey () {
7460- return static_cast <CaseHandleWrapper *>(
7462+ static const SwitchSuccWrapper *getTombstoneKey () {
7463+ return static_cast <SwitchSuccWrapper *>(
74617464 DenseMapInfo<void *>::getTombstoneKey ());
74627465 }
7463- static unsigned getHashValue (const CaseHandleWrapper *CHW ) {
7464- BasicBlock *Succ = CHW-> Case . getCaseSuccessor () ;
7466+ static unsigned getHashValue (const SwitchSuccWrapper *SSW ) {
7467+ BasicBlock *Succ = SSW-> Dest ;
74657468 BranchInst *BI = cast<BranchInst>(Succ->getTerminator ());
74667469 assert (BI->isUnconditional () &&
74677470 " Only supporting unconditional branches for now" );
@@ -7475,26 +7478,26 @@ template <> struct DenseMapInfo<const CaseHandleWrapper *> {
74757478 // this had poor performance. We find that the extra computation of getting
74767479 // the incoming PHI values here leads to better performance on overall Set
74777480 // performance. We also tried to build a map from BB -> Succs.IncomingValues
7478- // ahead of time and passing it in CaseHandleWrapper , but this slowed down
7481+ // ahead of time and passing it in SwitchSuccWrapper , but this slowed down
74797482 // the average compile time without having any impact on the worst case
74807483 // compile time.
74817484 BasicBlock *BB = BI->getSuccessor (0 );
74827485 SmallVector<Value *> PhiValsForBB;
74837486 for (PHINode &Phi : BB->phis ())
7484- PhiValsForBB.emplace_back ((*CHW ->PhiPredIVs )[&Phi][BB]);
7487+ PhiValsForBB.emplace_back ((*SSW ->PhiPredIVs )[&Phi][BB]);
74857488
74867489 return hash_combine (
74877490 BB, hash_combine_range (PhiValsForBB.begin (), PhiValsForBB.end ()));
74887491 }
7489- static bool isEqual (const CaseHandleWrapper *LHS,
7490- const CaseHandleWrapper *RHS) {
7491- auto EKey = DenseMapInfo<CaseHandleWrapper *>::getEmptyKey ();
7492- auto TKey = DenseMapInfo<CaseHandleWrapper *>::getTombstoneKey ();
7492+ static bool isEqual (const SwitchSuccWrapper *LHS,
7493+ const SwitchSuccWrapper *RHS) {
7494+ auto EKey = DenseMapInfo<SwitchSuccWrapper *>::getEmptyKey ();
7495+ auto TKey = DenseMapInfo<SwitchSuccWrapper *>::getTombstoneKey ();
74937496 if (LHS == EKey || RHS == EKey || LHS == TKey || RHS == TKey)
74947497 return LHS == RHS;
74957498
7496- BasicBlock *A = LHS->Case . getCaseSuccessor () ;
7497- BasicBlock *B = RHS->Case . getCaseSuccessor () ;
7499+ BasicBlock *A = LHS->Dest ;
7500+ BasicBlock *B = RHS->Dest ;
74987501
74997502 // FIXME: we checked that the size of A and B are both 1 in
75007503 // simplifyDuplicateSwitchArms to make the Case list smaller to
@@ -7535,10 +7538,11 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75357538 SmallPtrSet<PHINode *, 8 > Phis;
75367539 SmallPtrSet<BasicBlock *, 8 > Seen;
75377540 DenseMap<PHINode *, DenseMap<BasicBlock *, Value *>> PhiPredIVs;
7538- SmallVector<CaseHandleWrapper > Cases;
7541+ SmallVector<SwitchSuccWrapper > Cases;
75397542 Cases.reserve (SI->getNumCases ());
7540- for (auto &Case : SI->cases ()) {
7541- BasicBlock *BB = Case.getCaseSuccessor ();
7543+
7544+ for (unsigned I = 0 ; I < SI->getNumSuccessors (); ++I) {
7545+ BasicBlock *BB = SI->getSuccessor (I);
75427546
75437547 // FIXME: Support more than just a single BranchInst. One way we could do
75447548 // this is by taking a hashing approach of all insts in BB.
@@ -7567,11 +7571,11 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75677571 for (PHINode &Phi : Succ->phis ())
75687572 Phis.insert (&Phi);
75697573 }
7570- Cases.emplace_back (CaseHandleWrapper{Case , &PhiPredIVs});
7574+ Cases.emplace_back (SwitchSuccWrapper{I, BB , &PhiPredIVs});
75717575 }
75727576
75737577 // Precompute a data structure to improve performance of isEqual for
7574- // CaseHandleWrapper .
7578+ // SwitchSuccWrapper .
75757579 PhiPredIVs.reserve (Phis.size ());
75767580 for (PHINode *Phi : Phis) {
75777581 PhiPredIVs[Phi] =
@@ -7580,36 +7584,36 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75807584 PhiPredIVs[Phi].insert ({Phi->getIncomingBlock (IV), IV.get ()});
75817585 }
75827586
7583- // Build a set such that if the CaseHandleWrapper exists in the set and
7584- // another CaseHandleWrapper isEqual, then the equivalent CaseHandleWrapper
7587+ // Build a set such that if the SwitchSuccWrapper exists in the set and
7588+ // another SwitchSuccWrapper isEqual, then the equivalent SwitchSuccWrapper
75857589 // which is not in the set should be replaced with the one in the set. If the
7586- // CaseHandleWrapper is not in the set, then it should be added to the set so
7587- // other CaseHandleWrappers can check against it in the same manner. We chose
7588- // to use CaseHandleWrapper instead of BasicBlock since we'd need an extra
7589- // nested loop since there is no O(1) lookup of BasicBlock -> Cases in
7590- // SwichInst .
7591- DenseSet<const CaseHandleWrapper *, DenseMapInfo<const CaseHandleWrapper *>>
7590+ // SwitchSuccWrapper is not in the set, then it should be added to the set so
7591+ // other SwitchSuccWrappers can check against it in the same manner. We use
7592+ // SwitchSuccWrapper instead of just BasicBlock because we'd like to pass
7593+ // around information to isEquality, getHashValue, and when doing the
7594+ // replacement with better performance .
7595+ DenseSet<const SwitchSuccWrapper *, DenseMapInfo<const SwitchSuccWrapper *>>
75927596 ReplaceWith;
75937597 ReplaceWith.reserve (Cases.size ());
75947598
7595- bool MadeChange = false ;
75967599 SmallVector<DominatorTree::UpdateType> Updates;
75977600 Updates.reserve (ReplaceWith.size ());
7598- for (auto &CHW : Cases) {
7599- // CHW is a candidate for simplification. If we find a duplicate BB,
7601+ bool MadeChange = false ;
7602+ for (auto &SSW : Cases) {
7603+ // SSW is a candidate for simplification. If we find a duplicate BB,
76007604 // replace it.
7601- const auto [It, Inserted] = ReplaceWith.insert (&CHW );
7605+ const auto [It, Inserted] = ReplaceWith.insert (&SSW );
76027606 if (!Inserted) {
76037607 // We know that SI's parent BB no longer dominates the old case successor
76047608 // since we are making it dead.
7605- Updates.push_back ({DominatorTree::Delete, SI->getParent (),
7606- CHW.Case .getCaseSuccessor ()});
7607- CHW.Case .setSuccessor ((*It)->Case .getCaseSuccessor ());
7609+ Updates.push_back ({DominatorTree::Delete, SI->getParent (), SSW.Dest });
7610+ SI->setSuccessor (SSW.SuccNum , (*It)->Dest );
76087611 MadeChange = true ;
76097612 } else {
7610- ReplaceWith.insert (&CHW );
7613+ ReplaceWith.insert (&SSW );
76117614 }
76127615 }
7616+
76137617 if (DTU)
76147618 DTU->applyUpdates (Updates);
76157619
0 commit comments