@@ -569,8 +569,14 @@ static bool canBeUsedAsCastDestination(SILValue value, CastInst *castInst,
569569
570570SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst (
571571 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
573577 //
578+ // %value = ...
579+ // ...
574580 // %box = alloc_existential_box $Error, $ConcreteError
575581 // %a = project_existential_box $ConcreteError in %b : $Error
576582 // store %value to %a : $*ConcreteError
@@ -581,33 +587,67 @@ SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst(
581587 // ConcreteError in %dest : $*ConcreteError
582588 //
583589 // to:
584- // ...
590+ //
585591 // 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
586598 // destroy_addr %err : $*Error
587599 // store %value to %dest $*ConcreteError
588600 //
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.
591628 SILValue val = getConcreteValueOfExistentialBoxAddr (uccai->getSrc (), uccai);
592629 while (auto *cvi = dyn_cast_or_null<CopyValueInst>(val))
593630 val = cvi->getOperand ();
594631 if (canBeUsedAsCastDestination (val, uccai, DA)) {
595632 // We need to copy the value at its insertion point.
596633 {
597- auto *valInsertPt = val->getDefiningInsertionPoint ();
598- if (!valInsertPt )
634+ auto *nextInsertPt = val->getNextInstruction ();
635+ if (!nextInsertPt )
599636 return nullptr ;
600- auto valInsertPtIter = valInsertPt->getIterator ();
601637 // If our value is defined by an instruction (not an argument), we want to
602638 // insert the copy after that. Otherwise, we have an argument and we want
603639 // 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);
608648 }
609649
610- // Then we insert the destroy value /store at the cast location.
650+ // Then we insert the destroy addr /store at the cast location.
611651 SILBuilderWithScope builder (uccai, Builder);
612652 SILLocation loc = uccai->getLoc ();
613653 builder.createDestroyAddr (loc, uccai->getSrc ());
@@ -816,17 +856,12 @@ visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
816856 // We need to insert the copy after the defining instruction of val or at
817857 // the top of the block if val is an argument.
818858 {
819- auto *valInsertPt = val->getDefiningInsertionPoint ();
820- if (!valInsertPt )
859+ auto *nextInsertPt = val->getNextInstruction ();
860+ if (!nextInsertPt )
821861 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);
830865 }
831866
832867 SILBuilderWithScope builder (CCABI, Builder);
0 commit comments