Skip to content

Commit effb540

Browse files
committed
[SimplifyCFG] Allow some switch optimizations early in the pipeline
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 llvm#156477, which originally included this change as well.
1 parent 53a397a commit effb540

File tree

2 files changed

+29
-69
lines changed

2 files changed

+29
-69
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 16 additions & 8 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,11 @@ 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+
// and bit maps, as they may inhibit further optimization.
7287+
if (!ConvertSwitchToLookupTable && (AnyLookupTables || AnyBitMaps))
7288+
return false;
7289+
72777290
Builder.SetInsertPoint(SI);
72787291
// TableIndex is the switch condition - TableIndexOffset if we don't
72797292
// use the condition directly
@@ -7929,13 +7942,8 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
79297942
if (Options.ForwardSwitchCondToPhi && forwardSwitchConditionToPHI(SI))
79307943
return requestResimplify();
79317944

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))
7945+
if (simplifySwitchLookup(SI, Builder, DTU, DL, TTI,
7946+
Options.ConvertSwitchToLookupTable))
79397947
return requestResimplify();
79407948

79417949
if (simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))

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

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,11 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
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(

0 commit comments

Comments
 (0)