1 ; Test the basic functionality of speculating around PHI nodes based on reduced
2 ; cost of the constant operands to the PHI nodes using the x86 cost model.
4 ; REQUIRES: x86-registered-target
5 ; RUN: opt -S -passes=spec-phis < %s | FileCheck %s
7 target triple = "x86_64-unknown-unknown"
9 define i32 @test_basic(i1 %flag, i32 %arg) {
10 ; CHECK-LABEL: define i32 @test_basic(
12 br i1 %flag, label %a, label %b
13 ; CHECK: br i1 %flag, label %a, label %b
18 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
19 ; CHECK-NEXT: br label %exit
24 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
25 ; CHECK-NEXT: br label %exit
28 %p = phi i32 [ 7, %a ], [ 11, %b ]
29 %sum = add i32 %arg, %p
32 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
33 ; CHECK-NEXT: ret i32 %[[PHI]]
36 ; Check that we handle commuted operands and get the constant onto the RHS.
37 define i32 @test_commuted(i1 %flag, i32 %arg) {
38 ; CHECK-LABEL: define i32 @test_commuted(
40 br i1 %flag, label %a, label %b
41 ; CHECK: br i1 %flag, label %a, label %b
46 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
47 ; CHECK-NEXT: br label %exit
52 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
53 ; CHECK-NEXT: br label %exit
56 %p = phi i32 [ 7, %a ], [ 11, %b ]
57 %sum = add i32 %p, %arg
60 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
61 ; CHECK-NEXT: ret i32 %[[PHI]]
64 define i32 @test_split_crit_edge(i1 %flag, i32 %arg) {
65 ; CHECK-LABEL: define i32 @test_split_crit_edge(
67 br i1 %flag, label %exit, label %a
69 ; CHECK-NEXT: br i1 %flag, label %[[ENTRY_SPLIT:.*]], label %a
71 ; CHECK: [[ENTRY_SPLIT]]:
72 ; CHECK-NEXT: %[[SUM_ENTRY_SPLIT:.*]] = add i32 %arg, 7
73 ; CHECK-NEXT: br label %exit
78 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 11
79 ; CHECK-NEXT: br label %exit
82 %p = phi i32 [ 7, %entry ], [ 11, %a ]
83 %sum = add i32 %arg, %p
86 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_ENTRY_SPLIT]], %[[ENTRY_SPLIT]] ], [ %[[SUM_A]], %a ]
87 ; CHECK-NEXT: ret i32 %[[PHI]]
90 define i32 @test_no_spec_dominating_inst(i1 %flag, i32* %ptr) {
91 ; CHECK-LABEL: define i32 @test_no_spec_dominating_inst(
93 %load = load i32, i32* %ptr
94 br i1 %flag, label %a, label %b
95 ; CHECK: %[[LOAD:.*]] = load i32, i32* %ptr
96 ; CHECK-NEXT: br i1 %flag, label %a, label %b
101 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[LOAD]], 7
102 ; CHECK-NEXT: br label %exit
107 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[LOAD]], 11
108 ; CHECK-NEXT: br label %exit
111 %p = phi i32 [ 7, %a ], [ 11, %b ]
112 %sum = add i32 %load, %p
115 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
116 ; CHECK-NEXT: ret i32 %[[PHI]]
119 ; We have special logic handling PHI nodes, make sure it doesn't get confused
120 ; by a dominating PHI.
121 define i32 @test_no_spec_dominating_phi(i1 %flag1, i1 %flag2, i32 %x, i32 %y) {
122 ; CHECK-LABEL: define i32 @test_no_spec_dominating_phi(
124 br i1 %flag1, label %x.block, label %y.block
126 ; CHECK-NEXT: br i1 %flag1, label %x.block, label %y.block
131 ; CHECK-NEXT: br label %merge
136 ; CHECK-NEXT: br label %merge
139 %xy.phi = phi i32 [ %x, %x.block ], [ %y, %y.block ]
140 br i1 %flag2, label %a, label %b
142 ; CHECK-NEXT: %[[XY_PHI:.*]] = phi i32 [ %x, %x.block ], [ %y, %y.block ]
143 ; CHECK-NEXT: br i1 %flag2, label %a, label %b
148 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[XY_PHI]], 7
149 ; CHECK-NEXT: br label %exit
154 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[XY_PHI]], 11
155 ; CHECK-NEXT: br label %exit
158 %p = phi i32 [ 7, %a ], [ 11, %b ]
159 %sum = add i32 %xy.phi, %p
162 ; CHECK-NEXT: %[[SUM_PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
163 ; CHECK-NEXT: ret i32 %[[SUM_PHI]]
166 ; Ensure that we will speculate some number of "free" instructions on the given
167 ; architecture even though they are unrelated to the PHI itself.
168 define i32 @test_speculate_free_insts(i1 %flag, i64 %arg) {
169 ; CHECK-LABEL: define i32 @test_speculate_free_insts(
171 br i1 %flag, label %a, label %b
172 ; CHECK: br i1 %flag, label %a, label %b
177 ; CHECK-NEXT: %[[T1_A:.*]] = trunc i64 %arg to i48
178 ; CHECK-NEXT: %[[T2_A:.*]] = trunc i48 %[[T1_A]] to i32
179 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %[[T2_A]], 7
180 ; CHECK-NEXT: br label %exit
185 ; CHECK-NEXT: %[[T1_B:.*]] = trunc i64 %arg to i48
186 ; CHECK-NEXT: %[[T2_B:.*]] = trunc i48 %[[T1_B]] to i32
187 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %[[T2_B]], 11
188 ; CHECK-NEXT: br label %exit
191 %p = phi i32 [ 7, %a ], [ 11, %b ]
192 %t1 = trunc i64 %arg to i48
193 %t2 = trunc i48 %t1 to i32
194 %sum = add i32 %t2, %p
197 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
198 ; CHECK-NEXT: ret i32 %[[PHI]]
201 define i32 @test_speculate_free_phis(i1 %flag, i32 %arg1, i32 %arg2) {
202 ; CHECK-LABEL: define i32 @test_speculate_free_phis(
204 br i1 %flag, label %a, label %b
205 ; CHECK: br i1 %flag, label %a, label %b
210 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg1, 7
211 ; CHECK-NEXT: br label %exit
216 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg2, 11
217 ; CHECK-NEXT: br label %exit
220 %p1 = phi i32 [ 7, %a ], [ 11, %b ]
221 %p2 = phi i32 [ %arg1, %a ], [ %arg2, %b ]
222 %sum = add i32 %p2, %p1
225 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
226 ; We don't DCE the now unused PHI node...
227 ; CHECK-NEXT: %{{.*}} = phi i32 [ %arg1, %a ], [ %arg2, %b ]
228 ; CHECK-NEXT: ret i32 %[[PHI]]
231 ; We shouldn't speculate multiple uses even if each individually looks
232 ; profitable because of the total cost.
233 define i32 @test_no_spec_multi_uses(i1 %flag, i32 %arg1, i32 %arg2, i32 %arg3) {
234 ; CHECK-LABEL: define i32 @test_no_spec_multi_uses(
236 br i1 %flag, label %a, label %b
237 ; CHECK: br i1 %flag, label %a, label %b
242 ; CHECK-NEXT: br label %exit
247 ; CHECK-NEXT: br label %exit
250 %p = phi i32 [ 7, %a ], [ 11, %b ]
251 %add1 = add i32 %arg1, %p
252 %add2 = add i32 %arg2, %p
253 %add3 = add i32 %arg3, %p
254 %sum1 = add i32 %add1, %add2
255 %sum2 = add i32 %sum1, %add3
258 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
259 ; CHECK-NEXT: %[[ADD1:.*]] = add i32 %arg1, %[[PHI]]
260 ; CHECK-NEXT: %[[ADD2:.*]] = add i32 %arg2, %[[PHI]]
261 ; CHECK-NEXT: %[[ADD3:.*]] = add i32 %arg3, %[[PHI]]
262 ; CHECK-NEXT: %[[SUM1:.*]] = add i32 %[[ADD1]], %[[ADD2]]
263 ; CHECK-NEXT: %[[SUM2:.*]] = add i32 %[[SUM1]], %[[ADD3]]
264 ; CHECK-NEXT: ret i32 %[[SUM2]]
267 define i32 @test_multi_phis1(i1 %flag, i32 %arg) {
268 ; CHECK-LABEL: define i32 @test_multi_phis1(
270 br i1 %flag, label %a, label %b
271 ; CHECK: br i1 %flag, label %a, label %b
276 ; CHECK-NEXT: %[[SUM_A1:.*]] = add i32 %arg, 1
277 ; CHECK-NEXT: %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
278 ; CHECK-NEXT: %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
279 ; CHECK-NEXT: br label %exit
284 ; CHECK-NEXT: %[[SUM_B1:.*]] = add i32 %arg, 2
285 ; CHECK-NEXT: %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
286 ; CHECK-NEXT: %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
287 ; CHECK-NEXT: br label %exit
290 %p1 = phi i32 [ 1, %a ], [ 2, %b ]
291 %p2 = phi i32 [ 3, %a ], [ 4, %b ]
292 %p3 = phi i32 [ 5, %a ], [ 6, %b ]
293 %sum1 = add i32 %arg, %p1
294 %sum2 = add i32 %sum1, %p2
295 %sum3 = add i32 %sum2, %p3
298 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
299 ; CHECK-NEXT: ret i32 %[[PHI]]
302 ; Check that the order of the PHIs doesn't impact the behavior.
303 define i32 @test_multi_phis2(i1 %flag, i32 %arg) {
304 ; CHECK-LABEL: define i32 @test_multi_phis2(
306 br i1 %flag, label %a, label %b
307 ; CHECK: br i1 %flag, label %a, label %b
312 ; CHECK-NEXT: %[[SUM_A1:.*]] = add i32 %arg, 1
313 ; CHECK-NEXT: %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
314 ; CHECK-NEXT: %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
315 ; CHECK-NEXT: br label %exit
320 ; CHECK-NEXT: %[[SUM_B1:.*]] = add i32 %arg, 2
321 ; CHECK-NEXT: %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
322 ; CHECK-NEXT: %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
323 ; CHECK-NEXT: br label %exit
326 %p3 = phi i32 [ 5, %a ], [ 6, %b ]
327 %p2 = phi i32 [ 3, %a ], [ 4, %b ]
328 %p1 = phi i32 [ 1, %a ], [ 2, %b ]
329 %sum1 = add i32 %arg, %p1
330 %sum2 = add i32 %sum1, %p2
331 %sum3 = add i32 %sum2, %p3
334 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
335 ; CHECK-NEXT: ret i32 %[[PHI]]
338 define i32 @test_no_spec_indirectbr(i1 %flag, i32 %arg) {
339 ; CHECK-LABEL: define i32 @test_no_spec_indirectbr(
341 br i1 %flag, label %a, label %b
343 ; CHECK-NEXT: br i1 %flag, label %a, label %b
346 indirectbr i8* undef, [label %exit]
348 ; CHECK-NEXT: indirectbr i8* undef, [label %exit]
351 indirectbr i8* undef, [label %exit]
353 ; CHECK-NEXT: indirectbr i8* undef, [label %exit]
356 %p = phi i32 [ 7, %a ], [ 11, %b ]
357 %sum = add i32 %arg, %p
360 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
361 ; CHECK-NEXT: %[[SUM:.*]] = add i32 %arg, %[[PHI]]
362 ; CHECK-NEXT: ret i32 %[[SUM]]
367 declare i32 @__gxx_personality_v0(...)
369 ; FIXME: We should be able to handle this case -- only the exceptional edge is
370 ; impossible to split.
371 define i32 @test_no_spec_invoke_continue(i1 %flag, i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
372 ; CHECK-LABEL: define i32 @test_no_spec_invoke_continue(
374 br i1 %flag, label %a, label %b
376 ; CHECK-NEXT: br i1 %flag, label %a, label %b
380 to label %exit unwind label %lpad
382 ; CHECK-NEXT: invoke void @g()
383 ; CHECK-NEXT: to label %exit unwind label %lpad
387 to label %exit unwind label %lpad
389 ; CHECK-NEXT: invoke void @g()
390 ; CHECK-NEXT: to label %exit unwind label %lpad
393 %p = phi i32 [ 7, %a ], [ 11, %b ]
394 %sum = add i32 %arg, %p
397 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
398 ; CHECK-NEXT: %[[SUM:.*]] = add i32 %arg, %[[PHI]]
399 ; CHECK-NEXT: ret i32 %[[SUM]]
402 %lp = landingpad { i8*, i32 }
404 resume { i8*, i32 } undef
407 define i32 @test_no_spec_landingpad(i32 %arg, i32* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
408 ; CHECK-LABEL: define i32 @test_no_spec_landingpad(
411 to label %invoke.cont unwind label %lpad
413 ; CHECK-NEXT: invoke void @g()
414 ; CHECK-NEXT: to label %invoke.cont unwind label %lpad
418 to label %exit unwind label %lpad
419 ; CHECK: invoke.cont:
420 ; CHECK-NEXT: invoke void @g()
421 ; CHECK-NEXT: to label %exit unwind label %lpad
424 %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
425 %lp = landingpad { i8*, i32 }
427 %sum = add i32 %arg, %p
428 store i32 %sum, i32* %ptr
429 resume { i8*, i32 } undef
431 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
437 declare i32 @__CxxFrameHandler3(...)
439 define i32 @test_no_spec_cleanuppad(i32 %arg, i32* %ptr) personality i32 (...)* @__CxxFrameHandler3 {
440 ; CHECK-LABEL: define i32 @test_no_spec_cleanuppad(
443 to label %invoke.cont unwind label %lpad
445 ; CHECK-NEXT: invoke void @g()
446 ; CHECK-NEXT: to label %invoke.cont unwind label %lpad
450 to label %exit unwind label %lpad
451 ; CHECK: invoke.cont:
452 ; CHECK-NEXT: invoke void @g()
453 ; CHECK-NEXT: to label %exit unwind label %lpad
456 %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
457 %cp = cleanuppad within none []
458 %sum = add i32 %arg, %p
459 store i32 %sum, i32* %ptr
460 cleanupret from %cp unwind to caller
462 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
468 ; Check that we don't fall over when confronted with seemingly reasonable code
469 ; for us to handle but in an unreachable region and with non-PHI use-def
471 define i32 @test_unreachable_non_phi_cycles(i1 %flag, i32 %arg) {
472 ; CHECK-LABEL: define i32 @test_unreachable_non_phi_cycles(
476 ; CHECK-NEXT: ret i32 42
481 ; CHECK-NEXT: br label %exit
486 ; CHECK-NEXT: br label %exit
489 %p = phi i32 [ 7, %a ], [ 11, %b ]
490 %zext = zext i32 %sum to i64
491 %trunc = trunc i64 %zext to i32
492 %sum = add i32 %trunc, %p
493 br i1 %flag, label %a, label %b
495 ; CHECK-NEXT: %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
496 ; CHECK-NEXT: %[[ZEXT:.*]] = zext i32 %[[SUM:.*]] to i64
497 ; CHECK-NEXT: %[[TRUNC:.*]] = trunc i64 %[[ZEXT]] to i32
498 ; CHECK-NEXT: %[[SUM]] = add i32 %[[TRUNC]], %[[PHI]]
499 ; CHECK-NEXT: br i1 %flag, label %a, label %b
502 ; Check that we don't speculate in the face of an expensive immediate. There
503 ; are two reasons this should never speculate. First, even a local analysis
504 ; should fail because it makes some paths (%a) potentially more expensive due
505 ; to multiple uses of the immediate. Additionally, when we go to speculate the
506 ; instructions, their cost will also be too high.
507 ; FIXME: The goal is really to test the first property, but there doesn't
508 ; happen to be any way to use free-to-speculate instructions here so that it
509 ; would be the only interesting property.
510 define i64 @test_expensive_imm(i32 %flag, i64 %arg) {
511 ; CHECK-LABEL: define i64 @test_expensive_imm(
513 switch i32 %flag, label %a [
518 ; CHECK: switch i32 %flag, label %a [
519 ; CHECK-NEXT: i32 1, label %b
520 ; CHECK-NEXT: i32 2, label %c
521 ; CHECK-NEXT: i32 3, label %d
527 ; CHECK-NEXT: br label %exit
532 ; CHECK-NEXT: br label %exit
537 ; CHECK-NEXT: br label %exit
542 ; CHECK-NEXT: br label %exit
545 %p = phi i64 [ 4294967296, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
546 %sum1 = add i64 %arg, %p
547 %sum2 = add i64 %sum1, %p
550 ; CHECK-NEXT: %[[PHI:.*]] = phi i64 [ {{[0-9]+}}, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
551 ; CHECK-NEXT: %[[SUM1:.*]] = add i64 %arg, %[[PHI]]
552 ; CHECK-NEXT: %[[SUM2:.*]] = add i64 %[[SUM1]], %[[PHI]]
553 ; CHECK-NEXT: ret i64 %[[SUM2]]
556 define i32 @test_no_spec_non_postdominating_uses(i1 %flag1, i1 %flag2, i32 %arg) {
557 ; CHECK-LABEL: define i32 @test_no_spec_non_postdominating_uses(
559 br i1 %flag1, label %a, label %b
560 ; CHECK: br i1 %flag1, label %a, label %b
565 ; CHECK-NEXT: %[[SUM_A:.*]] = add i32 %arg, 7
566 ; CHECK-NEXT: br label %merge
571 ; CHECK-NEXT: %[[SUM_B:.*]] = add i32 %arg, 11
572 ; CHECK-NEXT: br label %merge
575 %p1 = phi i32 [ 7, %a ], [ 11, %b ]
576 %p2 = phi i32 [ 13, %a ], [ 42, %b ]
577 %sum1 = add i32 %arg, %p1
578 br i1 %flag2, label %exit1, label %exit2
580 ; CHECK-NEXT: %[[PHI1:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
581 ; CHECK-NEXT: %[[PHI2:.*]] = phi i32 [ 13, %a ], [ 42, %b ]
582 ; CHECK-NEXT: br i1 %flag2, label %exit1, label %exit2
587 ; CHECK-NEXT: ret i32 %[[PHI1]]
590 %sum2 = add i32 %arg, %p2
593 ; CHECK-NEXT: %[[SUM2:.*]] = add i32 %arg, %[[PHI2]]
594 ; CHECK-NEXT: ret i32 %[[SUM2]]