@@ -6435,18 +6435,20 @@ ShouldBuildLookupTable(SwitchInst *SI, uint64_t TableSize,
64356435}
64366436
64376437static bool ShouldUseSwitchConditionAsTableIndex (
6438- ConstantInt &MinCaseVal , const ConstantInt &MaxCaseVal ,
6438+ const ConstantInt &BeginCaseVal , const ConstantInt &EndCaseVal ,
64396439 bool HasDefaultResults, const SmallDenseMap<PHINode *, Type *> &ResultTypes,
64406440 const DataLayout &DL, const TargetTransformInfo &TTI) {
6441- if (MinCaseVal .isNullValue ())
6441+ if (BeginCaseVal .isNullValue ())
64426442 return true ;
6443- if (MinCaseVal.isNegative () ||
6444- MaxCaseVal.getLimitedValue () == std::numeric_limits<uint64_t >::max () ||
6443+ if (BeginCaseVal.getValue ().sge (EndCaseVal.getValue ()))
6444+ return false ;
6445+ if (BeginCaseVal.isNegative () ||
6446+ EndCaseVal.getLimitedValue () == std::numeric_limits<uint64_t >::max () ||
64456447 !HasDefaultResults)
64466448 return false ;
64476449 return all_of (ResultTypes, [&](const auto &KV) {
64486450 return SwitchLookupTable::WouldFitInRegister (
6449- DL, MaxCaseVal .getLimitedValue () + 1 /* TableSize */ ,
6451+ DL, EndCaseVal .getLimitedValue () + 1 /* TableSize */ ,
64506452 KV.second /* ResultType */ );
64516453 });
64526454}
@@ -6537,7 +6539,8 @@ static void reuseTableCompare(
65376539// / lookup tables.
65386540static bool SwitchToLookupTable (SwitchInst *SI, IRBuilder<> &Builder,
65396541 DomTreeUpdater *DTU, const DataLayout &DL,
6540- const TargetTransformInfo &TTI) {
6542+ const TargetTransformInfo &TTI,
6543+ bool TryMinTableSize) {
65416544 assert (SI->getNumCases () > 1 && " Degenerate switch?" );
65426545
65436546 BasicBlock *BB = SI->getParent ();
@@ -6563,9 +6566,6 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
65636566 // Figure out the corresponding result for each case value and phi node in the
65646567 // common destination, as well as the min and max case values.
65656568 assert (!SI->cases ().empty ());
6566- SwitchInst::CaseIt CI = SI->case_begin ();
6567- ConstantInt *MinCaseVal = CI->getCaseValue ();
6568- ConstantInt *MaxCaseVal = CI->getCaseValue ();
65696569
65706570 BasicBlock *CommonDest = nullptr ;
65716571
@@ -6576,17 +6576,49 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
65766576 SmallDenseMap<PHINode *, Type *> ResultTypes;
65776577 SmallVector<PHINode *, 4 > PHIs;
65786578
6579- for (SwitchInst::CaseIt E = SI->case_end (); CI != E; ++CI) {
6580- ConstantInt *CaseVal = CI->getCaseValue ();
6581- if (CaseVal->getValue ().slt (MinCaseVal->getValue ()))
6582- MinCaseVal = CaseVal;
6583- if (CaseVal->getValue ().sgt (MaxCaseVal->getValue ()))
6584- MaxCaseVal = CaseVal;
6579+ SmallVector<ConstantInt *, 8 > CaseVals (llvm::map_range (
6580+ SI->cases (), [](const auto &C) { return C.getCaseValue (); }));
6581+
6582+ llvm::sort (CaseVals, [](const auto *L, const auto *R) {
6583+ return L->getValue ().slt (R->getValue ());
6584+ });
6585+ auto *CaseValIter = CaseVals.begin ();
6586+ ConstantInt *BeginCaseVal = *CaseValIter;
6587+ ConstantInt *EndCaseVal = CaseVals.back ();
6588+ bool RangeOverflow = false ;
6589+ uint64_t MinTableSize = EndCaseVal->getValue ()
6590+ .ssub_ov (BeginCaseVal->getValue (), RangeOverflow)
6591+ .getLimitedValue () +
6592+ 1 ;
6593+ // If there is no overflow, then this must be the minimal table.
6594+ // The signed max-min can no longer build a lookup table, so return.
6595+ if (RangeOverflow && TryMinTableSize) {
6596+ // We consider cases where the starting to the endpoint will cross the
6597+ // signed max and min. For example, for the i8 range `[-128, -127, 126,
6598+ // 127]`, we choose from 126 to -127. The length of the lookup table is 4.
6599+ while (CaseValIter != CaseVals.end ()) {
6600+ auto *CurCaseVal = *CaseValIter++;
6601+ if (CaseValIter == CaseVals.end ())
6602+ break ;
6603+ auto *NextCaseVal = *CaseValIter;
6604+ const auto &NextVal = NextCaseVal->getValue ();
6605+ const auto &CurVal = CurCaseVal->getValue ();
6606+ uint64_t RequireTableSize = (CurVal - NextVal).getLimitedValue () + 1 ;
6607+ if (RequireTableSize < MinTableSize) {
6608+ BeginCaseVal = NextCaseVal;
6609+ EndCaseVal = CurCaseVal;
6610+ MinTableSize = RequireTableSize;
6611+ }
6612+ }
6613+ }
6614+
6615+ for (const auto &CI : SI->cases ()) {
6616+ ConstantInt *CaseVal = CI.getCaseValue ();
65856617
65866618 // Resulting value at phi nodes for this case value.
65876619 using ResultsTy = SmallVector<std::pair<PHINode *, Constant *>, 4 >;
65886620 ResultsTy Results;
6589- if (!getCaseResults (SI, CaseVal, CI-> getCaseSuccessor (), &CommonDest,
6621+ if (!getCaseResults (SI, CaseVal, CI. getCaseSuccessor (), &CommonDest,
65906622 Results, DL, TTI))
65916623 return false ;
65926624
@@ -6621,13 +6653,12 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
66216653 }
66226654
66236655 bool UseSwitchConditionAsTableIndex = ShouldUseSwitchConditionAsTableIndex (
6624- *MinCaseVal , *MaxCaseVal , HasDefaultResults, ResultTypes, DL, TTI);
6656+ *BeginCaseVal , *EndCaseVal , HasDefaultResults, ResultTypes, DL, TTI);
66256657 uint64_t TableSize;
66266658 if (UseSwitchConditionAsTableIndex)
6627- TableSize = MaxCaseVal ->getLimitedValue () + 1 ;
6659+ TableSize = EndCaseVal ->getLimitedValue () + 1 ;
66286660 else
6629- TableSize =
6630- (MaxCaseVal->getValue () - MinCaseVal->getValue ()).getLimitedValue () + 1 ;
6661+ TableSize = MinTableSize;
66316662
66326663 bool TableHasHoles = (NumResults < TableSize);
66336664 bool NeedMask = (TableHasHoles && !HasDefaultResults);
@@ -6640,13 +6671,16 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
66406671 }
66416672
66426673 if (!ShouldBuildLookupTable (SI, TableSize, TTI, DL, ResultTypes))
6643- return false ;
6674+ // When a signed max-min cannot construct a lookup table, try to find a
6675+ // range with a minimal lookup table.
6676+ return !TryMinTableSize &&
6677+ SwitchToLookupTable (SI, Builder, DTU, DL, TTI, true );
66446678
66456679 std::vector<DominatorTree::UpdateType> Updates;
66466680
66476681 // Compute the maximum table size representable by the integer type we are
66486682 // switching upon.
6649- unsigned CaseSize = MinCaseVal ->getType ()->getPrimitiveSizeInBits ();
6683+ unsigned CaseSize = BeginCaseVal ->getType ()->getPrimitiveSizeInBits ();
66506684 uint64_t MaxTableSize = CaseSize > 63 ? UINT64_MAX : 1ULL << CaseSize;
66516685 assert (MaxTableSize >= TableSize &&
66526686 " It is impossible for a switch to have more entries than the max "
@@ -6668,15 +6702,17 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
66686702 Value *TableIndex;
66696703 ConstantInt *TableIndexOffset;
66706704 if (UseSwitchConditionAsTableIndex) {
6671- TableIndexOffset = ConstantInt::get (MaxCaseVal ->getIntegerType (), 0 );
6705+ TableIndexOffset = ConstantInt::get (EndCaseVal ->getIntegerType (), 0 );
66726706 TableIndex = SI->getCondition ();
66736707 } else {
6674- TableIndexOffset = MinCaseVal ;
6708+ TableIndexOffset = BeginCaseVal ;
66756709 // If the default is unreachable, all case values are s>= MinCaseVal. Then
66766710 // we can try to attach nsw.
66776711 bool MayWrap = true ;
6678- if (!DefaultIsReachable) {
6679- APInt Res = MaxCaseVal->getValue ().ssub_ov (MinCaseVal->getValue (), MayWrap);
6712+ if (!DefaultIsReachable &&
6713+ EndCaseVal->getValue ().sge (BeginCaseVal->getValue ())) {
6714+ APInt Res =
6715+ EndCaseVal->getValue ().ssub_ov (BeginCaseVal->getValue (), MayWrap);
66806716 (void )Res;
66816717 }
66826718
@@ -6717,7 +6753,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
67176753 // PHI value for the default case in case we're using a bit mask.
67186754 } else {
67196755 Value *Cmp = Builder.CreateICmpULT (
6720- TableIndex, ConstantInt::get (MinCaseVal ->getType (), TableSize));
6756+ TableIndex, ConstantInt::get (BeginCaseVal ->getType (), TableSize));
67216757 RangeCheckBranch =
67226758 Builder.CreateCondBr (Cmp, LookupBB, SI->getDefaultDest ());
67236759 if (DTU)
@@ -7032,7 +7068,7 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
70327068 // CVP. Therefore, only apply this transformation during late stages of the
70337069 // optimisation pipeline.
70347070 if (Options.ConvertSwitchToLookupTable &&
7035- SwitchToLookupTable (SI, Builder, DTU, DL, TTI))
7071+ SwitchToLookupTable (SI, Builder, DTU, DL, TTI, false ))
70367072 return requestResimplify ();
70377073
70387074 if (simplifySwitchOfPowersOfTwo (SI, Builder, DL, TTI))
0 commit comments