[llvm-commits] [llvm] r164684 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/switch_to_lookup_table.ll
Duncan Sands
baldrick at free.fr
Wed Sep 26 05:17:50 PDT 2012
Hi Hans,
> SimplifyCFG: Make the switch-to-lookup table transformation store the
> tables in bitmaps when they fit in a target-legal register.
very nice.
> --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Wed Sep 26 04:44:49 2012
> @@ -60,6 +60,7 @@
>
> STATISTIC(NumSpeculations, "Number of speculative executed instructions");
> STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables");
> +STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
> STATISTIC(NumSinkCommons, "Number of common instructions sunk down to the end block");
Not in alphabetical order (very nitpicky I know!).
>
> namespace {
> @@ -3283,7 +3300,8 @@
> uint64_t TableSize,
> ConstantInt *Offset,
> const SmallVector<std::pair<ConstantInt*, Constant*>, 4>& Values,
> - Constant *DefaultValue) {
> + Constant *DefaultValue,
> + const TargetData *TD) {
> assert(Values.size() && "Can't build lookup table without values.");
> assert(TableSize >= Values.size() && "Can't fit values in table.");
>
> @@ -3323,6 +3341,21 @@
> return;
> }
>
> + // If the type is integer and the table fits in a register, build a bitmap.
> + if (WouldFitInRegister(TD, TableSize, DefaultValue->getType())) {
> + IntegerType *IT = cast<IntegerType>(DefaultValue->getType());
> + APInt TableInt(TableSize * IT->getBitWidth(), 0);
> + for (uint64_t I = TableSize; I > 0; --I) {
> + TableInt <<= IT->getBitWidth();
> + TableInt |= cast<ConstantInt>(TableContents[I - 1])->getZExtValue();
This getZextValue may crash on a (future) target with 128 bit registers. Why
not just use apints all the way:
TableInt |= cast<ConstantInt>(TableContents[I -
1])->getValue().zext(TableInt.getBitWidth());
?
> + }
> + BitMap = ConstantInt::get(M.getContext(), TableInt);
> + BitMapElementTy = IT;
> + Kind = BitMapKind;
> + ++NumBitMaps;
> + return;
> + }
> +
> // Store the table in an array.
> ArrayType *ArrayTy = ArrayType::get(DefaultValue->getType(), TableSize);
> Constant *Initializer = ConstantArray::get(ArrayTy, TableContents);
> @@ -3339,6 +3372,32 @@
> switch (Kind) {
> case SingleValueKind:
> return SingleValue;
> + case BitMapKind: {
> + // Type of the bitmap (e.g. i59).
> + IntegerType *MapTy = BitMap->getType();
> +
> + // Cast Index to the same type as the bitmap.
> + // Note: The Index is <= the number of elements in the table, so
> + // truncating it to the width of the bitmask is safe.
> + Value *ShiftAmt = Index;
> + IntegerType *IndexTy = cast<IntegerType>(Index->getType());
> + if (IndexTy->getBitWidth() < MapTy->getBitWidth())
> + ShiftAmt = Builder.CreateZExt(ShiftAmt, MapTy, "switch.zext");
> + else if (IndexTy->getBitWidth() > MapTy->getBitWidth())
> + ShiftAmt = Builder.CreateTrunc(ShiftAmt, MapTy, "switch.trunc");
How about adding a CreateZExtOrTrunc method to IRBuilder and using that
instead (in which case please add CreateSExtOrTrunc too)?
Otherwise LGTM.
Ciao, Duncan.
More information about the llvm-commits
mailing list