173
|
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
150
|
2 ; Test the basic functionality of speculating around PHI nodes based on reduced
|
|
3 ; cost of the constant operands to the PHI nodes using the x86 cost model.
|
|
4 ;
|
|
5 ; REQUIRES: x86-registered-target
|
|
6 ; RUN: opt -S -passes=spec-phis < %s | FileCheck %s
|
|
7
|
|
8 target triple = "x86_64-unknown-unknown"
|
|
9
|
|
10 define i32 @test_basic(i1 %flag, i32 %arg) {
|
173
|
11 ; CHECK-LABEL: @test_basic(
|
|
12 ; CHECK-NEXT: entry:
|
|
13 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
14 ; CHECK: a:
|
|
15 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[ARG:%.*]], 7
|
|
16 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
17 ; CHECK: b:
|
|
18 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[ARG]], 11
|
|
19 ; CHECK-NEXT: br label [[EXIT]]
|
|
20 ; CHECK: exit:
|
|
21 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
22 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
23 ;
|
150
|
24 entry:
|
|
25 br i1 %flag, label %a, label %b
|
|
26
|
|
27 a:
|
|
28 br label %exit
|
|
29
|
|
30 b:
|
|
31 br label %exit
|
|
32
|
|
33 exit:
|
|
34 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
35 %sum = add i32 %arg, %p
|
|
36 ret i32 %sum
|
|
37 }
|
|
38
|
|
39 ; Check that we handle commuted operands and get the constant onto the RHS.
|
|
40 define i32 @test_commuted(i1 %flag, i32 %arg) {
|
173
|
41 ; CHECK-LABEL: @test_commuted(
|
|
42 ; CHECK-NEXT: entry:
|
|
43 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
44 ; CHECK: a:
|
|
45 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[ARG:%.*]], 7
|
|
46 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
47 ; CHECK: b:
|
|
48 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[ARG]], 11
|
|
49 ; CHECK-NEXT: br label [[EXIT]]
|
|
50 ; CHECK: exit:
|
|
51 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
52 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
53 ;
|
150
|
54 entry:
|
|
55 br i1 %flag, label %a, label %b
|
|
56
|
|
57 a:
|
|
58 br label %exit
|
|
59
|
|
60 b:
|
|
61 br label %exit
|
|
62
|
|
63 exit:
|
|
64 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
65 %sum = add i32 %p, %arg
|
|
66 ret i32 %sum
|
|
67 }
|
|
68
|
|
69 define i32 @test_split_crit_edge(i1 %flag, i32 %arg) {
|
173
|
70 ; CHECK-LABEL: @test_split_crit_edge(
|
|
71 ; CHECK-NEXT: entry:
|
|
72 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[ENTRY_EXIT_CRIT_EDGE:%.*]], label [[A:%.*]]
|
|
73 ; CHECK: entry.exit_crit_edge:
|
|
74 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[ARG:%.*]], 7
|
|
75 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
76 ; CHECK: a:
|
|
77 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[ARG]], 11
|
|
78 ; CHECK-NEXT: br label [[EXIT]]
|
|
79 ; CHECK: exit:
|
|
80 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[ENTRY_EXIT_CRIT_EDGE]] ], [ [[SUM_1]], [[A]] ]
|
|
81 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
82 ;
|
150
|
83 entry:
|
|
84 br i1 %flag, label %exit, label %a
|
|
85
|
|
86 a:
|
|
87 br label %exit
|
|
88
|
|
89 exit:
|
|
90 %p = phi i32 [ 7, %entry ], [ 11, %a ]
|
|
91 %sum = add i32 %arg, %p
|
|
92 ret i32 %sum
|
|
93 }
|
|
94
|
|
95 define i32 @test_no_spec_dominating_inst(i1 %flag, i32* %ptr) {
|
173
|
96 ; CHECK-LABEL: @test_no_spec_dominating_inst(
|
|
97 ; CHECK-NEXT: entry:
|
|
98 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32* [[PTR:%.*]]
|
|
99 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
100 ; CHECK: a:
|
|
101 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[LOAD]], 7
|
|
102 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
103 ; CHECK: b:
|
|
104 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[LOAD]], 11
|
|
105 ; CHECK-NEXT: br label [[EXIT]]
|
|
106 ; CHECK: exit:
|
|
107 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
108 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
109 ;
|
150
|
110 entry:
|
|
111 %load = load i32, i32* %ptr
|
|
112 br i1 %flag, label %a, label %b
|
|
113
|
|
114 a:
|
|
115 br label %exit
|
|
116
|
|
117 b:
|
|
118 br label %exit
|
|
119
|
|
120 exit:
|
|
121 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
122 %sum = add i32 %load, %p
|
|
123 ret i32 %sum
|
|
124 }
|
|
125
|
|
126 ; We have special logic handling PHI nodes, make sure it doesn't get confused
|
|
127 ; by a dominating PHI.
|
|
128 define i32 @test_no_spec_dominating_phi(i1 %flag1, i1 %flag2, i32 %x, i32 %y) {
|
173
|
129 ; CHECK-LABEL: @test_no_spec_dominating_phi(
|
|
130 ; CHECK-NEXT: entry:
|
|
131 ; CHECK-NEXT: br i1 [[FLAG1:%.*]], label [[X_BLOCK:%.*]], label [[Y_BLOCK:%.*]]
|
|
132 ; CHECK: x.block:
|
|
133 ; CHECK-NEXT: br label [[MERGE:%.*]]
|
|
134 ; CHECK: y.block:
|
|
135 ; CHECK-NEXT: br label [[MERGE]]
|
|
136 ; CHECK: merge:
|
|
137 ; CHECK-NEXT: [[XY_PHI:%.*]] = phi i32 [ [[X:%.*]], [[X_BLOCK]] ], [ [[Y:%.*]], [[Y_BLOCK]] ]
|
|
138 ; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
139 ; CHECK: a:
|
|
140 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[XY_PHI]], 7
|
|
141 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
142 ; CHECK: b:
|
|
143 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[XY_PHI]], 11
|
|
144 ; CHECK-NEXT: br label [[EXIT]]
|
|
145 ; CHECK: exit:
|
|
146 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
147 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
148 ;
|
150
|
149 entry:
|
|
150 br i1 %flag1, label %x.block, label %y.block
|
|
151
|
|
152 x.block:
|
|
153 br label %merge
|
|
154
|
|
155 y.block:
|
|
156 br label %merge
|
|
157
|
|
158 merge:
|
|
159 %xy.phi = phi i32 [ %x, %x.block ], [ %y, %y.block ]
|
|
160 br i1 %flag2, label %a, label %b
|
|
161
|
|
162 a:
|
|
163 br label %exit
|
|
164
|
|
165 b:
|
|
166 br label %exit
|
|
167
|
|
168 exit:
|
|
169 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
170 %sum = add i32 %xy.phi, %p
|
|
171 ret i32 %sum
|
|
172 }
|
|
173
|
|
174 ; Ensure that we will speculate some number of "free" instructions on the given
|
|
175 ; architecture even though they are unrelated to the PHI itself.
|
|
176 define i32 @test_speculate_free_insts(i1 %flag, i64 %arg) {
|
173
|
177 ; CHECK-LABEL: @test_speculate_free_insts(
|
|
178 ; CHECK-NEXT: entry:
|
|
179 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
180 ; CHECK: a:
|
|
181 ; CHECK-NEXT: [[T1_0:%.*]] = trunc i64 [[ARG:%.*]] to i48
|
|
182 ; CHECK-NEXT: [[T2_0:%.*]] = trunc i48 [[T1_0]] to i32
|
|
183 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[T2_0]], 7
|
|
184 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
185 ; CHECK: b:
|
|
186 ; CHECK-NEXT: [[T1_1:%.*]] = trunc i64 [[ARG]] to i48
|
|
187 ; CHECK-NEXT: [[T2_1:%.*]] = trunc i48 [[T1_1]] to i32
|
|
188 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[T2_1]], 11
|
|
189 ; CHECK-NEXT: br label [[EXIT]]
|
|
190 ; CHECK: exit:
|
|
191 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
192 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
193 ;
|
150
|
194 entry:
|
|
195 br i1 %flag, label %a, label %b
|
|
196
|
|
197 a:
|
|
198 br label %exit
|
|
199
|
|
200 b:
|
|
201 br label %exit
|
|
202
|
|
203 exit:
|
|
204 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
205 %t1 = trunc i64 %arg to i48
|
|
206 %t2 = trunc i48 %t1 to i32
|
|
207 %sum = add i32 %t2, %p
|
|
208 ret i32 %sum
|
|
209 }
|
|
210
|
|
211 define i32 @test_speculate_free_phis(i1 %flag, i32 %arg1, i32 %arg2) {
|
173
|
212 ; CHECK-LABEL: @test_speculate_free_phis(
|
|
213 ; CHECK-NEXT: entry:
|
|
214 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
215 ; CHECK: a:
|
|
216 ; CHECK-NEXT: [[SUM_0:%.*]] = add i32 [[ARG1:%.*]], 7
|
|
217 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
218 ; CHECK: b:
|
|
219 ; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[ARG2:%.*]], 11
|
|
220 ; CHECK-NEXT: br label [[EXIT]]
|
|
221 ; CHECK: exit:
|
|
222 ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi i32 [ [[SUM_0]], [[A]] ], [ [[SUM_1]], [[B]] ]
|
|
223 ; CHECK-NEXT: [[P2:%.*]] = phi i32 [ [[ARG1]], [[A]] ], [ [[ARG2]], [[B]] ]
|
|
224 ; CHECK-NEXT: ret i32 [[SUM_PHI]]
|
|
225 ;
|
150
|
226 entry:
|
|
227 br i1 %flag, label %a, label %b
|
|
228
|
|
229 a:
|
|
230 br label %exit
|
|
231
|
|
232 b:
|
|
233 br label %exit
|
|
234
|
173
|
235 ; We don't DCE the now unused PHI node...
|
150
|
236 exit:
|
|
237 %p1 = phi i32 [ 7, %a ], [ 11, %b ]
|
|
238 %p2 = phi i32 [ %arg1, %a ], [ %arg2, %b ]
|
|
239 %sum = add i32 %p2, %p1
|
|
240 ret i32 %sum
|
|
241 }
|
|
242
|
|
243 ; We shouldn't speculate multiple uses even if each individually looks
|
|
244 ; profitable because of the total cost.
|
|
245 define i32 @test_no_spec_multi_uses(i1 %flag, i32 %arg1, i32 %arg2, i32 %arg3) {
|
173
|
246 ; CHECK-LABEL: @test_no_spec_multi_uses(
|
|
247 ; CHECK-NEXT: entry:
|
|
248 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
249 ; CHECK: a:
|
|
250 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
251 ; CHECK: b:
|
|
252 ; CHECK-NEXT: br label [[EXIT]]
|
|
253 ; CHECK: exit:
|
|
254 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A]] ], [ 11, [[B]] ]
|
|
255 ; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[ARG1:%.*]], [[P]]
|
|
256 ; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ARG2:%.*]], [[P]]
|
|
257 ; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ARG3:%.*]], [[P]]
|
|
258 ; CHECK-NEXT: [[SUM1:%.*]] = add i32 [[ADD1]], [[ADD2]]
|
|
259 ; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[SUM1]], [[ADD3]]
|
|
260 ; CHECK-NEXT: ret i32 [[SUM2]]
|
|
261 ;
|
150
|
262 entry:
|
|
263 br i1 %flag, label %a, label %b
|
|
264
|
|
265 a:
|
|
266 br label %exit
|
|
267
|
|
268 b:
|
|
269 br label %exit
|
|
270
|
|
271 exit:
|
|
272 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
273 %add1 = add i32 %arg1, %p
|
|
274 %add2 = add i32 %arg2, %p
|
|
275 %add3 = add i32 %arg3, %p
|
|
276 %sum1 = add i32 %add1, %add2
|
|
277 %sum2 = add i32 %sum1, %add3
|
|
278 ret i32 %sum2
|
|
279 }
|
|
280
|
|
281 define i32 @test_multi_phis1(i1 %flag, i32 %arg) {
|
173
|
282 ; CHECK-LABEL: @test_multi_phis1(
|
|
283 ; CHECK-NEXT: entry:
|
|
284 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
285 ; CHECK: a:
|
|
286 ; CHECK-NEXT: [[SUM1_0:%.*]] = add i32 [[ARG:%.*]], 1
|
|
287 ; CHECK-NEXT: [[SUM2_0:%.*]] = add i32 [[SUM1_0]], 3
|
|
288 ; CHECK-NEXT: [[SUM3_0:%.*]] = add i32 [[SUM2_0]], 5
|
|
289 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
290 ; CHECK: b:
|
|
291 ; CHECK-NEXT: [[SUM1_1:%.*]] = add i32 [[ARG]], 2
|
|
292 ; CHECK-NEXT: [[SUM2_1:%.*]] = add i32 [[SUM1_1]], 4
|
|
293 ; CHECK-NEXT: [[SUM3_1:%.*]] = add i32 [[SUM2_1]], 6
|
|
294 ; CHECK-NEXT: br label [[EXIT]]
|
|
295 ; CHECK: exit:
|
|
296 ; CHECK-NEXT: [[SUM3_PHI:%.*]] = phi i32 [ [[SUM3_0]], [[A]] ], [ [[SUM3_1]], [[B]] ]
|
|
297 ; CHECK-NEXT: ret i32 [[SUM3_PHI]]
|
|
298 ;
|
150
|
299 entry:
|
|
300 br i1 %flag, label %a, label %b
|
|
301
|
|
302 a:
|
|
303 br label %exit
|
|
304
|
|
305 b:
|
|
306 br label %exit
|
|
307
|
|
308 exit:
|
|
309 %p1 = phi i32 [ 1, %a ], [ 2, %b ]
|
|
310 %p2 = phi i32 [ 3, %a ], [ 4, %b ]
|
|
311 %p3 = phi i32 [ 5, %a ], [ 6, %b ]
|
|
312 %sum1 = add i32 %arg, %p1
|
|
313 %sum2 = add i32 %sum1, %p2
|
|
314 %sum3 = add i32 %sum2, %p3
|
|
315 ret i32 %sum3
|
|
316 }
|
|
317
|
|
318 ; Check that the order of the PHIs doesn't impact the behavior.
|
|
319 define i32 @test_multi_phis2(i1 %flag, i32 %arg) {
|
173
|
320 ; CHECK-LABEL: @test_multi_phis2(
|
|
321 ; CHECK-NEXT: entry:
|
|
322 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
323 ; CHECK: a:
|
|
324 ; CHECK-NEXT: [[SUM1_0:%.*]] = add i32 [[ARG:%.*]], 1
|
|
325 ; CHECK-NEXT: [[SUM2_0:%.*]] = add i32 [[SUM1_0]], 3
|
|
326 ; CHECK-NEXT: [[SUM3_0:%.*]] = add i32 [[SUM2_0]], 5
|
|
327 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
328 ; CHECK: b:
|
|
329 ; CHECK-NEXT: [[SUM1_1:%.*]] = add i32 [[ARG]], 2
|
|
330 ; CHECK-NEXT: [[SUM2_1:%.*]] = add i32 [[SUM1_1]], 4
|
|
331 ; CHECK-NEXT: [[SUM3_1:%.*]] = add i32 [[SUM2_1]], 6
|
|
332 ; CHECK-NEXT: br label [[EXIT]]
|
|
333 ; CHECK: exit:
|
|
334 ; CHECK-NEXT: [[SUM3_PHI:%.*]] = phi i32 [ [[SUM3_0]], [[A]] ], [ [[SUM3_1]], [[B]] ]
|
|
335 ; CHECK-NEXT: ret i32 [[SUM3_PHI]]
|
|
336 ;
|
150
|
337 entry:
|
|
338 br i1 %flag, label %a, label %b
|
|
339
|
|
340 a:
|
|
341 br label %exit
|
|
342
|
|
343 b:
|
|
344 br label %exit
|
|
345
|
|
346 exit:
|
|
347 %p3 = phi i32 [ 5, %a ], [ 6, %b ]
|
|
348 %p2 = phi i32 [ 3, %a ], [ 4, %b ]
|
|
349 %p1 = phi i32 [ 1, %a ], [ 2, %b ]
|
|
350 %sum1 = add i32 %arg, %p1
|
|
351 %sum2 = add i32 %sum1, %p2
|
|
352 %sum3 = add i32 %sum2, %p3
|
|
353 ret i32 %sum3
|
|
354 }
|
|
355
|
|
356 define i32 @test_no_spec_indirectbr(i1 %flag, i32 %arg) {
|
173
|
357 ; CHECK-LABEL: @test_no_spec_indirectbr(
|
|
358 ; CHECK-NEXT: entry:
|
|
359 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
360 ; CHECK: a:
|
|
361 ; CHECK-NEXT: indirectbr i8* undef, [label %exit]
|
|
362 ; CHECK: b:
|
|
363 ; CHECK-NEXT: indirectbr i8* undef, [label %exit]
|
|
364 ; CHECK: exit:
|
|
365 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A]] ], [ 11, [[B]] ]
|
|
366 ; CHECK-NEXT: [[SUM:%.*]] = add i32 [[ARG:%.*]], [[P]]
|
|
367 ; CHECK-NEXT: ret i32 [[SUM]]
|
|
368 ;
|
150
|
369 entry:
|
|
370 br i1 %flag, label %a, label %b
|
|
371
|
|
372 a:
|
|
373 indirectbr i8* undef, [label %exit]
|
|
374
|
|
375 b:
|
|
376 indirectbr i8* undef, [label %exit]
|
|
377
|
|
378 exit:
|
|
379 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
380 %sum = add i32 %arg, %p
|
|
381 ret i32 %sum
|
|
382 }
|
|
383
|
|
384 declare void @g()
|
|
385
|
|
386 declare i32 @__gxx_personality_v0(...)
|
|
387
|
|
388 ; FIXME: We should be able to handle this case -- only the exceptional edge is
|
|
389 ; impossible to split.
|
|
390 define i32 @test_no_spec_invoke_continue(i1 %flag, i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
173
|
391 ; CHECK-LABEL: @test_no_spec_invoke_continue(
|
|
392 ; CHECK-NEXT: entry:
|
|
393 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
394 ; CHECK: a:
|
|
395 ; CHECK-NEXT: invoke void @g()
|
|
396 ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[LPAD:%.*]]
|
|
397 ; CHECK: b:
|
|
398 ; CHECK-NEXT: invoke void @g()
|
|
399 ; CHECK-NEXT: to label [[EXIT]] unwind label [[LPAD]]
|
|
400 ; CHECK: exit:
|
|
401 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A]] ], [ 11, [[B]] ]
|
|
402 ; CHECK-NEXT: [[SUM:%.*]] = add i32 [[ARG:%.*]], [[P]]
|
|
403 ; CHECK-NEXT: ret i32 [[SUM]]
|
|
404 ; CHECK: lpad:
|
|
405 ; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
|
|
406 ; CHECK-NEXT: cleanup
|
|
407 ; CHECK-NEXT: resume { i8*, i32 } undef
|
|
408 ;
|
150
|
409 entry:
|
|
410 br i1 %flag, label %a, label %b
|
|
411
|
|
412 a:
|
|
413 invoke void @g()
|
173
|
414 to label %exit unwind label %lpad
|
150
|
415
|
|
416 b:
|
|
417 invoke void @g()
|
173
|
418 to label %exit unwind label %lpad
|
150
|
419
|
|
420 exit:
|
|
421 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
422 %sum = add i32 %arg, %p
|
|
423 ret i32 %sum
|
|
424
|
|
425 lpad:
|
|
426 %lp = landingpad { i8*, i32 }
|
173
|
427 cleanup
|
150
|
428 resume { i8*, i32 } undef
|
|
429 }
|
|
430
|
|
431 define i32 @test_no_spec_landingpad(i32 %arg, i32* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
|
173
|
432 ; CHECK-LABEL: @test_no_spec_landingpad(
|
|
433 ; CHECK-NEXT: entry:
|
|
434 ; CHECK-NEXT: invoke void @g()
|
|
435 ; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
|
|
436 ; CHECK: invoke.cont:
|
|
437 ; CHECK-NEXT: invoke void @g()
|
|
438 ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[LPAD]]
|
|
439 ; CHECK: lpad:
|
|
440 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[ENTRY:%.*]] ], [ 11, [[INVOKE_CONT]] ]
|
|
441 ; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
|
|
442 ; CHECK-NEXT: cleanup
|
|
443 ; CHECK-NEXT: [[SUM:%.*]] = add i32 [[ARG:%.*]], [[P]]
|
|
444 ; CHECK-NEXT: store i32 [[SUM]], i32* [[PTR:%.*]]
|
|
445 ; CHECK-NEXT: resume { i8*, i32 } undef
|
|
446 ; CHECK: exit:
|
|
447 ; CHECK-NEXT: ret i32 0
|
|
448 ;
|
150
|
449 entry:
|
|
450 invoke void @g()
|
173
|
451 to label %invoke.cont unwind label %lpad
|
150
|
452
|
|
453 invoke.cont:
|
|
454 invoke void @g()
|
173
|
455 to label %exit unwind label %lpad
|
150
|
456
|
|
457 lpad:
|
|
458 %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
|
|
459 %lp = landingpad { i8*, i32 }
|
173
|
460 cleanup
|
150
|
461 %sum = add i32 %arg, %p
|
|
462 store i32 %sum, i32* %ptr
|
|
463 resume { i8*, i32 } undef
|
|
464
|
|
465 exit:
|
|
466 ret i32 0
|
|
467 }
|
|
468
|
|
469 declare i32 @__CxxFrameHandler3(...)
|
|
470
|
|
471 define i32 @test_no_spec_cleanuppad(i32 %arg, i32* %ptr) personality i32 (...)* @__CxxFrameHandler3 {
|
173
|
472 ; CHECK-LABEL: @test_no_spec_cleanuppad(
|
|
473 ; CHECK-NEXT: entry:
|
|
474 ; CHECK-NEXT: invoke void @g()
|
|
475 ; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
|
|
476 ; CHECK: invoke.cont:
|
|
477 ; CHECK-NEXT: invoke void @g()
|
|
478 ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[LPAD]]
|
|
479 ; CHECK: lpad:
|
|
480 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[ENTRY:%.*]] ], [ 11, [[INVOKE_CONT]] ]
|
|
481 ; CHECK-NEXT: [[CP:%.*]] = cleanuppad within none []
|
|
482 ; CHECK-NEXT: [[SUM:%.*]] = add i32 [[ARG:%.*]], [[P]]
|
|
483 ; CHECK-NEXT: store i32 [[SUM]], i32* [[PTR:%.*]]
|
|
484 ; CHECK-NEXT: cleanupret from [[CP]] unwind to caller
|
|
485 ; CHECK: exit:
|
|
486 ; CHECK-NEXT: ret i32 0
|
|
487 ;
|
150
|
488 entry:
|
|
489 invoke void @g()
|
173
|
490 to label %invoke.cont unwind label %lpad
|
150
|
491
|
|
492 invoke.cont:
|
|
493 invoke void @g()
|
173
|
494 to label %exit unwind label %lpad
|
150
|
495
|
|
496 lpad:
|
|
497 %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
|
|
498 %cp = cleanuppad within none []
|
|
499 %sum = add i32 %arg, %p
|
|
500 store i32 %sum, i32* %ptr
|
|
501 cleanupret from %cp unwind to caller
|
|
502
|
|
503 exit:
|
|
504 ret i32 0
|
|
505 }
|
|
506
|
|
507 ; Check that we don't fall over when confronted with seemingly reasonable code
|
|
508 ; for us to handle but in an unreachable region and with non-PHI use-def
|
|
509 ; cycles.
|
|
510 define i32 @test_unreachable_non_phi_cycles(i1 %flag, i32 %arg) {
|
173
|
511 ; CHECK-LABEL: @test_unreachable_non_phi_cycles(
|
|
512 ; CHECK-NEXT: entry:
|
|
513 ; CHECK-NEXT: ret i32 42
|
|
514 ; CHECK: a:
|
|
515 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
516 ; CHECK: b:
|
|
517 ; CHECK-NEXT: br label [[EXIT]]
|
|
518 ; CHECK: exit:
|
|
519 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 7, [[A:%.*]] ], [ 11, [[B:%.*]] ]
|
|
520 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SUM:%.*]] to i64
|
|
521 ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[ZEXT]] to i32
|
|
522 ; CHECK-NEXT: [[SUM]] = add i32 [[TRUNC]], [[P]]
|
|
523 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[A]], label [[B]]
|
|
524 ;
|
150
|
525 entry:
|
|
526 ret i32 42
|
|
527
|
|
528 a:
|
|
529 br label %exit
|
|
530
|
|
531 b:
|
|
532 br label %exit
|
|
533
|
|
534 exit:
|
|
535 %p = phi i32 [ 7, %a ], [ 11, %b ]
|
|
536 %zext = zext i32 %sum to i64
|
|
537 %trunc = trunc i64 %zext to i32
|
|
538 %sum = add i32 %trunc, %p
|
|
539 br i1 %flag, label %a, label %b
|
|
540 }
|
|
541
|
|
542 ; Check that we don't speculate in the face of an expensive immediate. There
|
|
543 ; are two reasons this should never speculate. First, even a local analysis
|
|
544 ; should fail because it makes some paths (%a) potentially more expensive due
|
|
545 ; to multiple uses of the immediate. Additionally, when we go to speculate the
|
|
546 ; instructions, their cost will also be too high.
|
|
547 ; FIXME: The goal is really to test the first property, but there doesn't
|
|
548 ; happen to be any way to use free-to-speculate instructions here so that it
|
|
549 ; would be the only interesting property.
|
|
550 define i64 @test_expensive_imm(i32 %flag, i64 %arg) {
|
173
|
551 ; CHECK-LABEL: @test_expensive_imm(
|
|
552 ; CHECK-NEXT: entry:
|
|
553 ; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[A:%.*]] [
|
|
554 ; CHECK-NEXT: i32 1, label [[B:%.*]]
|
|
555 ; CHECK-NEXT: i32 2, label [[C:%.*]]
|
|
556 ; CHECK-NEXT: i32 3, label [[D:%.*]]
|
|
557 ; CHECK-NEXT: ]
|
|
558 ; CHECK: a:
|
|
559 ; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
560 ; CHECK: b:
|
|
561 ; CHECK-NEXT: br label [[EXIT]]
|
|
562 ; CHECK: c:
|
|
563 ; CHECK-NEXT: br label [[EXIT]]
|
|
564 ; CHECK: d:
|
|
565 ; CHECK-NEXT: br label [[EXIT]]
|
|
566 ; CHECK: exit:
|
|
567 ; CHECK-NEXT: [[P:%.*]] = phi i64 [ 4294967296, [[A]] ], [ 1, [[B]] ], [ 1, [[C]] ], [ 1, [[D]] ]
|
|
568 ; CHECK-NEXT: [[SUM1:%.*]] = add i64 [[ARG:%.*]], [[P]]
|
|
569 ; CHECK-NEXT: [[SUM2:%.*]] = add i64 [[SUM1]], [[P]]
|
|
570 ; CHECK-NEXT: ret i64 [[SUM2]]
|
|
571 ;
|
150
|
572 entry:
|
|
573 switch i32 %flag, label %a [
|
173
|
574 i32 1, label %b
|
|
575 i32 2, label %c
|
|
576 i32 3, label %d
|
150
|
577 ]
|
|
578
|
|
579 a:
|
|
580 br label %exit
|
|
581
|
|
582 b:
|
|
583 br label %exit
|
|
584
|
|
585 c:
|
|
586 br label %exit
|
|
587
|
|
588 d:
|
|
589 br label %exit
|
|
590
|
|
591 exit:
|
|
592 %p = phi i64 [ 4294967296, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
|
|
593 %sum1 = add i64 %arg, %p
|
|
594 %sum2 = add i64 %sum1, %p
|
|
595 ret i64 %sum2
|
|
596 }
|
|
597
|
|
598 define i32 @test_no_spec_non_postdominating_uses(i1 %flag1, i1 %flag2, i32 %arg) {
|
173
|
599 ; CHECK-LABEL: @test_no_spec_non_postdominating_uses(
|
|
600 ; CHECK-NEXT: entry:
|
|
601 ; CHECK-NEXT: br i1 [[FLAG1:%.*]], label [[A:%.*]], label [[B:%.*]]
|
|
602 ; CHECK: a:
|
|
603 ; CHECK-NEXT: [[SUM1_0:%.*]] = add i32 [[ARG:%.*]], 7
|
|
604 ; CHECK-NEXT: br label [[MERGE:%.*]]
|
|
605 ; CHECK: b:
|
|
606 ; CHECK-NEXT: [[SUM1_1:%.*]] = add i32 [[ARG]], 11
|
|
607 ; CHECK-NEXT: br label [[MERGE]]
|
|
608 ; CHECK: merge:
|
|
609 ; CHECK-NEXT: [[SUM1_PHI:%.*]] = phi i32 [ [[SUM1_0]], [[A]] ], [ [[SUM1_1]], [[B]] ]
|
|
610 ; CHECK-NEXT: [[P2:%.*]] = phi i32 [ 13, [[A]] ], [ 42, [[B]] ]
|
|
611 ; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[EXIT1:%.*]], label [[EXIT2:%.*]]
|
|
612 ; CHECK: exit1:
|
|
613 ; CHECK-NEXT: ret i32 [[SUM1_PHI]]
|
|
614 ; CHECK: exit2:
|
|
615 ; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[ARG]], [[P2]]
|
|
616 ; CHECK-NEXT: ret i32 [[SUM2]]
|
|
617 ;
|
150
|
618 entry:
|
|
619 br i1 %flag1, label %a, label %b
|
|
620
|
|
621 a:
|
|
622 br label %merge
|
|
623
|
|
624 b:
|
|
625 br label %merge
|
|
626
|
|
627 merge:
|
|
628 %p1 = phi i32 [ 7, %a ], [ 11, %b ]
|
|
629 %p2 = phi i32 [ 13, %a ], [ 42, %b ]
|
|
630 %sum1 = add i32 %arg, %p1
|
|
631 br i1 %flag2, label %exit1, label %exit2
|
|
632
|
|
633 exit1:
|
|
634 ret i32 %sum1
|
|
635
|
|
636 exit2:
|
|
637 %sum2 = add i32 %arg, %p2
|
|
638 ret i32 %sum2
|
|
639 }
|