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