1
1
// RUN: %target-sil-opt -enable-sil-verify-all %s -jumpthread-simplify-cfg -enable-ossa-simplify-cfg -enable-ossa-rewriteterminator | %FileCheck %s
2
2
// RUN: %target-sil-opt -enable-sil-verify-all %s -jumpthread-simplify-cfg -enable-ossa-simplify-cfg -enable-ossa-rewriteterminator -debug-only=sil-simplify-cfg 2>&1 | %FileCheck %s --check-prefix=CHECK-TRACE
3
- //
4
- // REQUIRES: EnableOSSASimplifyCFG
5
-
6
- // FIXME: When OSSA optimization is complete, convert XCHECK to CHECK lines
7
3
8
4
// FIXME: which of these tests actually require -jumpthread-simplify-cfg instead of -simplify-cfg?
9
5
6
+ // FIXME_rauw: revisit these fixme's after the OwnershipRAUW utility is rewritten in terms of OwnershipLiveness.
7
+
10
8
sil_stage canonical
11
9
12
10
import Builtin
@@ -46,6 +44,8 @@ class Final : Derived {
46
44
sil [ossa] @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
47
45
sil [ossa] @_TFC3ccb4Base6middlefS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
48
46
47
+ sil @get_base : $@convention(thin) () -> @owned Base
48
+
49
49
// CHECK-LABEL: sil [ossa] @redundant_checked_cast_br
50
50
sil [ossa] @redundant_checked_cast_br : $@convention(method) (@guaranteed Base) -> () {
51
51
bb0(%0 : @guaranteed $Base):
62
62
bb2(%5 : @guaranteed $Base):
63
63
// CHECK: [[SUCCESS]]
64
64
%7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
65
- // XCHECK -NOT: checked_cast_br
65
+ // CHECK -NOT: checked_cast_br
66
66
checked_cast_br [exact] %0 : $Base to Base, bb3, bb5
67
67
// CHECK: [[INNER:%.*]] = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
68
68
// CHECK: apply [[INNER]]
@@ -109,9 +109,10 @@ bb1:
109
109
return %3 : $()
110
110
111
111
// CHECK: [[SUCCESS]]([[SUCCESSARG:%.*]] : @owned $Base)
112
- // XCHECK-NOT: checked_cast_br
113
- // XCHECK: [[INNER:%.*]] = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
114
- // XCHECK: apply [[INNER]]([[SUCCESSARG]])
112
+ // CHECK-NOT: checked_cast_br
113
+ // CHECK: [[SUCCESSCOPY:%.*]] = copy_value [[SUCCESSARG]] : $Base
114
+ // CHECK: [[INNER:%.*]] = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
115
+ // CHECK: apply [[INNER]]([[SUCCESSCOPY]])
115
116
// CHECK: br bb1
116
117
bb2(%5 : @owned $Base):
117
118
%7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
@@ -206,8 +207,8 @@ bb2(%5 : @guaranteed $Base):
206
207
// CHECK: [[SUCCESS]]([[SUCCESSARG:%.*]] : @guaranteed $Base)
207
208
// CHECK: [[METHOD2:%.*]] = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
208
209
%7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
209
- // XCHECK -NOT: checked_cast_br [exact] %0 : $Base to Derived
210
- // XCHECK : apply [[METHOD2]]([[SUCCESSARG]])
210
+ // CHECK -NOT: checked_cast_br [exact] %0 : $Base to Derived
211
+ // CHECK : apply [[METHOD2]]([[SUCCESSARG]])
211
212
// Check that checked_cast_br [exact] was replaced by a branch to the failure BB of the checked_cast_br.
212
213
// This is because bb2 is reached via the success branch of the checked_cast_br [exact] from bb0.
213
214
// It means that the exact dynamic type of %0 is $Base. Thus it cannot be $Derived.
252
253
253
254
// CHECK: [[SUCCESS]]([[SUCCESSARG:%.*]] : @owned $Base)
254
255
// CHECK: [[METHOD2:%.*]] = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
255
- // XCHECK -NOT: checked_cast_br [exact] %0 : $Base to Derived
256
- // XCHECK : apply [[METHOD2]]([[SUCCESSARG]])
256
+ // CHECK -NOT: checked_cast_br [exact] %0 : $Base to Derived
257
+ // CHECK : apply [[METHOD2]]([[SUCCESSARG]])
257
258
// Check that checked_cast_br [exact] was replaced by a branch to the failure BB of the checked_cast_br.
258
259
// This is because bb2 is reached via the success branch of the checked_cast_br [exact] from bb0.
259
260
// It means that the exact dynamic type of %0 is $Base. Thus it cannot be $Derived.
@@ -324,16 +325,16 @@ bb5(%2a : @guaranteed $Base):
324
325
br bb6
325
326
326
327
bb6:
328
+ dealloc_ref %a : $Base
327
329
dealloc_stack_ref %a : $Base
328
330
%r = tuple()
329
331
return %r : $()
330
332
}
331
333
332
334
// Test a redundant checked_cast_br that has success, failure paths, and unknown paths.
333
335
//
334
- // TODO: this is currently a bailout.
335
- //
336
- //!!! CHECKME
336
+ // TODO: this is currently a bailout because the CFG transform can't handle it:
337
+ // (!SuccessPreds.empty() && !FailurePreds.empty() && numUnknownPreds > 0)
337
338
sil [ossa] @redundant_checked_cast_br_joined_success_fail_unknown : $@convention(method) (@guaranteed Base) -> () {
338
339
bb0(%0 : @guaranteed $Base):
339
340
%middle = class_method %0 : $Base, #Base.middle : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
@@ -344,26 +345,22 @@ bb1(%successBB0 : @guaranteed $Base):
344
345
345
346
bb2:
346
347
%successBB0call2 = apply %middle(%successBB0) : $@convention(method) (@guaranteed Base) -> ()
347
- %successBB0borrow2 = begin_borrow %successBB0 : $Base
348
- br bb8(%successBB0borrow2 : $Base)
348
+ br bb8(%successBB0 : $Base)
349
349
350
350
bb3:
351
351
%successBB0call3 = apply %middle(%successBB0) : $@convention(method) (@guaranteed Base) -> ()
352
- %successBB0borrow3 = begin_borrow %successBB0 : $Base
353
- br bb7(%successBB0borrow3 : $Base)
352
+ br bb7(%successBB0 : $Base)
354
353
355
354
bb4(%failBB0 : @guaranteed $Base):
356
355
cond_br undef, bb5, bb6
357
356
358
357
bb5:
359
358
%failBB0call5 = apply %middle(%failBB0) : $@convention(method) (@guaranteed Base) -> ()
360
- %failBB0borrow5 = begin_borrow %failBB0 : $Base
361
- br bb7(%failBB0borrow5 : $Base)
359
+ br bb7(%failBB0 : $Base)
362
360
363
361
bb6:
364
362
%failBB0call6 = apply %middle(%failBB0) : $@convention(method) (@guaranteed Base) -> ()
365
- %failBB0borrow6 = begin_borrow %failBB0 : $Base
366
- br bb8(%failBB0borrow6 : $Base)
363
+ br bb8(%failBB0 : $Base)
367
364
368
365
bb7(%unknown : @guaranteed $Base):
369
366
%unknownCall = apply %middle(%unknown) : $@convention(method) (@guaranteed Base) -> ()
@@ -391,9 +388,11 @@ bb11:
391
388
// Verify that checked-cast jump-threading kicks in and generates verifiable SIL.
392
389
//
393
390
// CHECK-TRACE-LABEL: ### Run SimplifyCFG on $testCheckCastJumpThread
394
- // XCHECK-TRACE: Condition is the same if reached over {{.*}} parent @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned OtherKlass }
395
- // XCHECK-TRACE-NEXT: bb3(%{{.*}} : $OtherKlass):
396
- // XCHECK-TRACE-NEXT: br bb5(%{{.*}} : $Klass)
391
+ // CHECK-TRACE: Condition is the same if reached over {{.*}} parent @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned any OtherKlass }
392
+ // CHECK-TRACE-NEXT: // %{{.*}} user:
393
+ // CHECK-TRACE-NEXT: bb1(%{{.*}} : @owned $any OtherKlass):
394
+ // CHECK-TRACE-NEXT: destroy_value
395
+ // CHECK-TRACE-NEXT: br bb5(%{{.*}} : $Klass)
397
396
sil shared [ossa] @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned OtherKlass {
398
397
bb0(%0 : @guaranteed $Klass):
399
398
%1 = function_ref @get_klass : $@convention(thin) () -> @owned Klass
@@ -402,7 +401,7 @@ bb0(%0 : @guaranteed $Klass):
402
401
%4 = copy_value %3 : $Klass
403
402
checked_cast_br %3 : $Klass to OtherKlass, bb1, bb2
404
403
405
- bb1(%5 : $OtherKlass):
404
+ bb1(%5 : @owned $OtherKlass):
406
405
destroy_value %5 : $OtherKlass
407
406
%6 = integer_literal $Builtin.Int1, -1
408
407
br bb3(%6 : $Builtin.Int1)
@@ -428,19 +427,20 @@ bb6:
428
427
bb7(%16 : @owned $Klass):
429
428
checked_cast_br %16 : $Klass to OtherKlass, bb9, bb8
430
429
431
- bb8(%18 : $Klass):
430
+ bb8(%18 : @owned $Klass):
432
431
destroy_value %18 : $Klass
433
432
br bb4
434
433
435
- bb9(%20 : $OtherKlass):
434
+ bb9(%20 : @owned $OtherKlass):
436
435
return %20 : $OtherKlass
437
436
438
437
bb10(%22 : $Builtin.Int64):
439
438
%23 = apply %1() : $@convention(thin) () -> @owned Klass
440
439
%24 = copy_value %23 : $Klass
441
440
checked_cast_br %23 : $Klass to OtherKlass, bb11, bb12
442
441
443
- bb11(%25 : $OtherKlass):
442
+ bb11(%25 : @owned $OtherKlass):
443
+ destroy_value %25 : $OtherKlass
444
444
%26 = integer_literal $Builtin.Int1, -1
445
445
br bb13(%26 : $Builtin.Int1)
446
446
@@ -465,3 +465,215 @@ bb16:
465
465
bb17:
466
466
br bb10(undef : $Builtin.Int64)
467
467
}
468
+
469
+ // =============================================================================
470
+ // Test OSSA lifetime fixup after removing redundant checked_cast_br
471
+
472
+ // Replace an owned result with a guaranteed value on the success path.
473
+ // Introduce a copy for the new lifetime.
474
+ //
475
+ // CHECK-LABEL: sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_success : $@convention(method) (@owned Base) -> () {
476
+ // CHECK: bb0(%0 : @owned $Base):
477
+ // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Base
478
+ // CHECK: checked_cast_br [exact] [[BORROW]] : $Base to Base, bb1, bb2
479
+ // CHECK: bb1([[EXACT:%.*]] : @guaranteed $Base):
480
+ // CHECK-NEXT: [[NEWCP:%.*]] = copy_value [[EXACT]] : $Base
481
+ // CHECK-NEXT: [[OLDCP:%.*]] = copy_value [[EXACT]] : $Base
482
+ // CHECK-NEXT: end_borrow
483
+ // CHECK: destroy_value [[OLDCP]] : $Base
484
+ // CHECK: apply %{{.*}}([[NEWCP]]) : $@convention(method) (@guaranteed Base) -> ()
485
+ // CHECK: destroy_value [[NEWCP]] : $Base
486
+ // CHECK: br bb3
487
+ // CHECK: bb2([[INEXACT:%.*]] : @guaranteed $Base):
488
+ // CHECK: apply %{{.*}}([[INEXACT]]) : $@convention(method) (@guaranteed Base) -> ()
489
+ // CHECK: end_borrow %1 : $Base
490
+ // CHECK: br bb3
491
+ // CHECK: bb3:
492
+ // CHECK: destroy_value %0 : $Base
493
+ // CHECK-LABEL: } // end sil function 'redundant_checked_cast_br_rauw_guaranteed_to_owned_success'
494
+ sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_success : $@convention(method) (@owned Base) -> () {
495
+ bb0(%0 : @owned $Base):
496
+ %borrow = begin_borrow %0 : $Base
497
+ %1 = class_method %0 : $Base, #Base.middle : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
498
+ checked_cast_br [exact] %borrow : $Base to Base, bb1, bb6
499
+
500
+ bb1(%5 : @guaranteed $Base):
501
+ %6 = copy_value %5 : $Base
502
+ end_borrow %borrow : $Base
503
+ %7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
504
+ checked_cast_br [exact] %6 : $Base to Base, bb2, bb4
505
+
506
+ bb2(%9 : @owned $Base):
507
+ %10 = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
508
+ %11 = apply %10(%9) : $@convention(method) (@guaranteed Base) -> ()
509
+ destroy_value %9 : $Base
510
+ br bb3
511
+
512
+ bb3:
513
+ %13 = tuple ()
514
+ br bb5(%13 : $())
515
+
516
+ bb4(%defaultBB2 : @owned $Base):
517
+ %15 = apply %7(%defaultBB2) : $@convention(method) (@guaranteed Base) -> ()
518
+ destroy_value %defaultBB2 : $Base
519
+ br bb3
520
+
521
+ bb5(%17 : $()):
522
+ br bb7
523
+
524
+ bb6(%defaultBB0 : @guaranteed $Base):
525
+ %19 = apply %1(%defaultBB0) : $@convention(method) (@guaranteed Base) -> ()
526
+ end_borrow %borrow : $Base
527
+ br bb7
528
+
529
+ bb7:
530
+ destroy_value %0 : $Base
531
+ %3 = tuple ()
532
+ return %3 : $()
533
+ }
534
+
535
+ // Replace an owned result with a guaranteed value on the merged path.
536
+ // Introduce a copy for the new lifetime.
537
+ // Simplify down to a single diamond.
538
+ //
539
+ // TODO: Simplify some of the obvisouly dead copy/destroy/borrows
540
+ // on-the-fly after each simplify-cfg. Possible using CanonicalizeOSSALifetime.
541
+ //
542
+ // CHECK-LABEL: sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_merge : $@convention(method) (@owned Base) -> () {
543
+ // CHECK: bb0(%0 : @owned $Base):
544
+ // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Base
545
+ // CHECK: checked_cast_br [exact] [[BORROW]] : $Base to Base, bb1, bb3
546
+ // CHECK: bb1([[ARG1:%.*]] : @guaranteed $Base):
547
+ // CHECK: [[NEWCOPY1:%.*]] = copy_value [[ARG1]] : $Base
548
+ // CHECK: apply %{{.*}}([[ARG1]]) : $@convention(method) (@guaranteed Base) -> ()
549
+ // CHECK: [[OLDCOPY:%.*]] = copy_value [[BORROW]] : $Base
550
+ // CHECK: end_borrow [[BORROW]] : $Base
551
+ // CHECK: destroy_value [[OLDCOPY]] : $Base
552
+ // CHECK: apply %{{.*}}([[NEWCOPY1]]) : $@convention(method) (@guaranteed Base) -> ()
553
+ // CHECK: destroy_value [[NEWCOPY1]] : $Base
554
+ // CHECK: br bb2
555
+ // CHECK: bb2:
556
+ // CHECK: destroy_value %0 : $Base
557
+ // CHECK: return
558
+ // CHECK: bb3([[ARG3:%.*]] : @guaranteed $Base):
559
+ // CHECK: apply %1([[ARG3]]) : $@convention(method) (@guaranteed Base) -> ()
560
+ // CHECK: [[NEWCOPY3:%.*]] = copy_value [[BORROW]] : $Base
561
+ // CHECK: end_borrow [[BORROW]] : $Base
562
+ // CHECK: apply %{{.*}}([[NEWCOPY3]]) : $@convention(method) (@guaranteed Base) -> ()
563
+ // CHECK: destroy_value [[NEWCOPY3]] : $Base
564
+ // CHECK: br bb2
565
+ // CHECK-LABEL: } // end sil function 'redundant_checked_cast_br_rauw_guaranteed_to_owned_merge'
566
+ sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_merge : $@convention(method) (@owned Base) -> () {
567
+ bb0(%0 : @owned $Base):
568
+ %m = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
569
+ %f = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
570
+ %1 = begin_borrow %0 : $Base
571
+ checked_cast_br [exact] %1 : $Base to Base, bb1, bb2
572
+
573
+ bb1(%4 : @guaranteed $Base):
574
+ %5 = apply %f(%4) : $@convention(method) (@guaranteed Base) -> ()
575
+ br bb3
576
+
577
+ bb2(%7 : @guaranteed $Base):
578
+ %8 = apply %m(%7) : $@convention(method) (@guaranteed Base) -> ()
579
+ br bb3
580
+
581
+ bb3:
582
+ %11 = copy_value %1 : $Base
583
+ end_borrow %1 : $Base
584
+ checked_cast_br [exact] %11 : $Base to Base, bb4, bb5
585
+
586
+ bb4(%14 : @owned $Base):
587
+ %15 = apply %f(%14) : $@convention(method) (@guaranteed Base) -> ()
588
+ destroy_value %14 : $Base
589
+ br bb6
590
+
591
+ bb5(%20 : @owned $Base):
592
+ %21 = apply %m(%20) : $@convention(method) (@guaranteed Base) -> ()
593
+ destroy_value %20 : $Base
594
+ br bb6
595
+
596
+ bb6:
597
+ destroy_value %0 : $Base
598
+ %27 = tuple ()
599
+ return %27 : $()
600
+ }
601
+
602
+ // Replace an owned result with a guaranteed value on the merged path.
603
+ //
604
+ // The merged path has an unknown predecessor, where the merged value
605
+ // is produced by an apply.
606
+ //
607
+ // Clone the success path, introducing a copy on it.
608
+ //
609
+ // CHECK-LABEL: sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_mergecopy : $@convention(method) (@owned Base) -> () {
610
+ // CHECK: bb0(%0 : @owned $Base):
611
+ // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Base
612
+ // CHECK: checked_cast_br [exact] [[BORROW]] : $Base to Base, bb1, bb2
613
+ // CHECK: bb1([[ARG1:%.*]] : @guaranteed $Base):
614
+ // CHECK: [[CP1:%.*]] = copy_value [[ARG1]] : $Base
615
+ // CHECK: apply %2([[ARG1]]) : $@convention(method) (@guaranteed Base) -> ()
616
+ // CHECK: end_borrow [[BORROW]] : $Base
617
+ // CHECK: br bb4([[CP1]] : $Base)
618
+ // CHECK: bb2([[ARG2:%.*]] : @guaranteed $Base):
619
+ // CHECK: apply %{{.*}}([[ARG2]]) : $@convention(method) (@guaranteed Base) -> ()
620
+ // CHECK: [[RESULT:%.*]] = apply %{{.*}}() : $@convention(thin) () -> @owned Base
621
+ // CHECK: end_borrow [[BORROW]] : $Base
622
+ // CHECK: checked_cast_br [exact] %13 : $Base to Base, bb3, bb5
623
+ // CHECK: bb3([[ARG3:%.*]] : @owned $Base):
624
+ // CHECK: br bb4(%16 : $Base)
625
+ // CHECK: bb4([[ARG4:%.*]] : @owned $Base):
626
+ // CHECK: apply %{{.*}}([[ARG4]]) : $@convention(method) (@guaranteed Base) -> ()
627
+ // CHECK: destroy_value [[ARG4]] : $Base
628
+ // CHECK: br bb6
629
+ // CHECK: bb5([[ARG5:%.*]] : @owned $Base):
630
+ // CHECK: apply %{{.*}}([[ARG5]]) : $@convention(method) (@guaranteed Base) -> ()
631
+ // CHECK: destroy_value [[ARG5]] : $Base
632
+ // CHECK: br bb6
633
+ // CHECK: bb6:
634
+ // CHECK: destroy_value %0 : $Base
635
+ // CHECK: return
636
+ // CHECK-LABEL: } // end sil function 'redundant_checked_cast_br_rauw_guaranteed_to_owned_mergecopy'
637
+ sil [ossa] @redundant_checked_cast_br_rauw_guaranteed_to_owned_mergecopy : $@convention(method) (@owned Base) -> () {
638
+ bb0(%0 : @owned $Base):
639
+ %1 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
640
+
641
+ %2 = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
642
+ %f = function_ref @get_base : $@convention(thin) () -> @owned Base
643
+ %3 = begin_borrow %0 : $Base
644
+ checked_cast_br [exact] %3 : $Base to Base, bb1, bb2
645
+
646
+ bb1(%6 : @guaranteed $Base):
647
+ %7 = apply %2(%6) : $@convention(method) (@guaranteed Base) -> ()
648
+ %8 = copy_value %6 : $Base
649
+ br bb3(%8 : $Base)
650
+
651
+ bb2(%9 : @guaranteed $Base):
652
+ %10 = apply %1(%9) : $@convention(method) (@guaranteed Base) -> ()
653
+ %11 = apply %f() : $@convention(thin) () -> @owned Base
654
+ br bb3(%11 : $Base)
655
+
656
+ bb3(%12 : @owned $Base):
657
+ end_borrow %3 : $Base
658
+ checked_cast_br [exact] %12 : $Base to Base, bb6, bb7
659
+
660
+ bb6(%16 : @owned $Base):
661
+ %17 = apply %2(%16) : $@convention(method) (@guaranteed Base) -> ()
662
+ destroy_value %16 : $Base
663
+ br bb8
664
+
665
+ bb7(%20 : @owned $Base):
666
+ %21 = apply %1(%20) : $@convention(method) (@guaranteed Base) -> ()
667
+ destroy_value %20 : $Base
668
+ br bb8
669
+
670
+ bb8:
671
+ destroy_value %0 : $Base
672
+ %25 = tuple ()
673
+ return %25 : $()
674
+ }
675
+
676
+ //!!!TODO: test replacing a guaranteed value with an ownedvalue
677
+ // test borrowOverValue->borrowCopyOverScope path
678
+
679
+ //!!!TODO: test prepareUnowned paths
0 commit comments