xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/HoistCode.ll (revision 6b9952759f66c8bc62ef4c6700f586053f009296)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=simplifycfg -hoist-common-insts=true -S | FileCheck %s
3; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -hoist-common-insts=true -S | FileCheck %s
4
5define void @foo(i1 %C, ptr %P) {
6; CHECK-LABEL: @foo(
7; CHECK-NEXT:  common.ret:
8; CHECK-NEXT:    store i32 7, ptr [[P:%.*]], align 4
9; CHECK-NEXT:    ret void
10;
11  br i1 %C, label %T, label %F
12T:              ; preds = %0
13  store i32 7, ptr %P
14  ret void
15F:              ; preds = %0
16  store i32 7, ptr %P
17  ret void
18}
19
20define void @foo_switch(i64 %C, ptr %P) {
21; CHECK-LABEL: @foo_switch(
22; CHECK-NEXT:  common.ret:
23; CHECK-NEXT:    store i32 7, ptr [[P:%.*]], align 4
24; CHECK-NEXT:    ret void
25;
26  switch i64 %C, label %bb0 [
27  i64 1, label %bb1
28  i64 2, label %bb2
29  ]
30bb0:              ; preds = %0
31  store i32 7, ptr %P
32  ret void
33bb1:              ; preds = %0
34  store i32 7, ptr %P
35  ret void
36bb2:              ; preds = %0
37  store i32 7, ptr %P
38  ret void
39}
40
41define float @PR39535min(float %x) {
42; CHECK-LABEL: @PR39535min(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[TOBOOL:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
45; CHECK-NEXT:    [[DOTX:%.*]] = select fast i1 [[TOBOOL]], float 0.000000e+00, float [[X]]
46; CHECK-NEXT:    ret float [[DOTX]]
47;
48entry:
49  %tobool = fcmp une float %x, 0.0
50  br i1 %tobool, label %cond.true, label %cond.false
51
52cond.true:
53  br label %cond.end
54
55cond.false:
56  br label %cond.end
57
58cond.end:
59  %cond = phi fast float [ 0.0, %cond.true ], [ %x, %cond.false ]
60  ret float %cond
61}
62
63define float @PR39535min_switch(i64 %i, float %x) {
64; CHECK-LABEL: @PR39535min_switch(
65; CHECK-NEXT:  entry:
66; CHECK-NEXT:    switch i64 [[I:%.*]], label [[END:%.*]] [
67; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
68; CHECK-NEXT:      i64 2, label [[BB1]]
69; CHECK-NEXT:    ]
70; CHECK:       bb1:
71; CHECK-NEXT:    br label [[END]]
72; CHECK:       end:
73; CHECK-NEXT:    [[COND:%.*]] = phi fast float [ [[X:%.*]], [[BB1]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
74; CHECK-NEXT:    ret float [[COND]]
75;
76entry:
77  switch i64 %i, label %bb0 [
78  i64 1, label %bb1
79  i64 2, label %bb2
80  ]
81
82bb0:
83  br label %end
84
85bb1:
86  br label %end
87
88bb2:
89  br label %end
90
91end:
92  %cond = phi fast float [ 0.0, %bb0 ], [ %x, %bb1 ], [ %x, %bb2 ]
93  ret float %cond
94}
95
96define i32 @hoist_zext_flags_preserve(i1 %C, i8 %x) {
97; CHECK-LABEL: @hoist_zext_flags_preserve(
98; CHECK-NEXT:  common.ret:
99; CHECK-NEXT:    [[Z1:%.*]] = zext nneg i8 [[X:%.*]] to i32
100; CHECK-NEXT:    ret i32 [[Z1]]
101;
102  br i1 %C, label %T, label %F
103T:
104  %z1 = zext nneg i8 %x to i32
105  ret i32 %z1
106F:
107  %z2 = zext nneg i8 %x to i32
108  ret i32 %z2
109}
110
111define i32 @hoist_zext_flags_drop(i1 %C, i8 %x) {
112; CHECK-LABEL: @hoist_zext_flags_drop(
113; CHECK-NEXT:  common.ret:
114; CHECK-NEXT:    [[Z1:%.*]] = zext i8 [[X:%.*]] to i32
115; CHECK-NEXT:    ret i32 [[Z1]]
116;
117  br i1 %C, label %T, label %F
118T:
119  %z1 = zext nneg i8 %x to i32
120  ret i32 %z1
121F:
122  %z2 = zext i8 %x to i32
123  ret i32 %z2
124}
125
126
127define float @hoist_uitofp_flags_preserve(i1 %C, i8 %x) {
128; CHECK-LABEL: @hoist_uitofp_flags_preserve(
129; CHECK-NEXT:  common.ret:
130; CHECK-NEXT:    [[Z1:%.*]] = uitofp nneg i8 [[X:%.*]] to float
131; CHECK-NEXT:    ret float [[Z1]]
132;
133  br i1 %C, label %T, label %F
134T:
135  %z1 = uitofp nneg i8 %x to float
136  ret float %z1
137F:
138  %z2 = uitofp nneg i8 %x to float
139  ret float %z2
140}
141
142define float @hoist_uitofp_flags_drop(i1 %C, i8 %x) {
143; CHECK-LABEL: @hoist_uitofp_flags_drop(
144; CHECK-NEXT:  common.ret:
145; CHECK-NEXT:    [[Z1:%.*]] = uitofp i8 [[X:%.*]] to float
146; CHECK-NEXT:    ret float [[Z1]]
147;
148  br i1 %C, label %T, label %F
149T:
150  %z1 = uitofp nneg i8 %x to float
151  ret float %z1
152F:
153  %z2 = uitofp i8 %x to float
154  ret float %z2
155}
156
157define i32 @hoist_or_flags_preserve(i1 %C, i32 %x, i32 %y) {
158; CHECK-LABEL: @hoist_or_flags_preserve(
159; CHECK-NEXT:  common.ret:
160; CHECK-NEXT:    [[Z1:%.*]] = or disjoint i32 [[X:%.*]], [[Y:%.*]]
161; CHECK-NEXT:    ret i32 [[Z1]]
162;
163  br i1 %C, label %T, label %F
164T:
165  %z1 = or disjoint i32 %x, %y
166  ret i32 %z1
167F:
168  %z2 = or disjoint i32 %x, %y
169  ret i32 %z2
170}
171
172define i32 @hoist_or_flags_drop(i1 %C, i32 %x, i32 %y) {
173; CHECK-LABEL: @hoist_or_flags_drop(
174; CHECK-NEXT:  common.ret:
175; CHECK-NEXT:    [[Z1:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
176; CHECK-NEXT:    ret i32 [[Z1]]
177;
178  br i1 %C, label %T, label %F
179T:
180  %z1 = or i32 %x, %y
181  ret i32 %z1
182F:
183  %z2 = or disjoint i32 %x, %y
184  ret i32 %z2
185}
186
187define i16 @hoist_trunc_flags_preserve(i1 %C, i32 %x) {
188; CHECK-LABEL: @hoist_trunc_flags_preserve(
189; CHECK-NEXT:  common.ret:
190; CHECK-NEXT:    [[Z1:%.*]] = trunc nuw nsw i32 [[X:%.*]] to i16
191; CHECK-NEXT:    ret i16 [[Z1]]
192;
193  br i1 %C, label %T, label %F
194T:
195  %z1 = trunc nsw nuw i32 %x to i16
196  ret i16 %z1
197F:
198  %z2 = trunc nsw nuw i32 %x to i16
199  ret i16 %z2
200}
201
202define i16 @hoist_trunc_flags_drop(i1 %C, i32 %x) {
203; CHECK-LABEL: @hoist_trunc_flags_drop(
204; CHECK-NEXT:  common.ret:
205; CHECK-NEXT:    [[Z1:%.*]] = trunc i32 [[X:%.*]] to i16
206; CHECK-NEXT:    ret i16 [[Z1]]
207;
208  br i1 %C, label %T, label %F
209T:
210  %z1 = trunc i32 %x to i16
211  ret i16 %z1
212F:
213  %z2 = trunc nsw nuw i32 %x to i16
214  ret i16 %z2
215}
216
217define ptr @hoist_gep_flags_both_nuw(i1 %C, ptr %p) {
218; CHECK-LABEL: @hoist_gep_flags_both_nuw(
219; CHECK-NEXT:  common.ret:
220; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr nuw i8, ptr [[P:%.*]], i64 1
221; CHECK-NEXT:    ret ptr [[GEP1]]
222;
223  br i1 %C, label %T, label %F
224T:
225  %gep1 = getelementptr nuw i8, ptr %p, i64 1
226  ret ptr %gep1
227F:
228  %gep2 = getelementptr nuw i8, ptr %p, i64 1
229  ret ptr %gep2
230}
231
232define ptr @hoist_gep_flags_both_nusw(i1 %C, ptr %p) {
233; CHECK-LABEL: @hoist_gep_flags_both_nusw(
234; CHECK-NEXT:  common.ret:
235; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 1
236; CHECK-NEXT:    ret ptr [[GEP1]]
237;
238  br i1 %C, label %T, label %F
239T:
240  %gep1 = getelementptr nusw i8, ptr %p, i64 1
241  ret ptr %gep1
242F:
243  %gep2 = getelementptr nusw i8, ptr %p, i64 1
244  ret ptr %gep2
245}
246
247define ptr @hoist_gep_flags_intersect1(i1 %C, ptr %p) {
248; CHECK-LABEL: @hoist_gep_flags_intersect1(
249; CHECK-NEXT:  common.ret:
250; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr nusw i8, ptr [[P:%.*]], i64 1
251; CHECK-NEXT:    ret ptr [[GEP1]]
252;
253  br i1 %C, label %T, label %F
254T:
255  %gep1 = getelementptr inbounds nuw i8, ptr %p, i64 1
256  ret ptr %gep1
257F:
258  %gep2 = getelementptr nusw i8, ptr %p, i64 1
259  ret ptr %gep2
260}
261
262define ptr @hoist_gep_flags_intersect2(i1 %C, ptr %p) {
263; CHECK-LABEL: @hoist_gep_flags_intersect2(
264; CHECK-NEXT:  common.ret:
265; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1
266; CHECK-NEXT:    ret ptr [[GEP1]]
267;
268  br i1 %C, label %T, label %F
269T:
270  %gep1 = getelementptr inbounds i8, ptr %p, i64 1
271  ret ptr %gep1
272F:
273  %gep2 = getelementptr nuw i8, ptr %p, i64 1
274  ret ptr %gep2
275}
276
277define i1 @hoist_icmp_flags_preserve(i1 %C, i32 %x, i32 %y) {
278; CHECK-LABEL: @hoist_icmp_flags_preserve(
279; CHECK-NEXT:  common.ret:
280; CHECK-NEXT:    [[Z1:%.*]] = icmp samesign ult i32 [[X:%.*]], [[Y:%.*]]
281; CHECK-NEXT:    ret i1 [[Z1]]
282;
283  br i1 %C, label %T, label %F
284T:
285  %z1 = icmp samesign ult i32 %x, %y
286  ret i1 %z1
287F:
288  %z2 = icmp samesign ult i32 %x, %y
289  ret i1 %z2
290}
291
292define i1 @hoist_icmp_flags_drop(i1 %C, i32 %x, i32 %y) {
293; CHECK-LABEL: @hoist_icmp_flags_drop(
294; CHECK-NEXT:  common.ret:
295; CHECK-NEXT:    [[Z1:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
296; CHECK-NEXT:    ret i1 [[Z1]]
297;
298  br i1 %C, label %T, label %F
299T:
300  %z1 = icmp ult i32 %x, %y
301  ret i1 %z1
302F:
303  %z2 = icmp samesign ult i32 %x, %y
304  ret i1 %z2
305}
306