|
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