xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll (revision 8979ae42769e529b0f6fce3268492ffb49bd54b9)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S | FileCheck %s
3
4declare i32 @f(i32)
5
6define i32 @basic(i32 %x) {
7; CHECK-LABEL: @basic(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
10; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
11; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[DEFAULT:%.*]]
12; CHECK:       common.ret:
13; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[DEFAULT]] ], [ [[TMP1:%.*]], [[A]] ]
14; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
15; CHECK:       default:
16; CHECK-NEXT:    [[TMP0]] = call i32 @f(i32 0)
17; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
18; CHECK:       a:
19; CHECK-NEXT:    [[TMP1]] = call i32 @f(i32 1)
20; CHECK-NEXT:    br label [[COMMON_RET]]
21;
22
23entry:
24  switch i32 %x, label %default [
25  i32 5, label %a
26  i32 6, label %a
27  i32 7, label %a
28  ]
29default:
30  %0 = call i32 @f(i32 0)
31  ret i32 %0
32a:
33  %1 = call i32 @f(i32 1)
34  ret i32 %1
35}
36
37
38define i32 @unreachable(i32 %x) {
39; CHECK-LABEL: @unreachable(
40; CHECK-NEXT:  entry:
41; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
42; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
43; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]]
44; CHECK:       common.ret:
45; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[A]] ], [ [[TMP1:%.*]], [[B]] ]
46; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
47; CHECK:       a:
48; CHECK-NEXT:    [[TMP0]] = call i32 @f(i32 0)
49; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
50; CHECK:       b:
51; CHECK-NEXT:    [[TMP1]] = call i32 @f(i32 1)
52; CHECK-NEXT:    br label [[COMMON_RET]]
53;
54
55entry:
56  switch i32 %x, label %unreachable [
57  i32 5, label %a
58  i32 6, label %a
59  i32 7, label %a
60  i32 10, label %b
61  i32 20, label %b
62  i32 30, label %b
63  i32 40, label %b
64  ]
65unreachable:
66  unreachable
67a:
68  %0 = call i32 @f(i32 0)
69  ret i32 %0
70b:
71  %1 = call i32 @f(i32 1)
72  ret i32 %1
73}
74
75
76define i32 @unreachable2(i32 %x) {
77; CHECK-LABEL: @unreachable2(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -5
80; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
81; CHECK-NEXT:    br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]]
82; CHECK:       common.ret:
83; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[A]] ], [ [[TMP1:%.*]], [[B]] ]
84; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
85; CHECK:       a:
86; CHECK-NEXT:    [[TMP0]] = call i32 @f(i32 0)
87; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
88; CHECK:       b:
89; CHECK-NEXT:    [[TMP1]] = call i32 @f(i32 1)
90; CHECK-NEXT:    br label [[COMMON_RET]]
91;
92
93entry:
94  ; Note: folding the most popular case destination into the default
95  ; would prevent switch-to-icmp here.
96  switch i32 %x, label %unreachable [
97  i32 5, label %a
98  i32 6, label %a
99  i32 7, label %a
100  i32 10, label %b
101  i32 20, label %b
102  ]
103unreachable:
104  unreachable
105a:
106  %0 = call i32 @f(i32 0)
107  ret i32 %0
108b:
109  %1 = call i32 @f(i32 1)
110  ret i32 %1
111}
112
113; This would crash because we did not clean up the
114; default block of the switch before removing the switch.
115
116define void @PR42737(ptr %a, i1 %c) {
117; CHECK-LABEL: @PR42737(
118; CHECK-NEXT:  entry:
119; CHECK-NEXT:    unreachable
120;
121entry:
122  br i1 %c, label %switch, label %else
123
124else:
125  store i32 2, ptr %a
126  br label %switch
127
128switch:
129  %cleanup.dest1 = phi i32 [ 0, %else ], [ 3, %entry ]
130  switch i32 %cleanup.dest1, label %unreach1 [
131  i32 0, label %cleanup1
132  i32 3, label %cleanup2
133  ]
134
135cleanup1:
136  br label %unreach2
137
138cleanup2:
139  br label %unreach2
140
141unreach1:
142  %phi2 = phi i32 [ %cleanup.dest1, %switch ]
143  unreachable
144
145unreach2:
146  unreachable
147}
148
149
150define void @pr53208_single_reachable_dest(i8 %sw, ptr %p0) {
151; CHECK-LABEL: @pr53208_single_reachable_dest(
152; CHECK-NEXT:  group2:
153; CHECK-NEXT:    call void @bar(ptr [[P0:%.*]])
154; CHECK-NEXT:    ret void
155;
156  switch i8 %sw, label %group3 [
157  i8 0, label %group1
158  i8 1, label %group1
159  i8 2, label %group1
160  i8 3, label %group1
161  i8 11, label %group1
162  i8 12, label %group1
163  i8 13, label %group1
164  i8 7, label %group1
165  i8 17, label %group1
166  i8 14, label %group1
167  i8 15, label %group1
168  i8 4, label %group2
169  i8 5, label %group2
170  i8 6, label %group2
171  i8 8, label %group2
172  i8 9, label %group2
173  i8 10, label %group2
174  ]
175
176group1:
177  br label %exit
178
179group2:
180  br label %exit
181
182group3:
183  br label %exit
184
185exit:
186  %phi = phi ptr [ null, %group3 ], [ %p0, %group2 ], [ null, %group1 ]
187  call void @bar(ptr %phi)
188  ret void
189}
190
191declare void @bar(ptr nonnull dereferenceable(4))
192