Skip to content

Commit d2c6d7f

Browse files
committed
CheckedCastBrJumpThreading test cases.
1 parent 04aa16f commit d2c6d7f

File tree

1 file changed

+242
-30
lines changed

1 file changed

+242
-30
lines changed

test/SILOptimizer/simplify_cfg_checkcast.sil

Lines changed: 242 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
// RUN: %target-sil-opt -enable-sil-verify-all %s -jumpthread-simplify-cfg -enable-ossa-simplify-cfg -enable-ossa-rewriteterminator | %FileCheck %s
22
// 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
73

84
// FIXME: which of these tests actually require -jumpthread-simplify-cfg instead of -simplify-cfg?
95

6+
// FIXME_rauw: revisit these fixme's after the OwnershipRAUW utility is rewritten in terms of OwnershipLiveness.
7+
108
sil_stage canonical
119

1210
import Builtin
@@ -46,6 +44,8 @@ class Final : Derived {
4644
sil [ossa] @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
4745
sil [ossa] @_TFC3ccb4Base6middlefS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
4846

47+
sil @get_base : $@convention(thin) () -> @owned Base
48+
4949
// CHECK-LABEL: sil [ossa] @redundant_checked_cast_br
5050
sil [ossa] @redundant_checked_cast_br : $@convention(method) (@guaranteed Base) -> () {
5151
bb0(%0 : @guaranteed $Base):
@@ -62,7 +62,7 @@ bb1:
6262
bb2(%5 : @guaranteed $Base):
6363
// CHECK: [[SUCCESS]]
6464
%7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
65-
// XCHECK-NOT: checked_cast_br
65+
// CHECK-NOT: checked_cast_br
6666
checked_cast_br [exact] %0 : $Base to Base, bb3, bb5
6767
// CHECK: [[INNER:%.*]] = function_ref @_TFC3ccb4Base5innerfS0_FT_T_ : $@convention(method) (@guaranteed Base) -> ()
6868
// CHECK: apply [[INNER]]
@@ -109,9 +109,10 @@ bb1:
109109
return %3 : $()
110110

111111
// 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]])
115116
// CHECK: br bb1
116117
bb2(%5 : @owned $Base):
117118
%7 = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
@@ -206,8 +207,8 @@ bb2(%5 : @guaranteed $Base):
206207
// CHECK: [[SUCCESS]]([[SUCCESSARG:%.*]] : @guaranteed $Base)
207208
// CHECK: [[METHOD2:%.*]] = class_method %0 : $Base, #Base.inner : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
208209
%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]])
211212
// Check that checked_cast_br [exact] was replaced by a branch to the failure BB of the checked_cast_br.
212213
// This is because bb2 is reached via the success branch of the checked_cast_br [exact] from bb0.
213214
// It means that the exact dynamic type of %0 is $Base. Thus it cannot be $Derived.
@@ -252,8 +253,8 @@ bb1:
252253

253254
// CHECK: [[SUCCESS]]([[SUCCESSARG:%.*]] : @owned $Base)
254255
// 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]])
257258
// Check that checked_cast_br [exact] was replaced by a branch to the failure BB of the checked_cast_br.
258259
// This is because bb2 is reached via the success branch of the checked_cast_br [exact] from bb0.
259260
// It means that the exact dynamic type of %0 is $Base. Thus it cannot be $Derived.
@@ -324,16 +325,16 @@ bb5(%2a : @guaranteed $Base):
324325
br bb6
325326

326327
bb6:
328+
dealloc_ref %a : $Base
327329
dealloc_stack_ref %a : $Base
328330
%r = tuple()
329331
return %r : $()
330332
}
331333

332334
// Test a redundant checked_cast_br that has success, failure paths, and unknown paths.
333335
//
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)
337338
sil [ossa] @redundant_checked_cast_br_joined_success_fail_unknown : $@convention(method) (@guaranteed Base) -> () {
338339
bb0(%0 : @guaranteed $Base):
339340
%middle = class_method %0 : $Base, #Base.middle : (Base) -> () -> (), $@convention(method) (@guaranteed Base) -> ()
@@ -344,26 +345,22 @@ bb1(%successBB0 : @guaranteed $Base):
344345

345346
bb2:
346347
%successBB0call2 = apply %middle(%successBB0) : $@convention(method) (@guaranteed Base) -> ()
347-
%successBB0borrow2 = begin_borrow %successBB0 : $Base
348-
br bb8(%successBB0borrow2 : $Base)
348+
br bb8(%successBB0 : $Base)
349349

350350
bb3:
351351
%successBB0call3 = apply %middle(%successBB0) : $@convention(method) (@guaranteed Base) -> ()
352-
%successBB0borrow3 = begin_borrow %successBB0 : $Base
353-
br bb7(%successBB0borrow3 : $Base)
352+
br bb7(%successBB0 : $Base)
354353

355354
bb4(%failBB0 : @guaranteed $Base):
356355
cond_br undef, bb5, bb6
357356

358357
bb5:
359358
%failBB0call5 = apply %middle(%failBB0) : $@convention(method) (@guaranteed Base) -> ()
360-
%failBB0borrow5 = begin_borrow %failBB0 : $Base
361-
br bb7(%failBB0borrow5 : $Base)
359+
br bb7(%failBB0 : $Base)
362360

363361
bb6:
364362
%failBB0call6 = apply %middle(%failBB0) : $@convention(method) (@guaranteed Base) -> ()
365-
%failBB0borrow6 = begin_borrow %failBB0 : $Base
366-
br bb8(%failBB0borrow6 : $Base)
363+
br bb8(%failBB0 : $Base)
367364

368365
bb7(%unknown : @guaranteed $Base):
369366
%unknownCall = apply %middle(%unknown) : $@convention(method) (@guaranteed Base) -> ()
@@ -391,9 +388,11 @@ bb11:
391388
// Verify that checked-cast jump-threading kicks in and generates verifiable SIL.
392389
//
393390
// 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)
397396
sil shared [ossa] @$testCheckCastJumpThread : $@convention(thin) (@guaranteed Klass) -> @owned OtherKlass {
398397
bb0(%0 : @guaranteed $Klass):
399398
%1 = function_ref @get_klass : $@convention(thin) () -> @owned Klass
@@ -402,7 +401,7 @@ bb0(%0 : @guaranteed $Klass):
402401
%4 = copy_value %3 : $Klass
403402
checked_cast_br %3 : $Klass to OtherKlass, bb1, bb2
404403

405-
bb1(%5 : $OtherKlass):
404+
bb1(%5 : @owned $OtherKlass):
406405
destroy_value %5 : $OtherKlass
407406
%6 = integer_literal $Builtin.Int1, -1
408407
br bb3(%6 : $Builtin.Int1)
@@ -428,19 +427,20 @@ bb6:
428427
bb7(%16 : @owned $Klass):
429428
checked_cast_br %16 : $Klass to OtherKlass, bb9, bb8
430429

431-
bb8(%18 : $Klass):
430+
bb8(%18 : @owned $Klass):
432431
destroy_value %18 : $Klass
433432
br bb4
434433

435-
bb9(%20 : $OtherKlass):
434+
bb9(%20 : @owned $OtherKlass):
436435
return %20 : $OtherKlass
437436

438437
bb10(%22 : $Builtin.Int64):
439438
%23 = apply %1() : $@convention(thin) () -> @owned Klass
440439
%24 = copy_value %23 : $Klass
441440
checked_cast_br %23 : $Klass to OtherKlass, bb11, bb12
442441

443-
bb11(%25 : $OtherKlass):
442+
bb11(%25 : @owned $OtherKlass):
443+
destroy_value %25 : $OtherKlass
444444
%26 = integer_literal $Builtin.Int1, -1
445445
br bb13(%26 : $Builtin.Int1)
446446

@@ -465,3 +465,215 @@ bb16:
465465
bb17:
466466
br bb10(undef : $Builtin.Int64)
467467
}
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

Comments
 (0)