Skip to content

Commit 055d3fa

Browse files
committed
[SimplifyCFG] Truncate integer values in switch lookup tables if possible
Real-world switches often return integer values in a much smaller range than the actual range of the integer type being returned. This change enables us to detect when all integer values in a switch lookup table only differ from each other in a smaller subset of the possible bit positions, truncate the lookup table elements to a narrower width and extend them at runtime. This has two main benefits: - Reduces the memory footprint of lookup tables without additional runtime overhead (most architectures have zero-extending widening load instructions), resulting in smaller executable sizes and less cache pollution - Makes a many more lookup tables small enough to fit into a bitmap, eliminating the need for any loads
1 parent 5cc0170 commit 055d3fa

File tree

12 files changed

+288
-97
lines changed

12 files changed

+288
-97
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ static cl::opt<unsigned> MaxSwitchCasesPerResult(
196196
STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
197197
STATISTIC(NumLinearMaps,
198198
"Number of switch instructions turned into linear mapping");
199+
STATISTIC(NumTruncatedInts, "Number of switch instructions turned into lookup "
200+
"tables with a truncated value");
199201
STATISTIC(NumLookupTables,
200202
"Number of switch instructions turned into lookup tables");
201203
STATISTIC(
@@ -6486,6 +6488,13 @@ class SwitchLookupTable {
64866488
// shift and mask operations.
64876489
BitMapKind,
64886490

6491+
// For tables with integer elements which only differ in a small subset
6492+
// of their bits, we can truncate the values to a smaller type to discard
6493+
// the bits which are the same for all values, saving memory. Values are
6494+
// retrieved by retrieving the truncated value from a lookup table, then
6495+
// extending and OR-ing to re-construct the original values.
6496+
TruncatedIntKind,
6497+
64896498
// The table is stored as an array of values. Values are retrieved by load
64906499
// instructions from the table.
64916500
ArrayKind
@@ -6503,6 +6512,14 @@ class SwitchLookupTable {
65036512
ConstantInt *LinearMultiplier = nullptr;
65046513
bool LinearMapValWrapped = false;
65056514

6515+
// For TruncatedIntKind, these are the truncated lookup table and the
6516+
// constants used to reconstruct original values from their truncated forms.
6517+
std::unique_ptr<SwitchLookupTable> TruncatedLookupTable = nullptr;
6518+
IntegerType *TruncatedOrigTy = nullptr;
6519+
ConstantInt *TruncatedShift = nullptr;
6520+
ConstantInt *TruncatedMask = nullptr;
6521+
bool TruncatedValWrapped = false;
6522+
65066523
// For ArrayKind, this is the array.
65076524
GlobalVariable *Array = nullptr;
65086525
};
@@ -6622,6 +6639,132 @@ SwitchLookupTable::SwitchLookupTable(
66226639
return;
66236640
}
66246641

6642+
// Check if we can truncate the value to a smaller form by discarding leading
6643+
// and trailing bits which are the same for all values.
6644+
if (isa<IntegerType>(ValueType)) {
6645+
IntegerType *IT = cast<IntegerType>(ValueType);
6646+
unsigned OrigWidth = IT->getBitWidth();
6647+
6648+
// Figure out which bits are always the same.
6649+
APInt AlwaysOneBits = APInt::getAllOnes(OrigWidth);
6650+
APInt AlwaysZeroBits = APInt::getAllOnes(OrigWidth);
6651+
for (Constant *TableEntry : TableContents) {
6652+
// Each entry in the lookup table may be a constant integer, otherwise
6653+
// it must be undefined (Undef or poison) in which case we can simply
6654+
// skip it.
6655+
if (isa<ConstantInt>(TableEntry)) {
6656+
const APInt &Val = cast<ConstantInt>(TableEntry)->getValue();
6657+
AlwaysOneBits &= Val;
6658+
AlwaysZeroBits &= ~Val;
6659+
}
6660+
}
6661+
assert((AlwaysOneBits & AlwaysZeroBits).isZero() &&
6662+
"A bit cannot be both zero and one in every case");
6663+
APInt NotChangingBits = AlwaysOneBits | AlwaysZeroBits;
6664+
6665+
unsigned DiscardedHighBits = NotChangingBits.countLeadingOnes();
6666+
unsigned DiscardedLowBits = NotChangingBits.countTrailingOnes();
6667+
unsigned TotalDiscardedBits = DiscardedHighBits + DiscardedLowBits;
6668+
unsigned TruncatedWidth = OrigWidth - TotalDiscardedBits;
6669+
6670+
// If the original type's width is a power of two, we want to ensure
6671+
// that the truncated size is also a power of two. Otherwise, the higher
6672+
// cost of indexing into the array with non-power-of-two-sized elements is
6673+
// probably going to cancel out any benefits we might get from making the
6674+
// table smaller.
6675+
if (has_single_bit(OrigWidth)) {
6676+
unsigned OldTruncatedWidth = TruncatedWidth;
6677+
TruncatedWidth = bit_ceil(TruncatedWidth);
6678+
6679+
// If the truncated size increased, we need to decrease DiscardedHighBits
6680+
// and/or DiscardedLowBits accordingly.
6681+
unsigned TruncatedWidthIncrease = TruncatedWidth - OldTruncatedWidth;
6682+
if (TruncatedWidthIncrease) {
6683+
TotalDiscardedBits -= TruncatedWidthIncrease;
6684+
6685+
// Prioritize decreasing the number of least significant bits discarded:
6686+
// if we can get this to 0, we won't need to shift left
6687+
unsigned LowBitsDecrease =
6688+
std::min(TruncatedWidthIncrease, DiscardedLowBits);
6689+
DiscardedLowBits -= LowBitsDecrease;
6690+
6691+
unsigned HighBitsDecrease = std::min(
6692+
TruncatedWidthIncrease - LowBitsDecrease, DiscardedHighBits);
6693+
DiscardedHighBits -= HighBitsDecrease;
6694+
6695+
assert(TruncatedWidthIncrease == LowBitsDecrease + HighBitsDecrease);
6696+
6697+
assert(DiscardedHighBits + DiscardedLowBits == TotalDiscardedBits &&
6698+
TotalDiscardedBits + TruncatedWidth == OrigWidth);
6699+
}
6700+
}
6701+
6702+
// We'll only truncate the values if the truncated values would be less than
6703+
// half the size of the original values, as otherwise there's unlikely to be
6704+
// any benefit.
6705+
if (TruncatedWidth <= OrigWidth / 2) {
6706+
IntegerType *TruncatedTy =
6707+
IntegerType::get(M.getContext(), TruncatedWidth);
6708+
6709+
PoisonValue *TruncatedPoison = PoisonValue::get(TruncatedTy);
6710+
6711+
// Truncate the values and build a new lookup table containing them
6712+
SmallVector<std::pair<ConstantInt *, Constant *>, 64> TruncatedValues(
6713+
TableSize);
6714+
for (uint64_t I = 0; I < TableSize; ++I) {
6715+
ConstantInt *CaseVal =
6716+
ConstantInt::get(M.getContext(), Offset->getValue() + I);
6717+
Constant *CaseRes = TableContents[I];
6718+
6719+
Constant *TruncatedCaseRes;
6720+
if (ConstantInt *IntCaseRes = dyn_cast<ConstantInt>(CaseRes)) {
6721+
APInt TruncatedVal = IntCaseRes->getValue().extractBits(
6722+
TruncatedWidth, DiscardedLowBits);
6723+
TruncatedCaseRes = ConstantInt::get(M.getContext(), TruncatedVal);
6724+
} else if (isa<PoisonValue>(CaseRes)) {
6725+
TruncatedCaseRes = TruncatedPoison;
6726+
} else {
6727+
assert(isa<UndefValue>(CaseRes));
6728+
// To avoid making a call to the deprecated
6729+
// 'UndefValue ::get(TruncatedTy)', we'll simply replace undefined
6730+
// table entries with zero.
6731+
TruncatedCaseRes =
6732+
ConstantInt::get(M.getContext(), APInt::getZero(TruncatedWidth));
6733+
}
6734+
6735+
assert(TruncatedCaseRes->getType() == TruncatedTy);
6736+
6737+
TruncatedValues[I] = {CaseVal, TruncatedCaseRes};
6738+
}
6739+
6740+
// Recursively construct a new lookup table with the truncated values.
6741+
// This enables us to use more efficient table kinds which weren't
6742+
// possible originally, such as a bitmap.
6743+
TruncatedLookupTable = std::make_unique<SwitchLookupTable>(
6744+
M, TableSize, Offset, TruncatedValues, TruncatedPoison, DL,
6745+
("switch.truncated." + FuncName).str());
6746+
TruncatedOrigTy = IT;
6747+
6748+
if (DiscardedLowBits > 0) {
6749+
TruncatedShift = ConstantInt::get(IT, DiscardedLowBits);
6750+
TruncatedValWrapped = DiscardedHighBits == 0;
6751+
}
6752+
6753+
// The mask we OR on at the end consists of all the bits which are always
6754+
// one, excluding the bits which fit into the truncated value and didn't
6755+
// need to be changed.
6756+
APInt Mask =
6757+
AlwaysOneBits & ~APInt::getBitsSet(OrigWidth, DiscardedLowBits,
6758+
OrigWidth - DiscardedHighBits);
6759+
if (!Mask.isZero())
6760+
TruncatedMask = ConstantInt::get(M.getContext(), Mask);
6761+
6762+
Kind = TruncatedIntKind;
6763+
++NumTruncatedInts;
6764+
return;
6765+
}
6766+
}
6767+
66256768
// Store the table in an array.
66266769
ArrayType *ArrayTy = ArrayType::get(ValueType, TableSize);
66276770
Constant *Initializer = ConstantArray::get(ArrayTy, TableContents);
@@ -6677,6 +6820,23 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder) {
66776820
// Mask off.
66786821
return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
66796822
}
6823+
case TruncatedIntKind: {
6824+
// Load the truncated value from the lookup table
6825+
Value *TruncatedVal = TruncatedLookupTable->buildLookup(Index, Builder);
6826+
6827+
// Derive the original value from the truncated version
6828+
Value *Result = Builder.CreateIntCast(TruncatedVal, TruncatedOrigTy, false,
6829+
"switch.truncatedint.cast");
6830+
if (TruncatedShift)
6831+
Result =
6832+
Builder.CreateShl(Result, TruncatedShift, "switch.truncatedint.shift",
6833+
/*HasNUW =*/true,
6834+
/*HasNSW =*/!TruncatedValWrapped);
6835+
if (TruncatedMask)
6836+
Result =
6837+
Builder.CreateOr(Result, TruncatedMask, "switch.truncatedint.mask");
6838+
return Result;
6839+
}
66806840
case ArrayKind: {
66816841
// Make sure the table index will not overflow when treated as signed.
66826842
IntegerType *IT = cast<IntegerType>(Index->getType());

llvm/test/Transforms/PhaseOrdering/X86/merge-functions2.ll

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ target triple = "x86_64-apple-macosx12.0.0"
77
define i32 @f(i32 noundef %x) {
88
; CHECK-LABEL: define range(i32 0, 2) i32 @f(
99
; CHECK-SAME: i32 noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
10-
; CHECK-NEXT: [[ENTRY:.*]]:
10+
; CHECK-NEXT: [[ENTRY:.*:]]
1111
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 8
12-
; CHECK-NEXT: br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[SW_EPILOG:.*]]
13-
; CHECK: [[SWITCH_LOOKUP]]:
14-
; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[X]] to i64
15-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds nuw [8 x i32], ptr @switch.table.g, i64 0, i64 [[TMP1]]
16-
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
17-
; CHECK-NEXT: br label %[[SW_EPILOG]]
18-
; CHECK: [[SW_EPILOG]]:
19-
; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], %[[SWITCH_LOOKUP]] ], [ 0, %[[ENTRY]] ]
12+
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[X]] to i8
13+
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i8 -43, [[SWITCH_CAST]]
14+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[SWITCH_DOWNSHIFT]], 1
15+
; CHECK-NEXT: [[SWITCH_TRUNCATEDINT_CAST:%.*]] = zext nneg i8 [[TMP1]] to i32
16+
; CHECK-NEXT: [[X_ADDR_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_TRUNCATEDINT_CAST]], i32 0
2017
; CHECK-NEXT: ret i32 [[X_ADDR_0]]
2118
;
2219
entry:

llvm/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
; RUN: opt -S -passes='simplifycfg<switch-to-lookup>' -mtriple=arm -relocation-model=rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
1111
; RUN: opt -S -passes='simplifycfg<switch-to-lookup>' -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
1212

13-
; CHECK: @{{.*}} = private unnamed_addr constant [3 x i32] [i32 1234, i32 5678, i32 15532]
13+
; CHECK: @{{.*}} = private unnamed_addr constant [3 x i16] [i16 1234, i16 5678, i16 15532]
1414
; ENABLE: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @c1, ptr @c2, ptr @c3]
1515
; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @c1, ptr @c2, ptr @c3]
1616
; ENABLE: @{{.*}} = private unnamed_addr constant [3 x ptr] [ptr @g1, ptr @g2, ptr @g3]

llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ define i32 @foo(i32 %x) #0 section ".tcm_text" {
1313
; ENABLE-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 6
1414
; ENABLE-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
1515
; ENABLE: switch.lookup:
16-
; ENABLE-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds nuw [6 x i32], ptr @switch.table.foo, i32 0, i32 [[X]]
17-
; ENABLE-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
16+
; ENABLE-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds nuw [6 x i8], ptr @switch.table.switch.truncated.foo, i32 0, i32 [[X]]
17+
; ENABLE-NEXT: [[SWITCH_LOAD1:%.*]] = load i8, ptr [[SWITCH_GEP]], align 1
18+
; ENABLE-NEXT: [[SWITCH_LOAD:%.*]] = zext i8 [[SWITCH_LOAD1]] to i32
1819
; ENABLE-NEXT: br label [[RETURN]]
1920
; ENABLE: return:
2021
; ENABLE-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 19, [[ENTRY:%.*]] ]

llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ define i32 @switch_of_powers(i32 %x) {
3434
; RV64ZBB-LABEL: @switch_of_powers(
3535
; RV64ZBB-NEXT: entry:
3636
; RV64ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
37-
; RV64ZBB-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers, i32 0, i32 [[TMP0]]
38-
; RV64ZBB-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
37+
; RV64ZBB-NEXT: [[SWITCH_CAST:%.*]] = zext i32 [[TMP0]] to i56
38+
; RV64ZBB-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i56 [[SWITCH_CAST]], 8
39+
; RV64ZBB-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i56 11821953350566659, [[SWITCH_SHIFTAMT]]
40+
; RV64ZBB-NEXT: [[SWITCH_MASKED:%.*]] = trunc i56 [[SWITCH_DOWNSHIFT]] to i8
41+
; RV64ZBB-NEXT: [[SWITCH_LOAD:%.*]] = zext i8 [[SWITCH_MASKED]] to i32
3942
; RV64ZBB-NEXT: ret i32 [[SWITCH_LOAD]]
4043
;
4144
entry:

llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ define i64 @test(i3 %arg) {
1010
; CHECK-LABEL: @test(
1111
; CHECK-NEXT: entry:
1212
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[ARG:%.*]], -4
13-
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4
14-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], ptr @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]]
15-
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
13+
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
14+
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[SWITCH_CAST]], 4
15+
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -638023754, [[SWITCH_SHIFTAMT]]
16+
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i4
17+
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = zext i4 [[SWITCH_MASKED]] to i64
1618
; CHECK-NEXT: [[V3:%.*]] = add i64 [[SWITCH_LOAD]], 0
1719
; CHECK-NEXT: ret i64 [[V3]]
1820
;

llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) {
1010
; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si(
1111
; CHECK-NEXT: entry:
1212
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2
13-
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
14-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
15-
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
13+
; CHECK-NEXT: [[SWITCH_OFFSET:%.*]] = add i2 [[SWITCH_TABLEIDX]], -2
14+
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = zext i2 [[SWITCH_OFFSET]] to i64
1615
; CHECK-NEXT: ret i64 [[SWITCH_LOAD]]
1716
;
1817
entry:

llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
target triple = "x86_64-unknown-linux-gnu"
66

77
;.
8-
; CHECK: @switch.table.switch_to_lookup_i64 = private unnamed_addr constant [3 x i8] c"\03\01\02", align 1
9-
; CHECK: @switch.table.switch_to_lookup_i128 = private unnamed_addr constant [3 x i8] c"\03\01\02", align 1
8+
; CHECK: @switch.table.switch.truncated.switch_to_lookup_i64 = private unnamed_addr constant [3 x i2] [i2 -1, i2 1, i2 -2], align 1
9+
; CHECK: @switch.table.switch.truncated.switch_to_lookup_i128 = private unnamed_addr constant [3 x i2] [i2 -1, i2 1, i2 -2], align 1
1010
;.
1111
define i8 @switch_to_lookup_i64(i64 %x){
1212
; CHECK-LABEL: @switch_to_lookup_i64(
@@ -17,8 +17,9 @@ define i8 @switch_to_lookup_i64(i64 %x){
1717
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
1818
; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
1919
; CHECK: switch.lookup:
20-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i64, i32 0, i64 [[X]]
21-
; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
20+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i2], ptr @switch.table.switch.truncated.switch_to_lookup_i64, i32 0, i64 [[X]]
21+
; CHECK-NEXT: [[SWITCH_LOAD1:%.*]] = load i2, ptr [[SWITCH_GEP]], align 1
22+
; CHECK-NEXT: [[SWITCH_LOAD]] = zext i2 [[SWITCH_LOAD1]] to i8
2223
; CHECK-NEXT: br label [[COMMON_RET]]
2324
;
2425
; INLINE-LABEL: @switch_to_lookup_i64(
@@ -61,8 +62,9 @@ define i8 @switch_to_lookup_i128(i128 %x){
6162
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
6263
; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
6364
; CHECK: switch.lookup:
64-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i128, i32 0, i128 [[X]]
65-
; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
65+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i2], ptr @switch.table.switch.truncated.switch_to_lookup_i128, i32 0, i128 [[X]]
66+
; CHECK-NEXT: [[SWITCH_LOAD1:%.*]] = load i2, ptr [[SWITCH_GEP]], align 1
67+
; CHECK-NEXT: [[SWITCH_LOAD]] = zext i2 [[SWITCH_LOAD1]] to i8
6668
; CHECK-NEXT: br label [[COMMON_RET]]
6769
;
6870
; INLINE-LABEL: @switch_to_lookup_i128(

0 commit comments

Comments
 (0)