@@ -6105,6 +6105,21 @@ class SwitchLookupTable {
6105
6105
static bool WouldFitInRegister (const DataLayout &DL, uint64_t TableSize,
6106
6106
Type *ElementType);
6107
6107
6108
+ static SmallVector<Constant *, 64 > buildTableContents (
6109
+ uint64_t TableSize, ConstantInt *Offset,
6110
+ const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6111
+ Constant *DefaultValue);
6112
+ static bool
6113
+ canBeSingleValueKind (const SmallVectorImpl<Constant *> &TableContents);
6114
+ static bool
6115
+ canBeLinearMapKind (const SmallVectorImpl<Constant *> &TableContents,
6116
+ bool &NonMonotonic, APInt &DistToPrev);
6117
+ static bool canBeBitMapKind (const SmallVectorImpl<Constant *> &TableContents,
6118
+ const DataLayout &DL);
6119
+ static bool
6120
+ canOnlyFallbackToArrayKind (const SmallVectorImpl<Constant *> &TableContents,
6121
+ const DataLayout &DL);
6122
+
6108
6123
private:
6109
6124
// Depending on the contents of the table, it can be represented in
6110
6125
// different ways.
@@ -6150,97 +6165,36 @@ SwitchLookupTable::SwitchLookupTable(
6150
6165
Module &M, uint64_t TableSize, ConstantInt *Offset,
6151
6166
const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6152
6167
Constant *DefaultValue, const DataLayout &DL, const StringRef &FuncName) {
6153
- assert (Values.size () && " Can't build lookup table without values!" );
6154
- assert (TableSize >= Values.size () && " Can't fit values in table!" );
6155
-
6156
- // If all values in the table are equal, this is that value.
6157
- SingleValue = Values.begin ()->second ;
6158
-
6159
- Type *ValueType = Values.begin ()->second ->getType ();
6160
-
6161
6168
// Build up the table contents.
6162
- SmallVector<Constant *, 64 > TableContents (TableSize);
6163
- for (size_t I = 0 , E = Values.size (); I != E; ++I) {
6164
- ConstantInt *CaseVal = Values[I].first ;
6165
- Constant *CaseRes = Values[I].second ;
6166
- assert (CaseRes->getType () == ValueType);
6167
-
6168
- uint64_t Idx = (CaseVal->getValue () - Offset->getValue ()).getLimitedValue ();
6169
- TableContents[Idx] = CaseRes;
6170
-
6171
- if (CaseRes != SingleValue)
6172
- SingleValue = nullptr ;
6173
- }
6174
-
6175
- // Fill in any holes in the table with the default result.
6176
- if (Values.size () < TableSize) {
6177
- assert (DefaultValue &&
6178
- " Need a default value to fill the lookup table holes." );
6179
- assert (DefaultValue->getType () == ValueType);
6180
- for (uint64_t I = 0 ; I < TableSize; ++I) {
6181
- if (!TableContents[I])
6182
- TableContents[I] = DefaultValue;
6183
- }
6184
-
6185
- if (DefaultValue != SingleValue)
6186
- SingleValue = nullptr ;
6187
- }
6169
+ SmallVector<Constant *, 64 > TableContents =
6170
+ buildTableContents (TableSize, Offset, Values, DefaultValue);
6188
6171
6189
6172
// If each element in the table contains the same value, we only need to store
6190
6173
// that single value.
6191
- if (SingleValue) {
6174
+ if (canBeSingleValueKind (TableContents)) {
6175
+ SingleValue = TableContents[0 ];
6192
6176
Kind = SingleValueKind;
6193
6177
return ;
6194
6178
}
6195
-
6196
- // Check if we can derive the value with a linear transformation from the
6197
- // table index.
6198
- if (isa<IntegerType>(ValueType)) {
6199
- bool LinearMappingPossible = true ;
6200
- APInt PrevVal;
6201
- APInt DistToPrev;
6202
- // When linear map is monotonic and signed overflow doesn't happen on
6203
- // maximum index, we can attach nsw on Add and Mul.
6204
- bool NonMonotonic = false ;
6205
- assert (TableSize >= 2 && " Should be a SingleValue table." );
6206
- // Check if there is the same distance between two consecutive values.
6207
- for (uint64_t I = 0 ; I < TableSize; ++I) {
6208
- ConstantInt *ConstVal = dyn_cast<ConstantInt>(TableContents[I]);
6209
- if (!ConstVal) {
6210
- // This is an undef. We could deal with it, but undefs in lookup tables
6211
- // are very seldom. It's probably not worth the additional complexity.
6212
- LinearMappingPossible = false ;
6213
- break ;
6214
- }
6215
- const APInt &Val = ConstVal->getValue ();
6216
- if (I != 0 ) {
6217
- APInt Dist = Val - PrevVal;
6218
- if (I == 1 ) {
6219
- DistToPrev = Dist;
6220
- } else if (Dist != DistToPrev) {
6221
- LinearMappingPossible = false ;
6222
- break ;
6223
- }
6224
- NonMonotonic |=
6225
- Dist.isStrictlyPositive () ? Val.sle (PrevVal) : Val.sgt (PrevVal);
6226
- }
6227
- PrevVal = Val;
6228
- }
6229
- if (LinearMappingPossible) {
6230
- LinearOffset = cast<ConstantInt>(TableContents[0 ]);
6231
- LinearMultiplier = ConstantInt::get (M.getContext (), DistToPrev);
6232
- bool MayWrap = false ;
6233
- APInt M = LinearMultiplier->getValue ();
6234
- (void )M.smul_ov (APInt (M.getBitWidth (), TableSize - 1 ), MayWrap);
6235
- LinearMapValWrapped = NonMonotonic || MayWrap;
6236
- Kind = LinearMapKind;
6237
- ++NumLinearMaps;
6238
- return ;
6239
- }
6179
+ // When linear map is monotonic and signed overflow doesn't happen on
6180
+ // maximum index, we can attach nsw on Add and Mul.
6181
+ bool NonMonotonic = false ;
6182
+ APInt DistToPrev;
6183
+ if (canBeLinearMapKind (TableContents, NonMonotonic, DistToPrev)) {
6184
+ LinearOffset = cast<ConstantInt>(TableContents[0 ]);
6185
+ LinearMultiplier = ConstantInt::get (M.getContext (), DistToPrev);
6186
+ bool MayWrap = false ;
6187
+ APInt M = LinearMultiplier->getValue ();
6188
+ (void )M.smul_ov (APInt (M.getBitWidth (), TableSize - 1 ), MayWrap);
6189
+ LinearMapValWrapped = NonMonotonic || MayWrap;
6190
+ Kind = LinearMapKind;
6191
+ ++NumLinearMaps;
6192
+ return ;
6240
6193
}
6241
6194
6195
+ Type *ValueType = Values.begin ()->second ->getType ();
6242
6196
// If the type is integer and the table fits in a register, build a bitmap.
6243
- if (WouldFitInRegister (DL, TableSize, ValueType )) {
6197
+ if (canBeBitMapKind (TableContents, DL )) {
6244
6198
IntegerType *IT = cast<IntegerType>(ValueType);
6245
6199
APInt TableInt (TableSize * IT->getBitWidth (), 0 );
6246
6200
for (uint64_t I = TableSize; I > 0 ; --I) {
@@ -6349,6 +6303,110 @@ bool SwitchLookupTable::WouldFitInRegister(const DataLayout &DL,
6349
6303
return DL.fitsInLegalInteger (TableSize * IT->getBitWidth ());
6350
6304
}
6351
6305
6306
+ SmallVector<Constant *, 64 > SwitchLookupTable::buildTableContents (
6307
+ uint64_t TableSize, ConstantInt *Offset,
6308
+ const SmallVectorImpl<std::pair<ConstantInt *, Constant *>> &Values,
6309
+ Constant *DefaultValue) {
6310
+ assert (Values.size () && " Can't build lookup table without values!" );
6311
+ assert (TableSize >= Values.size () && " Can't fit values in table!" );
6312
+
6313
+ Type *ValueType = Values.begin ()->second ->getType ();
6314
+
6315
+ // Build up the table contents.
6316
+ SmallVector<Constant *, 64 > TableContents (TableSize);
6317
+ for (size_t I = 0 , E = Values.size (); I != E; ++I) {
6318
+ ConstantInt *CaseVal = Values[I].first ;
6319
+ Constant *CaseRes = Values[I].second ;
6320
+ assert (CaseRes->getType () == ValueType);
6321
+
6322
+ uint64_t Idx = (CaseVal->getValue () - Offset->getValue ()).getLimitedValue ();
6323
+ TableContents[Idx] = CaseRes;
6324
+ }
6325
+
6326
+ // Fill in any holes in the table with the default result.
6327
+ if (Values.size () < TableSize) {
6328
+ assert (DefaultValue &&
6329
+ " Need a default value to fill the lookup table holes." );
6330
+ assert (DefaultValue->getType () == ValueType);
6331
+ for (uint64_t I = 0 ; I < TableSize; ++I) {
6332
+ if (!TableContents[I])
6333
+ TableContents[I] = DefaultValue;
6334
+ }
6335
+ }
6336
+ return TableContents;
6337
+ }
6338
+
6339
+ bool SwitchLookupTable::canBeSingleValueKind (
6340
+ const SmallVectorImpl<Constant *> &TableContents) {
6341
+ // If all values in the table are equal, this is that value.
6342
+ const Constant *SingleValue = TableContents[0 ];
6343
+ for (const Constant *Value : TableContents) {
6344
+ if (Value != SingleValue)
6345
+ return false ;
6346
+ }
6347
+ return true ;
6348
+ }
6349
+
6350
+ bool SwitchLookupTable::canBeLinearMapKind (
6351
+ const SmallVectorImpl<Constant *> &TableContents, bool &NonMonotonic,
6352
+ APInt &DistToPrev) {
6353
+ Type *ValueType = TableContents[0 ]->getType ();
6354
+ // Check if we can derive the value with a linear transformation from the
6355
+ // table index.
6356
+ if (!isa<IntegerType>(ValueType))
6357
+ return false ;
6358
+ bool LinearMappingPossible = true ;
6359
+ APInt PrevVal;
6360
+ auto TableSize = TableContents.size ();
6361
+
6362
+ // When linear map is monotonic and signed overflow doesn't happen on
6363
+ // maximum index, we can attach nsw on Add and Mul.
6364
+ assert (TableSize >= 2 && " Should be a SingleValue table." );
6365
+ // Check if there is the same distance between two consecutive values.
6366
+ for (uint64_t I = 0 ; I < TableSize; ++I) {
6367
+ ConstantInt *ConstVal = dyn_cast<ConstantInt>(TableContents[I]);
6368
+ if (!ConstVal) {
6369
+ // This is an undef. We could deal with it, but undefs in lookup tables
6370
+ // are very seldom. It's probably not worth the additional complexity.
6371
+ LinearMappingPossible = false ;
6372
+ break ;
6373
+ }
6374
+ const APInt &Val = ConstVal->getValue ();
6375
+ if (I != 0 ) {
6376
+ APInt Dist = Val - PrevVal;
6377
+ if (I == 1 ) {
6378
+ DistToPrev = Dist;
6379
+ } else if (Dist != DistToPrev) {
6380
+ LinearMappingPossible = false ;
6381
+ break ;
6382
+ }
6383
+ NonMonotonic |=
6384
+ Dist.isStrictlyPositive () ? Val.sle (PrevVal) : Val.sgt (PrevVal);
6385
+ }
6386
+ PrevVal = Val;
6387
+ }
6388
+ return LinearMappingPossible;
6389
+ }
6390
+
6391
+ bool SwitchLookupTable::canBeBitMapKind (
6392
+ const SmallVectorImpl<Constant *> &TableContents, const DataLayout &DL) {
6393
+ return WouldFitInRegister (DL, TableContents.size (),
6394
+ TableContents[0 ]->getType ());
6395
+ }
6396
+
6397
+ bool SwitchLookupTable::canOnlyFallbackToArrayKind (
6398
+ const SmallVectorImpl<Constant *> &TableContents, const DataLayout &DL) {
6399
+ if (canBeSingleValueKind (TableContents))
6400
+ return false ;
6401
+ bool NonMonotonic = false ;
6402
+ APInt DistToPrev;
6403
+ if (canBeLinearMapKind (TableContents, NonMonotonic, DistToPrev))
6404
+ return false ;
6405
+ if (canBeBitMapKind (TableContents, DL))
6406
+ return false ;
6407
+ return true ;
6408
+ }
6409
+
6352
6410
static bool isTypeLegalForLookupTable (Type *Ty, const TargetTransformInfo &TTI,
6353
6411
const DataLayout &DL) {
6354
6412
// Allow any legal type.
@@ -6662,6 +6720,42 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
6662
6720
Module &Mod = *CommonDest->getParent ()->getParent ();
6663
6721
BasicBlock *LookupBB = BasicBlock::Create (
6664
6722
Mod.getContext (), " switch.lookup" , CommonDest->getParent (), CommonDest);
6723
+ // If we are generating a covered lookup table, try to find an index that
6724
+ // doesn't create an array of values.
6725
+ // TODO: We could more expensive check, and choose the index with the best sum
6726
+ // of all kinds.
6727
+ if (MaxTableSize == TableSize && TableSize * PHIs.size () <= 128 ) {
6728
+ for (uint64_t Offset = 0 ; Offset < TableSize; Offset++) {
6729
+ auto *TableIndexOffset =
6730
+ ConstantInt::get (MaxCaseVal->getIntegerType (), Offset);
6731
+ bool CanOnlyFallbackToArrayKind = false ;
6732
+ for (PHINode *PHI : PHIs) {
6733
+ const ResultListTy &ResultList = ResultLists[PHI];
6734
+
6735
+ // If using a bitmask, use any value to fill the lookup table holes.
6736
+ Constant *DV =
6737
+ NeedMask ? ResultLists[PHI][0 ].second : DefaultResults[PHI];
6738
+ SmallVector<Constant *, 64 > TableContents =
6739
+ SwitchLookupTable::buildTableContents (TableSize, TableIndexOffset,
6740
+ ResultList, DV);
6741
+ if (SwitchLookupTable::canOnlyFallbackToArrayKind (TableContents, DL)) {
6742
+ CanOnlyFallbackToArrayKind = true ;
6743
+ break ;
6744
+ }
6745
+ }
6746
+ if (!CanOnlyFallbackToArrayKind) {
6747
+ if (Offset == 0 )
6748
+ UseSwitchConditionAsTableIndex = true ;
6749
+ MinCaseVal = TableIndexOffset;
6750
+ APInt One (TableIndexOffset->getValue ().getBitWidth (), 1 );
6751
+ bool Overflow = false ;
6752
+ MaxCaseVal = cast<ConstantInt>(ConstantInt::get (
6753
+ MaxCaseVal->getType (),
6754
+ TableIndexOffset->getValue ().usub_ov (One, Overflow)));
6755
+ break ;
6756
+ }
6757
+ }
6758
+ }
6665
6759
6666
6760
// Compute the table index value.
6667
6761
Builder.SetInsertPoint (SI);
0 commit comments