diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5604,6 +5604,27 @@ return DL.fitsInLegalInteger(TableSize * IT->getBitWidth()); } +static bool isTypeLegalForLookupTable(Type *Ty, const TargetTransformInfo &TTI, + const DataLayout &DL) { + // Allow any legal type. + if (TTI.isTypeLegal(Ty)) + return true; + + auto *IT = dyn_cast(Ty); + if (!IT) + return false; + + // Also allow power of 2 integer types that have at least 8 bits and fit in + // a register. These types are common in frontend languages and targets + // usually support loads of these types. + // TODO: We could relax this to any integer that fits in a register and rely + // on ABI alignment and padding in the table to allow the load to be widened. + // Or we could widen the constants and truncate the load. + unsigned BitWidth = IT->getBitWidth(); + return BitWidth >= 8 && isPowerOf2_32(BitWidth) && + DL.fitsInLegalInteger(IT->getBitWidth()); +} + /// Determine whether a lookup table should be built for this switch, based on /// the number of cases, size of the table, and the types of the results. static bool @@ -5619,7 +5640,7 @@ Type *Ty = I.second; // Saturate this flag to true. - HasIllegalType = HasIllegalType || !TTI.isTypeLegal(Ty); + HasIllegalType = HasIllegalType || !isTypeLegalForLookupTable(Ty, TTI, DL); // Saturate this flag to false. AllTablesFitInRegister = diff --git a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll --- a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll +++ b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll @@ -7,6 +7,12 @@ ; The table for @f ; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4 +; The char table for char +; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1 + +; The float table for @h +; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4 + ; The table for @foostring ; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0)], align 4 @@ -58,37 +64,15 @@ define i8 @char(i32 %c) { ; CHECK-LABEL: @char( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]] -; CHECK-NEXT: i32 47, label [[SW_BB5:%.*]] -; CHECK-NEXT: i32 48, label [[SW_BB6:%.*]] -; CHECK-NEXT: i32 49, label [[SW_BB7:%.*]] -; CHECK-NEXT: i32 50, label [[SW_BB8:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb4: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb5: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb6: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb7: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb8: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 +; 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], [9 x i8]* @switch.table.char, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8, i8* [[SWITCH_GEP]], align 1 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8 [ 15, [[SW_DEFAULT]] ], [ 84, [[SW_BB8]] ], [ 33, [[SW_BB7]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 15, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i8 [[RETVAL_0]] ; entry: @@ -125,23 +109,18 @@ define void @h(i32 %x) { ; CHECK-LABEL: @h( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW_EPILOG:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.default: +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul 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], [4 x float]* @switch.table.h, i32 0, i32 [[X]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load float, float* [[SWITCH_GEP]], align 4 ; CHECK-NEXT: br label [[SW_EPILOG]] ; CHECK: sw.epilog: -; CHECK-NEXT: [[A_0:%.*]] = phi i8 [ 7, [[SW_DEFAULT]] ], [ 5, [[SW_BB3]] ], [ 88, [[SW_BB2]] ], [ 9, [[SW_BB1]] ], [ 42, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[B_0:%.*]] = phi float [ 0x4023FAE140000000, [[SW_DEFAULT]] ], [ 0x4001AE1480000000, [[SW_BB3]] ], [ 0x4012449BA0000000, [[SW_BB2]] ], [ 0x3FF3BE76C0000000, [[SW_BB1]] ], [ 0x40091EB860000000, [[ENTRY]] ] +; CHECK-NEXT: [[A_0:%.*]] = phi i8 [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[B_0:%.*]] = phi float [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 0x4023FAE140000000, [[ENTRY]] ] ; CHECK-NEXT: call void @dummy(i8 signext [[A_0]], float [[B_0]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll --- a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll +++ b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll @@ -4,6 +4,15 @@ target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" target triple = "riscv64-unknown-elf" +; The table for @f +; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4 + +; The char table for char +; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1 + +; The float table for @h +; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4 + ; The table for @foostring ; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0)], align 8 @@ -15,31 +24,15 @@ define i32 @f(i32 %c) { ; CHECK-LABEL: @f( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]] -; CHECK-NEXT: i32 47, label [[SW_BB5:%.*]] -; CHECK-NEXT: i32 48, label [[SW_BB6:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb4: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb5: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb6: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 +; 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], [7 x i32]* @switch.table.f, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 15, [[SW_DEFAULT]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 15, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; entry: @@ -71,37 +64,15 @@ define i8 @char(i32 %c) { ; CHECK-LABEL: @char( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 42, label [[RETURN:%.*]] -; CHECK-NEXT: i32 43, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 44, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 45, label [[SW_BB3:%.*]] -; CHECK-NEXT: i32 46, label [[SW_BB4:%.*]] -; CHECK-NEXT: i32 47, label [[SW_BB5:%.*]] -; CHECK-NEXT: i32 48, label [[SW_BB6:%.*]] -; CHECK-NEXT: i32 49, label [[SW_BB7:%.*]] -; CHECK-NEXT: i32 50, label [[SW_BB8:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb4: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb5: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb6: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb7: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.bb8: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: sw.default: +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42 +; 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], [9 x i8]* @switch.table.char, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8, i8* [[SWITCH_GEP]], align 1 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8 [ 15, [[SW_DEFAULT]] ], [ 84, [[SW_BB8]] ], [ 33, [[SW_BB7]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 15, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i8 [[RETVAL_0]] ; entry: @@ -138,23 +109,18 @@ define void @h(i32 %x) { ; CHECK-LABEL: @h( ; CHECK-NEXT: entry: -; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW_EPILOG:%.*]] -; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 3, label [[SW_BB3:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.bb2: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.bb3: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.default: +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4 +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[SW_EPILOG:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul 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], [4 x float]* @switch.table.h, i32 0, i32 [[X]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load float, float* [[SWITCH_GEP]], align 4 ; CHECK-NEXT: br label [[SW_EPILOG]] ; CHECK: sw.epilog: -; CHECK-NEXT: [[A_0:%.*]] = phi i8 [ 7, [[SW_DEFAULT]] ], [ 5, [[SW_BB3]] ], [ 88, [[SW_BB2]] ], [ 9, [[SW_BB1]] ], [ 42, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[B_0:%.*]] = phi float [ 0x4023FAE140000000, [[SW_DEFAULT]] ], [ 0x4001AE1480000000, [[SW_BB3]] ], [ 0x4012449BA0000000, [[SW_BB2]] ], [ 0x3FF3BE76C0000000, [[SW_BB1]] ], [ 0x40091EB860000000, [[ENTRY]] ] +; CHECK-NEXT: [[A_0:%.*]] = phi i8 [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ 7, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[B_0:%.*]] = phi float [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 0x4023FAE140000000, [[ENTRY]] ] ; CHECK-NEXT: call void @dummy(i8 signext [[A_0]], float [[B_0]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll --- a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll +++ b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll @@ -10,21 +10,15 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 0, label [[ONE:%.*]] -; CHECK-NEXT: i32 1, label [[TWO:%.*]] -; CHECK-NEXT: i32 2, label [[THREE:%.*]] -; CHECK-NEXT: i32 3, label [[THREE]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 4 +; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.test1, i32 0, i32 [[TMP4]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] -; CHECK: one: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: two: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: three: -; CHECK-NEXT: br label [[COMMON_RET]] ; switch i32 %a, label %def [ i32 97, label %one @@ -84,20 +78,16 @@ ; Optimization shouldn't trigger; no holes present define i32 @test3(i32 %a) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 97, label [[ONE:%.*]] -; CHECK-NEXT: i32 98, label [[TWO:%.*]] -; CHECK-NEXT: i32 99, label [[THREE:%.*]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[A:%.*]], 97 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 3 +; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* @switch.table.test3, i32 0, i32 [[SWITCH_TABLEIDX]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] -; CHECK: one: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: two: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: three: -; CHECK-NEXT: br label [[COMMON_RET]] ; switch i32 %a, label %def [ i32 97, label %one @@ -196,21 +186,15 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 3, label [[ONE:%.*]] -; CHECK-NEXT: i32 2, label [[TWO:%.*]] -; CHECK-NEXT: i32 1, label [[THREE:%.*]] -; CHECK-NEXT: i32 0, label [[THREE]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 4 +; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.test6, i32 0, i32 [[TMP4]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] -; CHECK: one: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: two: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: three: -; CHECK-NEXT: br label [[COMMON_RET]] ; switch i32 %a, label %def [ i32 -97, label %one @@ -269,21 +253,15 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 0, label [[ONE:%.*]] -; CHECK-NEXT: i32 1, label [[TWO:%.*]] -; CHECK-NEXT: i32 2, label [[THREE:%.*]] -; CHECK-NEXT: i32 4, label [[THREE]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 5 +; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], [5 x i32]* @switch.table.test8, i32 0, i32 [[TMP4]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] -; CHECK: one: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: two: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: three: -; CHECK-NEXT: br label [[COMMON_RET]] ; switch i32 %a, label %def [ i32 97, label %one @@ -309,21 +287,15 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 31 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ -; CHECK-NEXT: i32 6, label [[ONE:%.*]] -; CHECK-NEXT: i32 7, label [[TWO:%.*]] -; CHECK-NEXT: i32 0, label [[THREE:%.*]] -; CHECK-NEXT: i32 2, label [[THREE]] -; CHECK-NEXT: ] +; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 8 +; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: switch.lookup: +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], [8 x i32]* @switch.table.test9, i32 0, i32 [[TMP4]] +; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: common.ret: -; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ] ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] -; CHECK: one: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: two: -; CHECK-NEXT: br label [[COMMON_RET]] -; CHECK: three: -; CHECK-NEXT: br label [[COMMON_RET]] ; switch i32 %a, label %def [ i32 18, label %one