@@ -5718,15 +5718,49 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
57185718 return Changed;
57195719}
57205720
5721- static bool casesAreContiguous (SmallVectorImpl<ConstantInt *> &Cases) {
5721+ static bool casesAreContiguous (Value *Condition,
5722+ SmallVectorImpl<ConstantInt *> &Cases,
5723+ ConstantInt *&ContiguousCasesMin,
5724+ ConstantInt *&ContiguousCasesMax,
5725+ bool &IsWrapping) {
57225726 assert (Cases.size () >= 1 );
57235727
57245728 array_pod_sort (Cases.begin (), Cases.end (), constantIntSortPredicate);
5725- for (size_t I = 1 , E = Cases.size (); I != E; ++I) {
5726- if (Cases[I - 1 ]->getValue () != Cases[I]->getValue () + 1 )
5729+ auto Min = Cases.back ()->getValue ();
5730+ auto Max = Cases.front ()->getValue ();
5731+ auto Offset = Max - Min;
5732+ auto ContiguousOffset = Cases.size () - 1 ;
5733+ if (Offset == ContiguousOffset) {
5734+ ContiguousCasesMin = Cases.back ();
5735+ ContiguousCasesMax = Cases.front ();
5736+ return true ;
5737+ }
5738+ ConstantRange CR = computeConstantRange (Condition, /* ForSigned=*/ false );
5739+ // If this is a wrapping contiguous range, that is, [Min, OtherMin] +
5740+ // [OtherMax, Max] (also [OtherMax, OtherMin]), [OtherMin+1, OtherMax-1] is a
5741+ // contiguous range for the other destination. N.B. If CR is not a full range,
5742+ // Max+1 is not equal to Min. It's not continuous in arithmetic.
5743+ if (Max == CR.getUnsignedMax () && Min == CR.getUnsignedMin ()) {
5744+ assert (Cases.size () >= 2 );
5745+ auto *It =
5746+ std::adjacent_find (Cases.begin (), Cases.end (), [](auto L, auto R) {
5747+ return L->getValue () != R->getValue () + 1 ;
5748+ });
5749+ if (It == Cases.end ())
57275750 return false ;
5751+ auto *OtherMax = *It;
5752+ auto *OtherMin = *(It + 1 );
5753+ if ((Max - OtherMax->getValue ()) + (OtherMin->getValue () - Min) ==
5754+ Cases.size () - 2 ) {
5755+ ContiguousCasesMin = cast<ConstantInt>(
5756+ ConstantInt::get (OtherMin->getType (), OtherMin->getValue () + 1 ));
5757+ ContiguousCasesMax = cast<ConstantInt>(
5758+ ConstantInt::get (OtherMax->getType (), OtherMax->getValue () - 1 ));
5759+ IsWrapping = true ;
5760+ return true ;
5761+ }
57285762 }
5729- return true ;
5763+ return false ;
57305764}
57315765
57325766static void createUnreachableSwitchDefault (SwitchInst *Switch,
@@ -5797,33 +5831,42 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
57975831 assert (!CasesA.empty () || HasDefault);
57985832
57995833 // Figure out if one of the sets of cases form a contiguous range.
5800- SmallVectorImpl<ConstantInt *> *ContiguousCases = nullptr ;
5834+ ConstantInt *ContiguousCasesMin = nullptr ;
5835+ ConstantInt *ContiguousCasesMax = nullptr ;
58015836 BasicBlock *ContiguousDest = nullptr ;
58025837 BasicBlock *OtherDest = nullptr ;
5803- if (!CasesA.empty () && casesAreContiguous (CasesA)) {
5804- ContiguousCases = &CasesA;
5838+ bool IsWrapping = false ;
5839+ if (!CasesA.empty () &&
5840+ casesAreContiguous (SI->getCondition (), CasesA, ContiguousCasesMin,
5841+ ContiguousCasesMax, IsWrapping)) {
58055842 ContiguousDest = DestA;
58065843 OtherDest = DestB;
5807- } else if (casesAreContiguous (CasesB)) {
5808- ContiguousCases = &CasesB;
5844+ } else if (casesAreContiguous (SI-> getCondition (), CasesB, ContiguousCasesMin,
5845+ ContiguousCasesMax, IsWrapping)) {
58095846 ContiguousDest = DestB;
58105847 OtherDest = DestA;
58115848 } else
58125849 return false ;
58135850
5851+ if (IsWrapping)
5852+ std::swap (ContiguousDest, OtherDest);
5853+
58145854 // Start building the compare and branch.
58155855
5816- Constant *Offset = ConstantExpr::getNeg (ContiguousCases->back ());
5817- Constant *NumCases =
5818- ConstantInt::get (Offset->getType (), ContiguousCases->size ());
5856+ auto ContiguousCasesSize =
5857+ (ContiguousCasesMax->getValue () - ContiguousCasesMin->getValue ())
5858+ .getZExtValue () +
5859+ 1 ;
5860+ Constant *Offset = ConstantExpr::getNeg (ContiguousCasesMin);
5861+ Constant *NumCases = ConstantInt::get (Offset->getType (), ContiguousCasesSize);
58195862
58205863 Value *Sub = SI->getCondition ();
58215864 if (!Offset->isNullValue ())
58225865 Sub = Builder.CreateAdd (Sub, Offset, Sub->getName () + " .off" );
58235866
58245867 Value *Cmp;
58255868 // If NumCases overflowed, then all possible values jump to the successor.
5826- if (NumCases->isNullValue () && !ContiguousCases-> empty () )
5869+ if (NumCases->isNullValue () && ContiguousCasesSize != 0 )
58275870 Cmp = ConstantInt::getTrue (SI->getContext ());
58285871 else
58295872 Cmp = Builder.CreateICmpULT (Sub, NumCases, " switch" );
@@ -5853,14 +5896,14 @@ bool SimplifyCFGOpt::turnSwitchRangeIntoICmp(SwitchInst *SI,
58535896
58545897 // Prune obsolete incoming values off the successors' PHI nodes.
58555898 for (auto BBI = ContiguousDest->begin (); isa<PHINode>(BBI); ++BBI) {
5856- unsigned PreviousEdges = ContiguousCases-> size () ;
5899+ unsigned PreviousEdges = ContiguousCasesSize ;
58575900 if (ContiguousDest == SI->getDefaultDest ())
58585901 ++PreviousEdges;
58595902 for (unsigned I = 0 , E = PreviousEdges - 1 ; I != E; ++I)
58605903 cast<PHINode>(BBI)->removeIncomingValue (SI->getParent ());
58615904 }
58625905 for (auto BBI = OtherDest->begin (); isa<PHINode>(BBI); ++BBI) {
5863- unsigned PreviousEdges = SI->getNumCases () - ContiguousCases-> size () ;
5906+ unsigned PreviousEdges = SI->getNumCases () - ContiguousCasesSize ;
58645907 if (OtherDest == SI->getDefaultDest ())
58655908 ++PreviousEdges;
58665909 for (unsigned I = 0 , E = PreviousEdges - 1 ; I != E; ++I)
0 commit comments