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 @@ -6035,7 +6035,7 @@ IntegerType *IT = cast(Index->getType()); uint64_t TableSize = Array->getInitializer()->getType()->getArrayNumElements(); - if (TableSize > (1ULL << (IT->getBitWidth() - 1))) + if (TableSize > (1ULL << std::min(IT->getBitWidth() - 1, 63u))) Index = Builder.CreateZExt( Index, IntegerType::get(IT->getContext(), IT->getBitWidth() + 1), "switch.tableidx.zext"); diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-large-types.ll @@ -0,0 +1,73 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -passes=simplifycfg --switch-to-lookup -S %s | FileCheck %s +target triple = "x86_64-unknown-linux-gnu" + + +define i8 @switch_to_lookup_i64(i128 %x){ +; CHECK-LABEL: define {{[^@]+}}@switch_to_lookup_i64 +; CHECK-SAME: (i128 [[X:%.*]]) { +; CHECK-NEXT: start: +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i128 [[X]], 3 +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: common.ret: +; 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], [3 x i8]* @switch.table.switch_to_lookup_i64, i32 0, i128 [[X]] +; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, i8* [[SWITCH_GEP]], align 1 +; CHECK-NEXT: br label [[COMMON_RET]] +; +start: + switch i128 %x, label %default [ + i128 0, label %end + i128 1, label %bb1 + i128 2, label %bb2 + ] + +bb1: + br label %end + +bb2: + br label %end + +default: + ret i8 10 + +end: + %p = phi i8 [ 1, %bb1 ], [ 2, %bb2 ], [ 3, %start ] + ret i8 %p +} +define i8 @switch_to_lookup_i128(i128 %x){ +; CHECK-LABEL: define {{[^@]+}}@switch_to_lookup_i128 +; CHECK-SAME: (i128 [[X:%.*]]) { +; CHECK-NEXT: start: +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i128 [[X]], 3 +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] +; CHECK: common.ret: +; 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], [3 x i8]* @switch.table.switch_to_lookup_i128, i32 0, i128 [[X]] +; CHECK-NEXT: [[SWITCH_LOAD]] = load i8, i8* [[SWITCH_GEP]], align 1 +; CHECK-NEXT: br label [[COMMON_RET]] +; +start: + switch i128 %x, label %default [ + i128 0, label %end + i128 1, label %bb1 + i128 2, label %bb2 + ] + +bb1: + br label %end + +bb2: + br label %end + +default: + ret i8 10 + +end: + %p = phi i8 [ 1, %bb1 ], [ 2, %bb2 ], [ 3, %start ] + ret i8 %p +}