diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 39edc4d871262..970f85378d3d2 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6458,6 +6458,9 @@ class SwitchReplacement { /// Return the default value of the switch. Constant *getDefaultValue(); + /// Return true if the replacement is a lookup table. + bool isLookupTable(); + private: // Depending on the switch, there are different alternatives. enum { @@ -6605,7 +6608,6 @@ SwitchReplacement::SwitchReplacement( (void)M.smul_ov(APInt(M.getBitWidth(), TableSize - 1), MayWrap); LinearMapValWrapped = NonMonotonic || MayWrap; Kind = LinearMapKind; - ++NumLinearMaps; return; } } @@ -6625,7 +6627,6 @@ SwitchReplacement::SwitchReplacement( BitMap = ConstantInt::get(M.getContext(), TableInt); BitMapElementTy = IT; Kind = BitMapKind; - ++NumBitMaps; return; } @@ -6642,6 +6643,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder, case SingleValueKind: return SingleValue; case LinearMapKind: { + ++NumLinearMaps; // Derive the result value from the input value. Value *Result = Builder.CreateIntCast(Index, LinearMultiplier->getType(), false, "switch.idx.cast"); @@ -6657,6 +6659,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder, return Result; } case BitMapKind: { + ++NumBitMaps; // Type of the bitmap (e.g. i59). IntegerType *MapTy = BitMap->getIntegerType(); @@ -6679,6 +6682,7 @@ Value *SwitchReplacement::replaceSwitch(Value *Index, IRBuilder<> &Builder, return Builder.CreateTrunc(DownShifted, BitMapElementTy, "switch.masked"); } case LookupTableKind: { + ++NumLookupTables; auto *Table = new GlobalVariable(*Func->getParent(), Initializer->getType(), /*isConstant=*/true, GlobalVariable::PrivateLinkage, @@ -6745,6 +6749,8 @@ static bool isTypeLegalForLookupTable(Type *Ty, const TargetTransformInfo &TTI, Constant *SwitchReplacement::getDefaultValue() { return DefaultValue; } +bool SwitchReplacement::isLookupTable() { return Kind == LookupTableKind; } + static bool isSwitchDense(uint64_t NumCases, uint64_t CaseRange) { // 40% is the default density for building a jump table in optsize/minsize // mode. See also TargetLoweringBase::isSuitableForJumpTable(), which this @@ -6915,11 +6921,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder, BasicBlock *BB = SI->getParent(); Function *Fn = BB->getParent(); - // Only build lookup table when we have a target that supports it or the - // attribute is not set. - if (!TTI.shouldBuildLookupTables() || - (Fn->getFnAttribute("no-jump-tables").getValueAsBool())) - return false; // FIXME: If the switch is too sparse for a lookup table, perhaps we could // split off a dense part and build a lookup table for that. @@ -7078,6 +7079,20 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder, PhiToReplacementMap.insert({PHI, Replacement}); } + bool AnyLookupTables = any_of( + PhiToReplacementMap, [](auto &KV) { return KV.second.isLookupTable(); }); + + // A few conditions prevent the generation of lookup tables: + // 1. The target does not support lookup tables. + // 2. The "no-jump-tables" function attribute is set. + // However, these objections do not apply to other switch replacements, like + // the bitmap, so we only stop here if any of these conditions are met and we + // want to create a LUT. Otherwise, continue with the switch replacement. + if (AnyLookupTables && + (!TTI.shouldBuildLookupTables() || + Fn->getFnAttribute("no-jump-tables").getValueAsBool())) + return false; + Builder.SetInsertPoint(SI); // TableIndex is the switch condition - TableIndexOffset if we don't // use the condition directly @@ -7219,7 +7234,6 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder, if (DTU) DTU->applyUpdates(Updates); - ++NumLookupTables; if (NeedMask) ++NumLookupTablesHoles; return true; diff --git a/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll b/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll new file mode 100644 index 0000000000000..c9063d3ec26ff --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll @@ -0,0 +1,515 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes='simplifycfg' < %s | FileCheck %s --check-prefix=OPTNOLUT +; RUN: %if amdgpu-registered-target %{ opt -mtriple=amdgcn--amdpal -S -passes='simplifycfg' < %s | FileCheck %s --check-prefix=TTINOLUT %} +; +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define i32 @linear_transform_with_default(i32 %x) { +; OPTNOLUT-LABEL: define i32 @linear_transform_with_default( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[CASE0:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE0]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 1, %[[CASE0]] ], [ 4, %[[CASE1]] ], [ 7, %[[CASE2]] ], [ 10, %[[CASE3]] ], [ 13, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[IDX]] +; +; TTINOLUT-LABEL: define i32 @linear_transform_with_default( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*]]: +; TTINOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 4 +; TTINOLUT-NEXT: br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[END:.*]] +; TTINOLUT: [[SWITCH_LOOKUP]]: +; TTINOLUT-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[X]], 3 +; TTINOLUT-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1 +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[END]]: +; TTINOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 13, %[[ENTRY]] ], [ [[SWITCH_OFFSET]], %[[SWITCH_LOOKUP]] ] +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %end [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end + +end: + %idx = phi i32 [ 1, %case0 ], [ 4, %case1 ], [ 7, %case2 ], [ 10, %case3 ], [ 13, %entry ] + ret i32 %idx +} + +define i32 @linear_transform_with_outlier(i32 %x) { +; OPTNOLUT-LABEL: define i32 @linear_transform_with_outlier( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[CASE0:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: i32 4, label %[[CASE4:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE0]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE4]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 0, %[[CASE0]] ], [ 3, %[[CASE1]] ], [ 6, %[[CASE2]] ], [ 9, %[[CASE3]] ], [ 13, %[[CASE4]] ], [ 12, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[IDX]] +; +; TTINOLUT-LABEL: define i32 @linear_transform_with_outlier( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*]]: +; TTINOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [ +; TTINOLUT-NEXT: i32 0, label %[[CASE0:.*]] +; TTINOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; TTINOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; TTINOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; TTINOLUT-NEXT: i32 4, label %[[CASE4:.*]] +; TTINOLUT-NEXT: ] +; TTINOLUT: [[CASE0]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE1]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE2]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE3]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE4]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[END]]: +; TTINOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 0, %[[CASE0]] ], [ 3, %[[CASE1]] ], [ 6, %[[CASE2]] ], [ 9, %[[CASE3]] ], [ 13, %[[CASE4]] ], [ 12, %[[ENTRY]] ] +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %end [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + i32 4, label %case4 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +case4: + br label %end + +end: + %idx = phi i32 [ 0, %case0 ], [ 3, %case1 ], [ 6, %case2 ], [ 9, %case3 ], [ 13, %case4 ], [ 12, %entry ] + ret i32 %idx +} + +define i32 @linear_transform_no_default(i32 %x) { +; OPTNOLUT-LABEL: define i32 @linear_transform_no_default( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[END:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: i32 4, label %[[CASE4:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE4]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[DEFAULT]]: +; OPTNOLUT-NEXT: unreachable +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[SWITCH_IDX_MULT:%.*]] = phi i32 [ 3, %[[CASE1]] ], [ 6, %[[CASE2]] ], [ 9, %[[CASE3]] ], [ 12, %[[CASE4]] ], [ 0, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[SWITCH_IDX_MULT]] +; +; TTINOLUT-LABEL: define i32 @linear_transform_no_default( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*:]] +; TTINOLUT-NEXT: [[IDX:%.*]] = mul nsw i32 [[X]], 3 +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + i32 4, label %case4 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +case4: + br label %end +default: + unreachable + +end: + %idx = phi i32 [ 0, %case0 ], [ 3, %case1 ], [ 6, %case2 ], [ 9, %case3 ], [ 12, %case4 ] + ret i32 %idx +} + +define i4 @bitmap_no_default(i32 %x) { +; OPTNOLUT-LABEL: define i4 @bitmap_no_default( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[END:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[DEFAULT]]: +; OPTNOLUT-NEXT: unreachable +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[SWITCH_MASKED:%.*]] = phi i4 [ 2, %[[CASE1]] ], [ 4, %[[CASE2]] ], [ -8, %[[CASE3]] ], [ 0, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i4 [[SWITCH_MASKED]] +; +; TTINOLUT-LABEL: define i4 @bitmap_no_default( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*:]] +; TTINOLUT-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[X]] to i16 +; TTINOLUT-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 4 +; TTINOLUT-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i16 -31712, [[SWITCH_SHIFTAMT]] +; TTINOLUT-NEXT: [[IDX:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT]] to i4 +; TTINOLUT-NEXT: ret i4 [[IDX]] +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +default: + unreachable + +end: + %idx = phi i4 [ 0, %case0 ], [ 2, %case1 ], [ 4, %case2 ], [ 8, %case3 ] + ret i4 %idx +} + +define i4 @bitmap_with_default(i32 %x) { +; OPTNOLUT-LABEL: define i4 @bitmap_with_default( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[END:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[DEFAULT]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i4 [ 2, %[[CASE1]] ], [ 4, %[[CASE2]] ], [ -8, %[[CASE3]] ], [ -1, %[[DEFAULT]] ], [ 0, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i4 [[IDX]] +; +; TTINOLUT-LABEL: define i4 @bitmap_with_default( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*]]: +; TTINOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 4 +; TTINOLUT-NEXT: br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[END:.*]] +; TTINOLUT: [[SWITCH_LOOKUP]]: +; TTINOLUT-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[X]] to i16 +; TTINOLUT-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 4 +; TTINOLUT-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i16 -31712, [[SWITCH_SHIFTAMT]] +; TTINOLUT-NEXT: [[SWITCH_MASKED:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT]] to i4 +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[END]]: +; TTINOLUT-NEXT: [[IDX:%.*]] = phi i4 [ [[SWITCH_MASKED]], %[[SWITCH_LOOKUP]] ], [ -1, %[[ENTRY]] ] +; TTINOLUT-NEXT: ret i4 [[IDX]] +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +default: + br label %end + +end: + %idx = phi i4 [ 0, %case0 ], [ 2, %case1 ], [ 4, %case2 ], [ 8, %case3 ], [15, %default] + ret i4 %idx +} + +define i32 @single_value_no_default(i32 %x) { +; OPTNOLUT-LABEL: define i32 @single_value_no_default( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*:]] +; OPTNOLUT-NEXT: ret i32 2 +; +; TTINOLUT-LABEL: define i32 @single_value_no_default( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*:]] +; TTINOLUT-NEXT: ret i32 2 +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + i32 4, label %case4 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +case4: + br label %end +default: + unreachable + +end: + %idx = phi i32 [ 2, %case0 ], [ 2, %case1 ], [ 2, %case2 ], [ 2, %case3 ], [ 2, %case4 ] + ret i32 %idx +} + +define i32 @single_value_withdefault(i32 %x) { +; OPTNOLUT-LABEL: define i32 @single_value_withdefault( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[END:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[END]] +; OPTNOLUT-NEXT: i32 2, label %[[END]] +; OPTNOLUT-NEXT: i32 3, label %[[END]] +; OPTNOLUT-NEXT: i32 4, label %[[END]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[DEFAULT]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[DOT:%.*]] = phi i32 [ 3, %[[DEFAULT]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[DOT]] +; +; TTINOLUT-LABEL: define i32 @single_value_withdefault( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*:]] +; TTINOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 5 +; TTINOLUT-NEXT: [[IDX:%.*]] = select i1 [[TMP0]], i32 2, i32 3 +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + i32 4, label %case4 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +case4: + br label %end +default: + br label %end + +end: + %idx = phi i32 [ 2, %case0 ], [ 2, %case1 ], [ 2, %case2 ], [ 2, %case3 ], [ 2, %case4 ], [ 3, %default ] + ret i32 %idx +} + +define i32 @single_value_no_jump_tables(i32 %x) "no-jump-tables"="true" { +; OPTNOLUT-LABEL: define i32 @single_value_no_jump_tables( +; OPTNOLUT-SAME: i32 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[END:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[END]] +; OPTNOLUT-NEXT: i32 2, label %[[END]] +; OPTNOLUT-NEXT: i32 3, label %[[END]] +; OPTNOLUT-NEXT: i32 4, label %[[END]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[DEFAULT]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 3, %[[DEFAULT]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[IDX]] +; +; TTINOLUT-LABEL: define i32 @single_value_no_jump_tables( +; TTINOLUT-SAME: i32 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; TTINOLUT-NEXT: [[ENTRY:.*:]] +; TTINOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 5 +; TTINOLUT-NEXT: [[IDX:%.*]] = select i1 [[TMP0]], i32 2, i32 3 +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %default [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + i32 4, label %case4 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end +case4: + br label %end +default: + br label %end + +end: + %idx = phi i32 [ 2, %case0 ], [ 2, %case1 ], [ 2, %case2 ], [ 2, %case3 ], [ 2, %case4 ], [ 3, %default ] + ret i32 %idx +} + +define i32 @lookup_table(i32 %x) { +; OPTNOLUT-LABEL: define i32 @lookup_table( +; OPTNOLUT-SAME: i32 [[X:%.*]]) { +; OPTNOLUT-NEXT: [[ENTRY:.*]]: +; OPTNOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [ +; OPTNOLUT-NEXT: i32 0, label %[[CASE0:.*]] +; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; OPTNOLUT-NEXT: ] +; OPTNOLUT: [[CASE0]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE1]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE2]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[CASE3]]: +; OPTNOLUT-NEXT: br label %[[END]] +; OPTNOLUT: [[END]]: +; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 13, %[[CASE0]] ], [ 3, %[[CASE1]] ], [ 11, %[[CASE2]] ], [ 8, %[[CASE3]] ], [ 24, %[[ENTRY]] ] +; OPTNOLUT-NEXT: ret i32 [[IDX]] +; +; TTINOLUT-LABEL: define i32 @lookup_table( +; TTINOLUT-SAME: i32 [[X:%.*]]) { +; TTINOLUT-NEXT: [[ENTRY:.*]]: +; TTINOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [ +; TTINOLUT-NEXT: i32 0, label %[[CASE0:.*]] +; TTINOLUT-NEXT: i32 1, label %[[CASE1:.*]] +; TTINOLUT-NEXT: i32 2, label %[[CASE2:.*]] +; TTINOLUT-NEXT: i32 3, label %[[CASE3:.*]] +; TTINOLUT-NEXT: ] +; TTINOLUT: [[CASE0]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE1]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE2]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[CASE3]]: +; TTINOLUT-NEXT: br label %[[END]] +; TTINOLUT: [[END]]: +; TTINOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 13, %[[CASE0]] ], [ 3, %[[CASE1]] ], [ 11, %[[CASE2]] ], [ 8, %[[CASE3]] ], [ 24, %[[ENTRY]] ] +; TTINOLUT-NEXT: ret i32 [[IDX]] +; +entry: + switch i32 %x, label %end [ + i32 0, label %case0 + i32 1, label %case1 + i32 2, label %case2 + i32 3, label %case3 + ] + +case0: + br label %end +case1: + br label %end +case2: + br label %end +case3: + br label %end + +end: + %idx = phi i32 [ 13, %case0 ], [ 3, %case1 ], [ 11, %case2 ], [ 8, %case3 ], [ 24, %entry ] + ret i32 %idx +}