Skip to content

Commit 4c82754

Browse files
authored
[SimplifyCFG] Allow some switch optimizations early in the pipeline (#158242)
While we do not want to form actual lookup tables early, we do want to perform some optimizations, as they may enable inlining of the much simpler form. Builds on #156477, which originally included this change as well. This PR makes two changes on top of it: * Do not perform the optimization early if it requires adding a mask check. These make the resulting IR less analyzable. * Add a new SimplifyCFG option that controls switch-to-arithmetic conversion separately from switch-to-lookup conversion. Enable the new flag at the end of the function simplification pipeline. This means that we attempt the arithmetic conversion before inlining, but avoid it in the early pipeline, where it may lose information.
1 parent 805451f commit 4c82754

File tree

9 files changed

+109
-75
lines changed

9 files changed

+109
-75
lines changed

llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct SimplifyCFGOptions {
2424
int BonusInstThreshold = 1;
2525
bool ForwardSwitchCondToPhi = false;
2626
bool ConvertSwitchRangeToICmp = false;
27+
bool ConvertSwitchToArithmetic = false;
2728
bool ConvertSwitchToLookupTable = false;
2829
bool NeedCanonicalLoop = true;
2930
bool HoistCommonInsts = false;
@@ -48,6 +49,10 @@ struct SimplifyCFGOptions {
4849
ConvertSwitchRangeToICmp = B;
4950
return *this;
5051
}
52+
SimplifyCFGOptions &convertSwitchToArithmetic(bool B) {
53+
ConvertSwitchToArithmetic = B;
54+
return *this;
55+
}
5156
SimplifyCFGOptions &convertSwitchToLookupTable(bool B) {
5257
ConvertSwitchToLookupTable = B;
5358
return *this;

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,8 @@ Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {
11111111
Result.forwardSwitchCondToPhi(Enable);
11121112
} else if (ParamName == "switch-range-to-icmp") {
11131113
Result.convertSwitchRangeToICmp(Enable);
1114+
} else if (ParamName == "switch-to-arithmetic") {
1115+
Result.convertSwitchToArithmetic(Enable);
11141116
} else if (ParamName == "switch-to-lookup") {
11151117
Result.convertSwitchToLookupTable(Enable);
11161118
} else if (ParamName == "keep-loops") {

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
781781

782782
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions()
783783
.convertSwitchRangeToICmp(true)
784+
.convertSwitchToArithmetic(true)
784785
.hoistCommonInsts(true)
785786
.sinkCommonInsts(true)));
786787
FPM.addPass(InstCombinePass());
@@ -1377,6 +1378,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
13771378
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions()
13781379
.forwardSwitchCondToPhi(true)
13791380
.convertSwitchRangeToICmp(true)
1381+
.convertSwitchToArithmetic(true)
13801382
.convertSwitchToLookupTable(true)
13811383
.needCanonicalLoops(false)
13821384
.hoistCommonInsts(true)
@@ -1603,6 +1605,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
16031605
OptimizePM.addPass(
16041606
SimplifyCFGPass(SimplifyCFGOptions()
16051607
.convertSwitchRangeToICmp(true)
1608+
.convertSwitchToArithmetic(true)
16061609
.speculateUnpredictables(true)
16071610
.hoistLoadsStoresWithCondFaulting(true)));
16081611

@@ -2187,6 +2190,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
21872190
// Delete basic blocks, which optimization passes may have killed.
21882191
LateFPM.addPass(SimplifyCFGPass(SimplifyCFGOptions()
21892192
.convertSwitchRangeToICmp(true)
2193+
.convertSwitchToArithmetic(true)
21902194
.hoistCommonInsts(true)
21912195
.speculateUnpredictables(true)));
21922196
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM)));

llvm/lib/Passes/PassRegistry.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,9 @@ FUNCTION_PASS_WITH_PARAMS(
687687
parseSimplifyCFGOptions,
688688
"no-speculate-blocks;speculate-blocks;no-simplify-cond-branch;"
689689
"simplify-cond-branch;no-forward-switch-cond;forward-switch-cond;"
690-
"no-switch-range-to-icmp;switch-range-to-icmp;no-switch-to-lookup;"
691-
"switch-to-lookup;no-keep-loops;keep-loops;no-hoist-common-insts;"
690+
"no-switch-range-to-icmp;switch-range-to-icmp;no-switch-to-arithmetic;"
691+
"switch-to-arithmetic;no-switch-to-lookup;switch-to-lookup;"
692+
"no-keep-loops;keep-loops;no-hoist-common-insts;"
692693
"hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;"
693694
"hoist-loads-stores-with-cond-faulting;no-sink-common-insts;"
694695
"sink-common-insts;no-speculate-unpredictables;speculate-unpredictables;"

llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ void SimplifyCFGPass::printPipeline(
355355
OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;";
356356
OS << (Options.ConvertSwitchRangeToICmp ? "" : "no-")
357357
<< "switch-range-to-icmp;";
358+
OS << (Options.ConvertSwitchToArithmetic ? "" : "no-")
359+
<< "switch-to-arithmetic;";
358360
OS << (Options.ConvertSwitchToLookupTable ? "" : "no-")
359361
<< "switch-to-lookup;";
360362
OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;";

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6642,6 +6642,9 @@ class SwitchReplacement {
66426642
/// Return true if the replacement is a lookup table.
66436643
bool isLookupTable();
66446644

6645+
/// Return true if the replacement is a bit map.
6646+
bool isBitMap();
6647+
66456648
private:
66466649
// Depending on the switch, there are different alternatives.
66476650
enum {
@@ -6932,6 +6935,8 @@ Constant *SwitchReplacement::getDefaultValue() { return DefaultValue; }
69326935

69336936
bool SwitchReplacement::isLookupTable() { return Kind == LookupTableKind; }
69346937

6938+
bool SwitchReplacement::isBitMap() { return Kind == BitMapKind; }
6939+
69356940
static bool isSwitchDense(uint64_t NumCases, uint64_t CaseRange) {
69366941
// 40% is the default density for building a jump table in optsize/minsize
69376942
// mode. See also TargetLoweringBase::isSuitableForJumpTable(), which this
@@ -7097,7 +7102,8 @@ static void reuseTableCompare(
70977102
/// lookup tables.
70987103
static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
70997104
DomTreeUpdater *DTU, const DataLayout &DL,
7100-
const TargetTransformInfo &TTI) {
7105+
const TargetTransformInfo &TTI,
7106+
bool ConvertSwitchToLookupTable) {
71017107
assert(SI->getNumCases() > 1 && "Degenerate switch?");
71027108

71037109
BasicBlock *BB = SI->getParent();
@@ -7262,6 +7268,8 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
72627268

72637269
bool AnyLookupTables = any_of(
72647270
PhiToReplacementMap, [](auto &KV) { return KV.second.isLookupTable(); });
7271+
bool AnyBitMaps = any_of(PhiToReplacementMap,
7272+
[](auto &KV) { return KV.second.isBitMap(); });
72657273

72667274
// A few conditions prevent the generation of lookup tables:
72677275
// 1. The target does not support lookup tables.
@@ -7274,6 +7282,12 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
72747282
Fn->getFnAttribute("no-jump-tables").getValueAsBool()))
72757283
return false;
72767284

7285+
// In the early optimization pipeline, disable formation of lookup tables,
7286+
// bit maps and mask checks, as they may inhibit further optimization.
7287+
if (!ConvertSwitchToLookupTable &&
7288+
(AnyLookupTables || AnyBitMaps || NeedMask))
7289+
return false;
7290+
72777291
Builder.SetInsertPoint(SI);
72787292
// TableIndex is the switch condition - TableIndexOffset if we don't
72797293
// use the condition directly
@@ -7929,14 +7943,13 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
79297943
if (Options.ForwardSwitchCondToPhi && forwardSwitchConditionToPHI(SI))
79307944
return requestResimplify();
79317945

7932-
// The conversion from switch to lookup tables results in difficult-to-analyze
7933-
// code and makes pruning branches much harder. This is a problem if the
7934-
// switch expression itself can still be restricted as a result of inlining or
7935-
// CVP. Therefore, only apply this transformation during late stages of the
7936-
// optimisation pipeline.
7937-
if (Options.ConvertSwitchToLookupTable &&
7938-
simplifySwitchLookup(SI, Builder, DTU, DL, TTI))
7939-
return requestResimplify();
7946+
// The conversion of switches to arithmetic or lookup table is disabled in
7947+
// the early optimization pipeline, as it may lose information or make the
7948+
// resulting code harder to analyze.
7949+
if (Options.ConvertSwitchToArithmetic || Options.ConvertSwitchToLookupTable)
7950+
if (simplifySwitchLookup(SI, Builder, DTU, DL, TTI,
7951+
Options.ConvertSwitchToLookupTable))
7952+
return requestResimplify();
79407953

79417954
if (simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))
79427955
return requestResimplify();

llvm/test/Other/new-pm-print-pipeline.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
; CHECK-17: function(print<stack-lifetime><may>,print<stack-lifetime><must>)
5151

5252
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18
53-
; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;no-switch-range-to-icmp;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables>)
53+
; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;no-switch-range-to-icmp;no-switch-to-arithmetic;switch-to-lookup;keep-loops;hoist-common-insts;hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;no-speculate-blocks;no-simplify-cond-branch;no-speculate-unpredictables>)
5454

5555
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,loop-vectorize<interleave-forced-only;vectorize-forced-only>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-19
5656
; CHECK-19: function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,loop-vectorize<interleave-forced-only;vectorize-forced-only;>)

llvm/test/Transforms/PhaseOrdering/switch-to-arithmetic-inlining.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,10 +436,11 @@ bb104: ; preds = %bb102
436436
br label %bb105
437437
}
438438

439+
; Make sure the call is inlined.
439440
define i8 @test2(i8 %x) {
440441
; CHECK-LABEL: define range(i8 0, 53) i8 @test2(
441442
; CHECK-SAME: i8 [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
442-
; CHECK-NEXT: [[CALL:%.*]] = tail call i8 @test(i8 [[X]])
443+
; CHECK-NEXT: [[CALL:%.*]] = tail call range(i8 0, 53) i8 @llvm.umin.i8(i8 [[X]], i8 52)
443444
; CHECK-NEXT: ret i8 [[CALL]]
444445
;
445446
%call = call i8 @test(i8 %x)

llvm/test/Transforms/SimplifyCFG/switch-transformations-no-lut.ll

Lines changed: 68 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2-
; RUN: opt -S -passes='simplifycfg' < %s | FileCheck %s --check-prefix=OPTNOLUT
2+
; RUN: opt -S -passes='simplifycfg<switch-to-arithmetic>' < %s | FileCheck %s --check-prefix=OPTNOLUT
33
; RUN: %if amdgpu-registered-target %{ opt -mtriple=amdgcn--amdpal -S -passes='simplifycfg<switch-to-lookup>' < %s | FileCheck %s --check-prefix=TTINOLUT %}
44
;
55
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
66

77
define i32 @linear_transform_with_default(i32 %x) {
88
; OPTNOLUT-LABEL: define i32 @linear_transform_with_default(
99
; OPTNOLUT-SAME: i32 [[X:%.*]]) {
10-
; OPTNOLUT-NEXT: [[ENTRY:.*]]:
11-
; OPTNOLUT-NEXT: switch i32 [[X]], label %[[END:.*]] [
12-
; OPTNOLUT-NEXT: i32 0, label %[[CASE0:.*]]
13-
; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]]
14-
; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]]
15-
; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]]
16-
; OPTNOLUT-NEXT: ]
17-
; OPTNOLUT: [[CASE0]]:
18-
; OPTNOLUT-NEXT: br label %[[END]]
19-
; OPTNOLUT: [[CASE1]]:
20-
; OPTNOLUT-NEXT: br label %[[END]]
21-
; OPTNOLUT: [[CASE2]]:
22-
; OPTNOLUT-NEXT: br label %[[END]]
23-
; OPTNOLUT: [[CASE3]]:
24-
; OPTNOLUT-NEXT: br label %[[END]]
25-
; OPTNOLUT: [[END]]:
26-
; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 1, %[[CASE0]] ], [ 4, %[[CASE1]] ], [ 7, %[[CASE2]] ], [ 10, %[[CASE3]] ], [ 13, %[[ENTRY]] ]
10+
; OPTNOLUT-NEXT: [[ENTRY:.*:]]
11+
; OPTNOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 4
12+
; OPTNOLUT-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[X]], 3
13+
; OPTNOLUT-NEXT: [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1
14+
; OPTNOLUT-NEXT: [[IDX:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 13
2715
; OPTNOLUT-NEXT: ret i32 [[IDX]]
2816
;
2917
; TTINOLUT-LABEL: define i32 @linear_transform_with_default(
@@ -138,26 +126,8 @@ end:
138126
define i32 @linear_transform_no_default(i32 %x) {
139127
; OPTNOLUT-LABEL: define i32 @linear_transform_no_default(
140128
; OPTNOLUT-SAME: i32 [[X:%.*]]) {
141-
; OPTNOLUT-NEXT: [[ENTRY:.*]]:
142-
; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [
143-
; OPTNOLUT-NEXT: i32 0, label %[[END:.*]]
144-
; OPTNOLUT-NEXT: i32 1, label %[[CASE1:.*]]
145-
; OPTNOLUT-NEXT: i32 2, label %[[CASE2:.*]]
146-
; OPTNOLUT-NEXT: i32 3, label %[[CASE3:.*]]
147-
; OPTNOLUT-NEXT: i32 4, label %[[CASE4:.*]]
148-
; OPTNOLUT-NEXT: ]
149-
; OPTNOLUT: [[CASE1]]:
150-
; OPTNOLUT-NEXT: br label %[[END]]
151-
; OPTNOLUT: [[CASE2]]:
152-
; OPTNOLUT-NEXT: br label %[[END]]
153-
; OPTNOLUT: [[CASE3]]:
154-
; OPTNOLUT-NEXT: br label %[[END]]
155-
; OPTNOLUT: [[CASE4]]:
156-
; OPTNOLUT-NEXT: br label %[[END]]
157-
; OPTNOLUT: [[DEFAULT]]:
158-
; OPTNOLUT-NEXT: unreachable
159-
; OPTNOLUT: [[END]]:
160-
; OPTNOLUT-NEXT: [[SWITCH_IDX_MULT:%.*]] = phi i32 [ 3, %[[CASE1]] ], [ 6, %[[CASE2]] ], [ 9, %[[CASE3]] ], [ 12, %[[CASE4]] ], [ 0, %[[ENTRY]] ]
129+
; OPTNOLUT-NEXT: [[ENTRY:.*:]]
130+
; OPTNOLUT-NEXT: [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[X]], 3
161131
; OPTNOLUT-NEXT: ret i32 [[SWITCH_IDX_MULT]]
162132
;
163133
; TTINOLUT-LABEL: define i32 @linear_transform_no_default(
@@ -350,18 +320,9 @@ end:
350320
define i32 @single_value_withdefault(i32 %x) {
351321
; OPTNOLUT-LABEL: define i32 @single_value_withdefault(
352322
; OPTNOLUT-SAME: i32 [[X:%.*]]) {
353-
; OPTNOLUT-NEXT: [[ENTRY:.*]]:
354-
; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [
355-
; OPTNOLUT-NEXT: i32 0, label %[[END:.*]]
356-
; OPTNOLUT-NEXT: i32 1, label %[[END]]
357-
; OPTNOLUT-NEXT: i32 2, label %[[END]]
358-
; OPTNOLUT-NEXT: i32 3, label %[[END]]
359-
; OPTNOLUT-NEXT: i32 4, label %[[END]]
360-
; OPTNOLUT-NEXT: ]
361-
; OPTNOLUT: [[DEFAULT]]:
362-
; OPTNOLUT-NEXT: br label %[[END]]
363-
; OPTNOLUT: [[END]]:
364-
; OPTNOLUT-NEXT: [[DOT:%.*]] = phi i32 [ 3, %[[DEFAULT]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ]
323+
; OPTNOLUT-NEXT: [[ENTRY:.*:]]
324+
; OPTNOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 5
325+
; OPTNOLUT-NEXT: [[DOT:%.*]] = select i1 [[TMP0]], i32 2, i32 3
365326
; OPTNOLUT-NEXT: ret i32 [[DOT]]
366327
;
367328
; TTINOLUT-LABEL: define i32 @single_value_withdefault(
@@ -401,18 +362,9 @@ end:
401362
define i32 @single_value_no_jump_tables(i32 %x) "no-jump-tables"="true" {
402363
; OPTNOLUT-LABEL: define i32 @single_value_no_jump_tables(
403364
; OPTNOLUT-SAME: i32 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
404-
; OPTNOLUT-NEXT: [[ENTRY:.*]]:
405-
; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [
406-
; OPTNOLUT-NEXT: i32 0, label %[[END:.*]]
407-
; OPTNOLUT-NEXT: i32 1, label %[[END]]
408-
; OPTNOLUT-NEXT: i32 2, label %[[END]]
409-
; OPTNOLUT-NEXT: i32 3, label %[[END]]
410-
; OPTNOLUT-NEXT: i32 4, label %[[END]]
411-
; OPTNOLUT-NEXT: ]
412-
; OPTNOLUT: [[DEFAULT]]:
413-
; OPTNOLUT-NEXT: br label %[[END]]
414-
; OPTNOLUT: [[END]]:
415-
; OPTNOLUT-NEXT: [[IDX:%.*]] = phi i32 [ 3, %[[DEFAULT]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ], [ 2, %[[ENTRY]] ]
365+
; OPTNOLUT-NEXT: [[ENTRY:.*:]]
366+
; OPTNOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X]], 5
367+
; OPTNOLUT-NEXT: [[IDX:%.*]] = select i1 [[TMP0]], i32 2, i32 3
416368
; OPTNOLUT-NEXT: ret i32 [[IDX]]
417369
;
418370
; TTINOLUT-LABEL: define i32 @single_value_no_jump_tables(
@@ -449,6 +401,60 @@ end:
449401
ret i32 %idx
450402
}
451403

404+
define i1 @single_value_with_mask(i32 %x) {
405+
; OPTNOLUT-LABEL: define i1 @single_value_with_mask(
406+
; OPTNOLUT-SAME: i32 [[X:%.*]]) {
407+
; OPTNOLUT-NEXT: [[ENTRY:.*]]:
408+
; OPTNOLUT-NEXT: switch i32 [[X]], label %[[DEFAULT:.*]] [
409+
; OPTNOLUT-NEXT: i32 18, label %[[END:.*]]
410+
; OPTNOLUT-NEXT: i32 21, label %[[END]]
411+
; OPTNOLUT-NEXT: i32 48, label %[[END]]
412+
; OPTNOLUT-NEXT: i32 16, label %[[END]]
413+
; OPTNOLUT-NEXT: ]
414+
; OPTNOLUT: [[DEFAULT]]:
415+
; OPTNOLUT-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 80
416+
; OPTNOLUT-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i1 false, i1 true
417+
; OPTNOLUT-NEXT: br label %[[END]]
418+
; OPTNOLUT: [[END]]:
419+
; OPTNOLUT-NEXT: [[RES:%.*]] = phi i1 [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ false, %[[ENTRY]] ], [ [[SEL]], %[[DEFAULT]] ]
420+
; OPTNOLUT-NEXT: ret i1 [[RES]]
421+
;
422+
; TTINOLUT-LABEL: define i1 @single_value_with_mask(
423+
; TTINOLUT-SAME: i32 [[X:%.*]]) {
424+
; TTINOLUT-NEXT: [[ENTRY:.*]]:
425+
; TTINOLUT-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[X]], 16
426+
; TTINOLUT-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 33
427+
; TTINOLUT-NEXT: [[SWITCH_MASKINDEX:%.*]] = zext i32 [[SWITCH_TABLEIDX]] to i64
428+
; TTINOLUT-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i64 4294967333, [[SWITCH_MASKINDEX]]
429+
; TTINOLUT-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i64 [[SWITCH_SHIFTED]] to i1
430+
; TTINOLUT-NEXT: [[OR_COND:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_LOBIT]], i1 false
431+
; TTINOLUT-NEXT: br i1 [[OR_COND]], label %[[END:.*]], label %[[DEFAULT:.*]]
432+
; TTINOLUT: [[DEFAULT]]:
433+
; TTINOLUT-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 80
434+
; TTINOLUT-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i1 false, i1 true
435+
; TTINOLUT-NEXT: br label %[[END]]
436+
; TTINOLUT: [[END]]:
437+
; TTINOLUT-NEXT: [[RES:%.*]] = phi i1 [ [[SEL]], %[[DEFAULT]] ], [ false, %[[ENTRY]] ]
438+
; TTINOLUT-NEXT: ret i1 [[RES]]
439+
;
440+
entry:
441+
switch i32 %x, label %default [
442+
i32 18, label %end
443+
i32 21, label %end
444+
i32 48, label %end
445+
i32 16, label %end
446+
]
447+
448+
default:
449+
%cmp = icmp eq i32 %x, 80
450+
%sel = select i1 %cmp, i1 false, i1 true
451+
br label %end
452+
453+
end:
454+
%res = phi i1 [ false, %entry ], [ false, %entry ], [ false, %entry ], [ false, %entry ], [ %sel, %default ]
455+
ret i1 %res
456+
}
457+
452458
define i32 @lookup_table(i32 %x) {
453459
; OPTNOLUT-LABEL: define i32 @lookup_table(
454460
; OPTNOLUT-SAME: i32 [[X:%.*]]) {

0 commit comments

Comments
 (0)