@@ -569,8 +569,14 @@ static bool canBeUsedAsCastDestination(SILValue value, CastInst *castInst,
569
569
570
570
SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst (
571
571
UnconditionalCheckedCastAddrInst *uccai) {
572
- // Optimize the unconditional_checked_cast_addr in this pattern:
572
+
573
+ // Optimize the unconditional_checked_cast_addr in the following non-ossa/ossa
574
+ // pattern:
575
+ //
576
+ // Non-OSSA Pattern
573
577
//
578
+ // %value = ...
579
+ // ...
574
580
// %box = alloc_existential_box $Error, $ConcreteError
575
581
// %a = project_existential_box $ConcreteError in %b : $Error
576
582
// store %value to %a : $*ConcreteError
@@ -581,33 +587,67 @@ SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst(
581
587
// ConcreteError in %dest : $*ConcreteError
582
588
//
583
589
// to:
584
- // ...
590
+ //
585
591
// retain_value %value : $ConcreteError
592
+ // ...
593
+ // %box = alloc_existential_box $Error, $ConcreteError
594
+ // %a = project_existential_box $ConcreteError in %b : $Error
595
+ // store %value to %a : $*ConcreteError
596
+ // %err = alloc_stack $Error
597
+ // store %box to %err : $*Error
586
598
// destroy_addr %err : $*Error
587
599
// store %value to %dest $*ConcreteError
588
600
//
589
- // This lets the alloc_existential_box become dead and it can be removed in
590
- // following optimizations.
601
+ // OSSA Pattern:
602
+ //
603
+ // %value = ...
604
+ // ...
605
+ // %box = alloc_existential_box $Error, $ConcreteError
606
+ // %a = project_existential_box $ConcreteError in %b : $Error
607
+ // store %value to [init] %a : $*ConcreteError
608
+ // %err = alloc_stack $Error
609
+ // store %box to [init] %err : $*Error
610
+ // %dest = alloc_stack $ConcreteError
611
+ // unconditional_checked_cast_addr Error in %err : $*Error to
612
+ // ConcreteError in %dest : $*ConcreteError
613
+ //
614
+ // to:
615
+ //
616
+ // %value_copy = copy_value %value
617
+ // ...
618
+ // %box = alloc_existential_box $Error, $ConcreteError
619
+ // %a = project_existential_box $ConcreteError in %b : $Error
620
+ // store %value to [init] %a : $*ConcreteError
621
+ // %err = alloc_stack $Error
622
+ // store %box to [init] %err : $*Error
623
+ // destroy_addr %err : $*Error
624
+ // store %value to %dest $*ConcreteError
625
+ //
626
+ // In both cases, this lets the alloc_existential_box become dead and it can
627
+ // be removed in other subsequent optimizations.
591
628
SILValue val = getConcreteValueOfExistentialBoxAddr (uccai->getSrc (), uccai);
592
629
while (auto *cvi = dyn_cast_or_null<CopyValueInst>(val))
593
630
val = cvi->getOperand ();
594
631
if (canBeUsedAsCastDestination (val, uccai, DA)) {
595
632
// We need to copy the value at its insertion point.
596
633
{
597
- auto *valInsertPt = val->getDefiningInsertionPoint ();
598
- if (!valInsertPt )
634
+ auto *nextInsertPt = val->getNextInstruction ();
635
+ if (!nextInsertPt )
599
636
return nullptr ;
600
- auto valInsertPtIter = valInsertPt->getIterator ();
601
637
// If our value is defined by an instruction (not an argument), we want to
602
638
// insert the copy after that. Otherwise, we have an argument and we want
603
639
// to insert the copy right at the beginning of the block.
604
- if (val->getDefiningInstruction ())
605
- valInsertPtIter = std::next (valInsertPtIter);
606
- SILBuilderWithScope builder (valInsertPtIter, Builder);
607
- val = builder.emitCopyValueOperation (valInsertPtIter->getLoc (), val);
640
+ SILBuilderWithScope builder (nextInsertPt, Builder);
641
+ // We use an autogenerated location to ensure that if next is a
642
+ // terminator, we do not trip an assertion around mismatched debug info.
643
+ //
644
+ // FIXME: We should find a better way of solving this than losing location
645
+ // info!
646
+ auto loc = RegularLocation::getAutoGeneratedLocation ();
647
+ val = builder.emitCopyValueOperation (loc, val);
608
648
}
609
649
610
- // Then we insert the destroy value /store at the cast location.
650
+ // Then we insert the destroy addr /store at the cast location.
611
651
SILBuilderWithScope builder (uccai, Builder);
612
652
SILLocation loc = uccai->getLoc ();
613
653
builder.createDestroyAddr (loc, uccai->getSrc ());
@@ -816,17 +856,12 @@ visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
816
856
// We need to insert the copy after the defining instruction of val or at
817
857
// the top of the block if val is an argument.
818
858
{
819
- auto *valInsertPt = val->getDefiningInsertionPoint ();
820
- if (!valInsertPt )
859
+ auto *nextInsertPt = val->getNextInstruction ();
860
+ if (!nextInsertPt )
821
861
return nullptr ;
822
- auto valInsertPtIter = valInsertPt->getIterator ();
823
- // If our value is defined by an instruction (not an argument), we want to
824
- // insert the copy after that. Otherwise, we have an argument and we want
825
- // to insert the copy right at the beginning of the block.
826
- if (val->getDefiningInstruction ())
827
- valInsertPtIter = std::next (valInsertPtIter);
828
- SILBuilderWithScope builder (valInsertPtIter, Builder);
829
- val = builder.emitCopyValueOperation (valInsertPtIter->getLoc (), val);
862
+ SILBuilderWithScope builder (nextInsertPt, Builder);
863
+ auto loc = RegularLocation::getAutoGeneratedLocation ();
864
+ val = builder.emitCopyValueOperation (loc, val);
830
865
}
831
866
832
867
SILBuilderWithScope builder (CCABI, Builder);
0 commit comments