|
25 | 25 | #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" |
26 | 26 | #include "swift/SILOptimizer/Analysis/CFG.h" |
27 | 27 | #include "swift/SILOptimizer/Analysis/ValueTracking.h" |
| 28 | +#include "swift/SILOptimizer/Utils/Existential.h" |
28 | 29 | #include "llvm/ADT/DenseMap.h" |
29 | 30 | #include "llvm/ADT/SmallPtrSet.h" |
30 | 31 | #include "llvm/ADT/SmallVector.h" |
@@ -600,186 +601,6 @@ SILCombiner::optimizeConcatenationOfStringLiterals(ApplyInst *AI) { |
600 | 601 | return tryToConcatenateStrings(AI, Builder); |
601 | 602 | } |
602 | 603 |
|
603 | | -/// Determine the pattern for global_addr. |
604 | | -/// %3 = global_addr @$P : $*SomeP |
605 | | -/// %4 = init_existential_addr %3 : $*SomeP, $SomeC |
606 | | -/// %5 = alloc_ref $SomeC |
607 | | -/// store %5 to %4 : $*SomeC |
608 | | -/// %8 = alloc_stack $SomeP |
609 | | -/// copy_addr %3 to [initialization] %8 : $*SomeP |
610 | | -/// %9 = open_existential_addr immutable_access %8 : $*SomeP to $*@opened SomeP |
611 | | -static SILValue findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI, |
612 | | - CopyAddrInst *CAI) { |
613 | | - assert(CAI->getSrc() == SILValue(GAI) && |
614 | | - "Broken Assumption! Global Addr is not the source of the passed in " |
615 | | - "copy_addr?!"); |
616 | | - |
617 | | - /// Check for a single InitExistential usage for GAI and |
618 | | - /// a simple dominance check: both InitExistential and CAI are in |
619 | | - /// the same basic block and only one InitExistential |
620 | | - /// occurs between GAI and CAI. |
621 | | - llvm::SmallPtrSet<SILInstruction *, 8> IEUses; |
622 | | - for (auto *Use : GAI->getUses()) { |
623 | | - if (auto *InitExistential = |
624 | | - dyn_cast<InitExistentialAddrInst>(Use->getUser())) { |
625 | | - IEUses.insert(InitExistential); |
626 | | - } |
627 | | - } |
628 | | - |
629 | | - /// No InitExistential found in the basic block. |
630 | | - if (IEUses.empty()) |
631 | | - return SILValue(); |
632 | | - |
633 | | - /// Walk backwards from CAI instruction till the begining of the basic block |
634 | | - /// looking for InitExistential. |
635 | | - SILValue SingleIE; |
636 | | - for (auto II = CAI->getIterator().getReverse(), IE = CAI->getParent()->rend(); |
637 | | - II != IE; ++II) { |
638 | | - if (!IEUses.count(&*II)) |
639 | | - continue; |
640 | | - if (SingleIE) |
641 | | - return SILValue(); |
642 | | - |
643 | | - SingleIE = cast<InitExistentialAddrInst>(&*II); |
644 | | - } |
645 | | - return SingleIE; |
646 | | -} |
647 | | - |
648 | | -/// Returns the address of an object with which the stack location \p ASI is |
649 | | -/// initialized. This is either a init_existential_addr or the destination of a |
650 | | -/// copy_addr. Returns a null value if the address does not dominate the |
651 | | -/// alloc_stack user \p ASIUser. |
652 | | -/// If the value is copied from another stack location, \p isCopied is set to |
653 | | -/// true. |
654 | | -static SILValue getAddressOfStackInit(AllocStackInst *ASI, |
655 | | - SILInstruction *ASIUser, |
656 | | - bool &isCopied) { |
657 | | - SILInstruction *SingleWrite = nullptr; |
658 | | - // Check that this alloc_stack is initialized only once. |
659 | | - for (auto Use : ASI->getUses()) { |
660 | | - auto *User = Use->getUser(); |
661 | | - |
662 | | - // Ignore instructions which don't write to the stack location. |
663 | | - // Also ignore ASIUser (only kicks in if ASIUser is the original apply). |
664 | | - if (isa<DeallocStackInst>(User) || isa<DebugValueAddrInst>(User) || |
665 | | - isa<DestroyAddrInst>(User) || isa<WitnessMethodInst>(User) || |
666 | | - isa<DeinitExistentialAddrInst>(User) || |
667 | | - isa<OpenExistentialAddrInst>(User) || |
668 | | - User == ASIUser) { |
669 | | - continue; |
670 | | - } |
671 | | - if (auto *CAI = dyn_cast<CopyAddrInst>(User)) { |
672 | | - if (CAI->getDest() == ASI) { |
673 | | - if (SingleWrite) |
674 | | - return SILValue(); |
675 | | - SingleWrite = CAI; |
676 | | - isCopied = true; |
677 | | - } |
678 | | - continue; |
679 | | - } |
680 | | - if (isa<InitExistentialAddrInst>(User)) { |
681 | | - if (SingleWrite) |
682 | | - return SILValue(); |
683 | | - SingleWrite = User; |
684 | | - continue; |
685 | | - } |
686 | | - if (isa<ApplyInst>(User) || isa<TryApplyInst>(User)) { |
687 | | - // Ignore function calls which do not write to the stack location. |
688 | | - auto Idx = Use->getOperandNumber() - ApplyInst::getArgumentOperandNumber(); |
689 | | - auto Conv = FullApplySite(User).getArgumentConvention(Idx); |
690 | | - if (Conv != SILArgumentConvention::Indirect_In && |
691 | | - Conv != SILArgumentConvention::Indirect_In_Guaranteed) |
692 | | - return SILValue(); |
693 | | - continue; |
694 | | - } |
695 | | - // Bail if there is any unknown (and potentially writing) instruction. |
696 | | - return SILValue(); |
697 | | - } |
698 | | - if (!SingleWrite) |
699 | | - return SILValue(); |
700 | | - |
701 | | - // A very simple dominance check. As ASI is an operand of ASIUser, |
702 | | - // SingleWrite dominates ASIUser if it is in the same block as ASI or ASIUser. |
703 | | - SILBasicBlock *BB = SingleWrite->getParent(); |
704 | | - if (BB != ASI->getParent() && BB != ASIUser->getParent()) |
705 | | - return SILValue(); |
706 | | - |
707 | | - if (auto *CAI = dyn_cast<CopyAddrInst>(SingleWrite)) { |
708 | | - // Try to derive the type from the copy_addr that was used to |
709 | | - // initialize the alloc_stack. |
710 | | - assert(isCopied && "isCopied not set for a copy_addr"); |
711 | | - SILValue CAISrc = CAI->getSrc(); |
712 | | - if (auto *ASI = dyn_cast<AllocStackInst>(CAISrc)) |
713 | | - return getAddressOfStackInit(ASI, CAI, isCopied); |
714 | | - // Check if the CAISrc is a global_addr. |
715 | | - if (auto *GAI = dyn_cast<GlobalAddrInst>(CAISrc)) { |
716 | | - return findInitExistentialFromGlobalAddr(GAI, CAI); |
717 | | - } |
718 | | - return CAISrc; |
719 | | - } |
720 | | - return cast<InitExistentialAddrInst>(SingleWrite); |
721 | | -} |
722 | | - |
723 | | -/// Find the init_existential, which could be used to determine a concrete |
724 | | -/// type of the \p Self. |
725 | | -/// If the value is copied from another stack location, \p isCopied is set to |
726 | | -/// true. |
727 | | -static SILInstruction *findInitExistential(FullApplySite AI, SILValue Self, |
728 | | - ArchetypeType *&OpenedArchetype, |
729 | | - SILValue &OpenedArchetypeDef, |
730 | | - bool &isCopied) { |
731 | | - isCopied = false; |
732 | | - if (auto *Instance = dyn_cast<AllocStackInst>(Self)) { |
733 | | - // In case the Self operand is an alloc_stack where a copy_addr copies the |
734 | | - // result of an open_existential_addr to this stack location. |
735 | | - if (SILValue Src = getAddressOfStackInit(Instance, AI.getInstruction(), |
736 | | - isCopied)) |
737 | | - Self = Src; |
738 | | - } |
739 | | - |
740 | | - if (auto *Open = dyn_cast<OpenExistentialAddrInst>(Self)) { |
741 | | - auto Op = Open->getOperand(); |
742 | | - auto *ASI = dyn_cast<AllocStackInst>(Op); |
743 | | - if (!ASI) |
744 | | - return nullptr; |
745 | | - |
746 | | - SILValue StackWrite = getAddressOfStackInit(ASI, Open, isCopied); |
747 | | - if (!StackWrite) |
748 | | - return nullptr; |
749 | | - |
750 | | - auto *IE = dyn_cast<InitExistentialAddrInst>(StackWrite); |
751 | | - if (!IE) |
752 | | - return nullptr; |
753 | | - |
754 | | - OpenedArchetype = Open->getType().castTo<ArchetypeType>(); |
755 | | - OpenedArchetypeDef = Open; |
756 | | - return IE; |
757 | | - } |
758 | | - |
759 | | - if (auto *Open = dyn_cast<OpenExistentialRefInst>(Self)) { |
760 | | - if (auto *IE = dyn_cast<InitExistentialRefInst>(Open->getOperand())) { |
761 | | - OpenedArchetype = Open->getType().castTo<ArchetypeType>(); |
762 | | - OpenedArchetypeDef = Open; |
763 | | - return IE; |
764 | | - } |
765 | | - return nullptr; |
766 | | - } |
767 | | - |
768 | | - if (auto *Open = dyn_cast<OpenExistentialMetatypeInst>(Self)) { |
769 | | - if (auto *IE = |
770 | | - dyn_cast<InitExistentialMetatypeInst>(Open->getOperand())) { |
771 | | - auto Ty = Open->getType().getASTType(); |
772 | | - while (auto Metatype = dyn_cast<MetatypeType>(Ty)) |
773 | | - Ty = Metatype.getInstanceType(); |
774 | | - OpenedArchetype = cast<ArchetypeType>(Ty); |
775 | | - OpenedArchetypeDef = Open; |
776 | | - return IE; |
777 | | - } |
778 | | - return nullptr; |
779 | | - } |
780 | | - return nullptr; |
781 | | -} |
782 | | - |
783 | 604 | /// Create a new apply instructions that uses the concrete type instead |
784 | 605 | /// of the existential type. |
785 | 606 | SILInstruction * |
|
0 commit comments