Skip to content

[SimplifyCFG] Use indexType from data layout in switch to table conversion #146207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6347,7 +6347,7 @@ class SwitchLookupTable {

/// Build instructions with Builder to retrieve the value at
/// the position given by Index in the lookup table.
Value *buildLookup(Value *Index, IRBuilder<> &Builder);
Value *buildLookup(Value *Index, IRBuilder<> &Builder, const DataLayout &DL);

/// Return true if a table with TableSize elements of
/// type ElementType would fit in a target-legal register.
Expand Down Expand Up @@ -6533,7 +6533,8 @@ SwitchLookupTable::SwitchLookupTable(
Kind = ArrayKind;
}

Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder) {
Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder,
const DataLayout &DL) {
switch (Kind) {
case SingleValueKind:
return SingleValue;
Expand Down Expand Up @@ -6575,16 +6576,12 @@ Value *SwitchLookupTable::buildLookup(Value *Index, IRBuilder<> &Builder) {
return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked");
}
case ArrayKind: {
// Make sure the table index will not overflow when treated as signed.
IntegerType *IT = cast<IntegerType>(Index->getType());
uint64_t TableSize =
Array->getInitializer()->getType()->getArrayNumElements();
if (TableSize > (1ULL << std::min(IT->getBitWidth() - 1, 63u)))
Index = Builder.CreateZExt(
Index, IntegerType::get(IT->getContext(), IT->getBitWidth() + 1),
"switch.tableidx.zext");

Value *GEPIndices[] = {Builder.getInt32(0), Index};
Type *IndexTy = DL.getIndexType(Array->getType());

if (Index->getType() != IndexTy)
Index = Builder.CreateZExtOrTrunc(Index, IndexTy);

Value *GEPIndices[] = {ConstantInt::get(IndexTy, 0), Index};
Value *GEP = Builder.CreateInBoundsGEP(Array->getValueType(), Array,
GEPIndices, "switch.gep");
return Builder.CreateLoad(
Expand Down Expand Up @@ -7064,7 +7061,7 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
SwitchLookupTable Table(Mod, TableSize, TableIndexOffset, ResultList, DV,
DL, FuncName);

Value *Result = Table.buildLookup(TableIndex, Builder);
Value *Result = Table.buildLookup(TableIndex, Builder, DL);

// Do a small peephole optimization: re-use the switch table compare if
// possible.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ define i32 @switch_of_powers(i32 %x) {
; RV64ZBB-LABEL: @switch_of_powers(
; RV64ZBB-NEXT: entry:
; RV64ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
; RV64ZBB-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers, i32 0, i32 [[TMP0]]
; RV64ZBB-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
; RV64ZBB-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers, i64 0, i64 [[TMP1]]
; RV64ZBB-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
; RV64ZBB-NEXT: ret i32 [[SWITCH_LOAD]]
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ define i32 @f(i32 %c) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7
; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.f, i32 0, i32 [[SWITCH_TABLEIDX]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SWITCH_TABLEIDX]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.f, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
Expand Down Expand Up @@ -67,7 +68,8 @@ define i8 @char(i32 %c) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 9
; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i8], ptr @switch.table.char, i32 0, i32 [[SWITCH_TABLEIDX]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SWITCH_TABLEIDX]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [9 x i8], ptr @switch.table.char, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8, ptr [[SWITCH_GEP]], align 1
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
Expand Down Expand Up @@ -114,7 +116,8 @@ define void @h(i32 %x) {
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[X]], 8
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 89655594, [[SWITCH_SHIFTAMT]]
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x float], ptr @switch.table.h, i32 0, i32 [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[X]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x float], ptr @switch.table.h, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load float, ptr [[SWITCH_GEP]], align 4
; CHECK-NEXT: br label [[SW_EPILOG]]
; CHECK: sw.epilog:
Expand Down Expand Up @@ -159,7 +162,8 @@ define ptr @foostring(i32 %x) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x ptr], ptr @switch.table.foostring, i32 0, i32 [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[X]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x ptr], ptr @switch.table.foostring, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ define i32 @bar(i32 %c) {
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4
; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.bar, i32 0, i32 [[SWITCH_TABLEIDX]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SWITCH_TABLEIDX]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.bar, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ define i64 @test(i3 %arg) {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i3 [[ARG:%.*]], -4
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i4
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], ptr @switch.table.test, i32 0, i4 [[SWITCH_TABLEIDX_ZEXT]]
; CHECK-NEXT: [[TMP0:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i64], ptr @switch.table.test, i64 0, i64 [[TMP0]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: [[V3:%.*]] = add i64 [[SWITCH_LOAD]], 0
; CHECK-NEXT: ret i64 [[V3]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ define i32 @switch_of_powers_two(i32 %arg) {
; CHECK-SAME: i32 [[ARG:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 true)
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two, i32 0, i32 [[TMP0]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers_two, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
;
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) {
; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TMP0:%.*]], -2
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
; CHECK-NEXT: [[TMP1:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: ret i64 [[SWITCH_LOAD]]
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ target triple = "x86_64-unknown-linux-gnu"
define { ptr, i64 } @switch_to_lookup_bitcast(i8 %0) unnamed_addr {
; CHECK-LABEL: @switch_to_lookup_bitcast(
; CHECK-NEXT: start:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table.switch_to_lookup_bitcast, i32 0, i8 [[TMP0:%.*]]
; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP0:%.*]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table.switch_to_lookup_bitcast, i64 0, i64 [[TMP3]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i64 } undef, ptr [[SWITCH_LOAD]], 0
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i64 } [[TMP1]], i64 1, 1
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-gep.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ target triple = "x86_64-unknown-linux-gnu"
define { ptr, i64 } @switch_to_lookup_gep(i8 %0) unnamed_addr {
; CHECK-LABEL: @switch_to_lookup_gep(
; CHECK-NEXT: start:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table.switch_to_lookup_gep, i32 0, i8 [[TMP0:%.*]]
; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP0:%.*]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table.switch_to_lookup_gep, i64 0, i64 [[TMP3]]
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i64 } undef, ptr [[SWITCH_LOAD]], 0
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, i64 } [[TMP1]], i64 1, 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ define i1 @zot(i32 %arg) {
; CHECK-NEXT: %0 = icmp ult i32 %arg, 3
; CHECK-NEXT: br i1 %0, label %switch.lookup, label %bb6
; CHECK: switch.lookup:
; CHECK-NEXT: %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.zot, i32 0, i32 %arg
; CHECK-NEXT: %1 = zext i32 %arg to i64
; CHECK-NEXT: %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.zot, i64 0, i64 %1
; CHECK-NEXT: %switch.load = load ptr, ptr %switch.gep, align 8
; CHECK-NEXT: br label %bb6
; CHECK: bb6:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ define i8 @switch_to_lookup_i64(i64 %x){
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i64, i32 0, i64 [[X]]
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i64, i64 0, i64 [[X]]
; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
; CHECK-NEXT: br label [[COMMON_RET]]
;
Expand Down Expand Up @@ -61,7 +61,8 @@ define i8 @switch_to_lookup_i128(i128 %x){
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i8 [ [[SWITCH_LOAD:%.*]], [[SWITCH_LOOKUP]] ], [ 10, [[START:%.*]] ]
; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
; CHECK: switch.lookup:
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i128, i32 0, i128 [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = trunc i128 [[X]] to i64
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8], ptr @switch.table.switch_to_lookup_i128, i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, ptr [[SWITCH_GEP]], align 1
; CHECK-NEXT: br label [[COMMON_RET]]
;
Expand Down
Loading
Loading