@@ -6186,6 +6186,21 @@ class SwitchLookupTable {
6186
6186
static bool WouldFitInRegister (const DataLayout &DL, uint64_t TableSize,
6187
6187
Type *ElementType);
6188
6188
6189
+ static SmallVector<Constant *, 64 > buildTableContents (
6190
+ uint64_t TableSize, ConstantInt *Offset,
6191
+ const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6192
+ Constant *DefaultValue);
6193
+ static bool
6194
+ canBeSingleValueKind (const SmallVectorImpl<Constant *> &TableContents);
6195
+ static bool
6196
+ canBeLinearMapKind (const SmallVectorImpl<Constant *> &TableContents,
6197
+ bool &NonMonotonic, APInt &DistToPrev);
6198
+ static bool canBeBitMapKind (const SmallVectorImpl<Constant *> &TableContents,
6199
+ const DataLayout &DL);
6200
+ static bool
6201
+ canOnlyFallbackToArrayKind (const SmallVectorImpl<Constant *> &TableContents,
6202
+ const DataLayout &DL);
6203
+
6189
6204
private:
6190
6205
// Depending on the contents of the table, it can be represented in
6191
6206
// different ways.
@@ -6231,97 +6246,36 @@ SwitchLookupTable::SwitchLookupTable(
6231
6246
Module &M, uint64_t TableSize, ConstantInt *Offset,
6232
6247
const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6233
6248
Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName) {
6234
- assert (Values.size () && " Can't build lookup table without values!" );
6235
- assert (TableSize >= Values.size () && " Can't fit values in table!" );
6236
-
6237
- // If all values in the table are equal, this is that value.
6238
- SingleValue = Values.begin ()->second ;
6239
-
6240
- Type *ValueType = Values.begin ()->second ->getType ();
6241
-
6242
6249
// Build up the table contents.
6243
- SmallVector<Constant *, 64 > TableContents (TableSize);
6244
- for (size_t I = 0 , E = Values.size (); I != E; ++I) {
6245
- ConstantInt *CaseVal = Values[I].first ;
6246
- Constant *CaseRes = Values[I].second ;
6247
- assert (CaseRes->getType () == ValueType);
6248
-
6249
- uint64_t Idx = (CaseVal->getValue () - Offset->getValue ()).getLimitedValue ();
6250
- TableContents[Idx] = CaseRes;
6251
-
6252
- if (CaseRes != SingleValue)
6253
- SingleValue = nullptr ;
6254
- }
6255
-
6256
- // Fill in any holes in the table with the default result.
6257
- if (Values.size () < TableSize) {
6258
- assert (DefaultValue &&
6259
- " Need a default value to fill the lookup table holes." );
6260
- assert (DefaultValue->getType () == ValueType);
6261
- for (uint64_t I = 0 ; I < TableSize; ++I) {
6262
- if (!TableContents[I])
6263
- TableContents[I] = DefaultValue;
6264
- }
6265
-
6266
- if (DefaultValue != SingleValue)
6267
- SingleValue = nullptr ;
6268
- }
6250
+ SmallVector<Constant *, 64 > TableContents =
6251
+ buildTableContents (TableSize, Offset, Values, DefaultValue);
6269
6252
6270
6253
// If each element in the table contains the same value, we only need to store
6271
6254
// that single value.
6272
- if (SingleValue) {
6255
+ if (canBeSingleValueKind (TableContents)) {
6256
+ SingleValue = TableContents[0 ];
6273
6257
Kind = SingleValueKind;
6274
6258
return ;
6275
6259
}
6276
-
6277
- // Check if we can derive the value with a linear transformation from the
6278
- // table index.
6279
- if (isa<IntegerType>(ValueType)) {
6280
- bool LinearMappingPossible = true ;
6281
- APInt PrevVal;
6282
- APInt DistToPrev;
6283
- // When linear map is monotonic and signed overflow doesn't happen on
6284
- // maximum index, we can attach nsw on Add and Mul.
6285
- bool NonMonotonic = false ;
6286
- assert (TableSize >= 2 && " Should be a SingleValue table." );
6287
- // Check if there is the same distance between two consecutive values.
6288
- for (uint64_t I = 0 ; I < TableSize; ++I) {
6289
- ConstantInt *ConstVal = dyn_cast<ConstantInt>(TableContents[I]);
6290
- if (!ConstVal) {
6291
- // This is an undef. We could deal with it, but undefs in lookup tables
6292
- // are very seldom. It's probably not worth the additional complexity.
6293
- LinearMappingPossible = false ;
6294
- break ;
6295
- }
6296
- const APInt &Val = ConstVal->getValue ();
6297
- if (I != 0 ) {
6298
- APInt Dist = Val - PrevVal;
6299
- if (I == 1 ) {
6300
- DistToPrev = Dist;
6301
- } else if (Dist != DistToPrev) {
6302
- LinearMappingPossible = false ;
6303
- break ;
6304
- }
6305
- NonMonotonic |=
6306
- Dist.isStrictlyPositive () ? Val.sle (PrevVal) : Val.sgt (PrevVal);
6307
- }
6308
- PrevVal = Val;
6309
- }
6310
- if (LinearMappingPossible) {
6311
- LinearOffset = cast<ConstantInt>(TableContents[0 ]);
6312
- LinearMultiplier = ConstantInt::get (M.getContext (), DistToPrev);
6313
- bool MayWrap = false ;
6314
- APInt M = LinearMultiplier->getValue ();
6315
- (void )M.smul_ov (APInt (M.getBitWidth (), TableSize - 1 ), MayWrap);
6316
- LinearMapValWrapped = NonMonotonic || MayWrap;
6317
- Kind = LinearMapKind;
6318
- ++NumLinearMaps;
6319
- return ;
6320
- }
6260
+ // When linear map is monotonic and signed overflow doesn't happen on
6261
+ // maximum index, we can attach nsw on Add and Mul.
6262
+ bool NonMonotonic = false ;
6263
+ APInt DistToPrev;
6264
+ if (canBeLinearMapKind (TableContents, NonMonotonic, DistToPrev)) {
6265
+ LinearOffset = cast<ConstantInt>(TableContents[0 ]);
6266
+ LinearMultiplier = ConstantInt::get (M.getContext (), DistToPrev);
6267
+ bool MayWrap = false ;
6268
+ APInt M = LinearMultiplier->getValue ();
6269
+ (void )M.smul_ov (APInt (M.getBitWidth (), TableSize - 1 ), MayWrap);
6270
+ LinearMapValWrapped = NonMonotonic || MayWrap;
6271
+ Kind = LinearMapKind;
6272
+ ++NumLinearMaps;
6273
+ return ;
6321
6274
}
6322
6275
6276
+ Type *ValueType = Values.begin ()->second ->getType ();
6323
6277
// If the type is integer and the table fits in a register, build a bitmap.
6324
- if (WouldFitInRegister (DL, TableSize, ValueType )) {
6278
+ if (canBeBitMapKind (TableContents, DL )) {
6325
6279
IntegerType *IT = cast<IntegerType>(ValueType);
6326
6280
APInt TableInt (TableSize * IT->getBitWidth (), 0 );
6327
6281
for (uint64_t I = TableSize; I > 0 ; --I) {
@@ -6430,6 +6384,110 @@ bool SwitchLookupTable::WouldFitInRegister(const DataLayout &DL,
6430
6384
return DL.fitsInLegalInteger (TableSize * IT->getBitWidth ());
6431
6385
}
6432
6386
6387
+ SmallVector<Constant *, 64 > SwitchLookupTable::buildTableContents (
6388
+ uint64_t TableSize, ConstantInt *Offset,
6389
+ const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6390
+ Constant *DefaultValue) {
6391
+ assert (Values.size () && " Can't build lookup table without values!" );
6392
+ assert (TableSize >= Values.size () && " Can't fit values in table!" );
6393
+
6394
+ Type *ValueType = Values.begin ()->second ->getType ();
6395
+
6396
+ // Build up the table contents.
6397
+ SmallVector<Constant *, 64 > TableContents (TableSize);
6398
+ for (size_t I = 0 , E = Values.size (); I != E; ++I) {
6399
+ ConstantInt *CaseVal = Values[I].first ;
6400
+ Constant *CaseRes = Values[I].second ;
6401
+ assert (CaseRes->getType () == ValueType);
6402
+
6403
+ uint64_t Idx = (CaseVal->getValue () - Offset->getValue ()).getLimitedValue ();
6404
+ TableContents[Idx] = CaseRes;
6405
+ }
6406
+
6407
+ // Fill in any holes in the table with the default result.
6408
+ if (Values.size () < TableSize) {
6409
+ assert (DefaultValue &&
6410
+ " Need a default value to fill the lookup table holes." );
6411
+ assert (DefaultValue->getType () == ValueType);
6412
+ for (uint64_t I = 0 ; I < TableSize; ++I) {
6413
+ if (!TableContents[I])
6414
+ TableContents[I] = DefaultValue;
6415
+ }
6416
+ }
6417
+ return TableContents;
6418
+ }
6419
+
6420
+ bool SwitchLookupTable::canBeSingleValueKind (
6421
+ const SmallVectorImpl<Constant *> &TableContents) {
6422
+ // If all values in the table are equal, this is that value.
6423
+ const Constant *SingleValue = TableContents[0 ];
6424
+ for (const Constant *Value : TableContents) {
6425
+ if (Value != SingleValue)
6426
+ return false ;
6427
+ }
6428
+ return true ;
6429
+ }
6430
+
6431
+ bool SwitchLookupTable::canBeLinearMapKind (
6432
+ const SmallVectorImpl<Constant *> &TableContents, bool &NonMonotonic,
6433
+ APInt &DistToPrev) {
6434
+ Type *ValueType = TableContents[0 ]->getType ();
6435
+ // Check if we can derive the value with a linear transformation from the
6436
+ // table index.
6437
+ if (!isa<IntegerType>(ValueType))
6438
+ return false ;
6439
+ bool LinearMappingPossible = true ;
6440
+ APInt PrevVal;
6441
+ auto TableSize = TableContents.size ();
6442
+
6443
+ // When linear map is monotonic and signed overflow doesn't happen on
6444
+ // maximum index, we can attach nsw on Add and Mul.
6445
+ assert (TableSize >= 2 && " Should be a SingleValue table." );
6446
+ // Check if there is the same distance between two consecutive values.
6447
+ for (uint64_t I = 0 ; I < TableSize; ++I) {
6448
+ ConstantInt *ConstVal = dyn_cast<ConstantInt>(TableContents[I]);
6449
+ if (!ConstVal) {
6450
+ // This is an undef. We could deal with it, but undefs in lookup tables
6451
+ // are very seldom. It's probably not worth the additional complexity.
6452
+ LinearMappingPossible = false ;
6453
+ break ;
6454
+ }
6455
+ const APInt &Val = ConstVal->getValue ();
6456
+ if (I != 0 ) {
6457
+ APInt Dist = Val - PrevVal;
6458
+ if (I == 1 ) {
6459
+ DistToPrev = Dist;
6460
+ } else if (Dist != DistToPrev) {
6461
+ LinearMappingPossible = false ;
6462
+ break ;
6463
+ }
6464
+ NonMonotonic |=
6465
+ Dist.isStrictlyPositive () ? Val.sle (PrevVal) : Val.sgt (PrevVal);
6466
+ }
6467
+ PrevVal = Val;
6468
+ }
6469
+ return LinearMappingPossible;
6470
+ }
6471
+
6472
+ bool SwitchLookupTable::canBeBitMapKind (
6473
+ const SmallVectorImpl<Constant *> &TableContents, const DataLayout &DL) {
6474
+ return WouldFitInRegister (DL, TableContents.size (),
6475
+ TableContents[0 ]->getType ());
6476
+ }
6477
+
6478
+ bool SwitchLookupTable::canOnlyFallbackToArrayKind (
6479
+ const SmallVectorImpl<Constant *> &TableContents, const DataLayout &DL) {
6480
+ if (canBeSingleValueKind (TableContents))
6481
+ return false ;
6482
+ bool NonMonotonic = false ;
6483
+ APInt DistToPrev;
6484
+ if (canBeLinearMapKind (TableContents, NonMonotonic, DistToPrev))
6485
+ return false ;
6486
+ if (canBeBitMapKind (TableContents, DL))
6487
+ return false ;
6488
+ return true ;
6489
+ }
6490
+
6433
6491
static bool isTypeLegalForLookupTable (Type *Ty, const TargetTransformInfo &TTI,
6434
6492
const DataLayout &DL) {
6435
6493
// Allow any legal type.
@@ -6743,6 +6801,42 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
6743
6801
Module &Mod = *CommonDest->getParent ()->getParent ();
6744
6802
BasicBlock *LookupBB = BasicBlock::Create (
6745
6803
Mod.getContext (), " switch.lookup" , CommonDest->getParent (), CommonDest);
6804
+ // If we are generating a covered lookup table, try to find an index that
6805
+ // doesn't create an array of values.
6806
+ // TODO: We could more expensive check, and choose the index with the best sum
6807
+ // of all kinds.
6808
+ if (MaxTableSize == TableSize && TableSize * PHIs.size () <= 128 ) {
6809
+ for (uint64_t Offset = 0 ; Offset < TableSize; Offset++) {
6810
+ auto *TableIndexOffset =
6811
+ ConstantInt::get (MaxCaseVal->getIntegerType (), Offset);
6812
+ bool CanOnlyFallbackToArrayKind = false ;
6813
+ for (PHINode *PHI : PHIs) {
6814
+ const ResultListTy &ResultList = ResultLists[PHI];
6815
+
6816
+ // If using a bitmask, use any value to fill the lookup table holes.
6817
+ Constant *DV =
6818
+ NeedMask ? ResultLists[PHI][0 ].second : DefaultResults[PHI];
6819
+ SmallVector<Constant *, 64 > TableContents =
6820
+ SwitchLookupTable::buildTableContents (TableSize, TableIndexOffset,
6821
+ ResultList, DV);
6822
+ if (SwitchLookupTable::canOnlyFallbackToArrayKind (TableContents, DL)) {
6823
+ CanOnlyFallbackToArrayKind = true ;
6824
+ break ;
6825
+ }
6826
+ }
6827
+ if (!CanOnlyFallbackToArrayKind) {
6828
+ if (Offset == 0 )
6829
+ UseSwitchConditionAsTableIndex = true ;
6830
+ MinCaseVal = TableIndexOffset;
6831
+ APInt One (TableIndexOffset->getValue ().getBitWidth (), 1 );
6832
+ bool Overflow = false ;
6833
+ MaxCaseVal = cast<ConstantInt>(ConstantInt::get (
6834
+ MaxCaseVal->getType (),
6835
+ TableIndexOffset->getValue ().usub_ov (One, Overflow)));
6836
+ break ;
6837
+ }
6838
+ }
6839
+ }
6746
6840
6747
6841
// Compute the table index value.
6748
6842
Builder.SetInsertPoint (SI);
0 commit comments