Skip to content

Commit c277c90

Browse files
author
Raj Barik
committed
Reorganizing the code to find init_existential; Move them to Existential.cpp/h in order for other passes such as ExistentialSpecializer to use it apart from SILCombiner
1 parent e8ee93b commit c277c90

File tree

4 files changed

+242
-180
lines changed

4 files changed

+242
-180
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===--- Existential.h - Existential related Analyses. -------*- C++ //-*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SILOPTIMIZER_UTILS_EXISTENTIAL_H
14+
#define SWIFT_SILOPTIMIZER_UTILS_EXISTENTIAL_H
15+
16+
#include "swift/SIL/SILInstruction.h"
17+
18+
namespace swift {
19+
20+
/// Find InitExistential from global_addr and copy_addr.
21+
SILValue findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI,
22+
CopyAddrInst *CAI);
23+
24+
/// Returns the address of an object with which the stack location \p ASI is
25+
/// initialized. This is either a init_existential_addr or the destination of a
26+
/// copy_addr. Returns a null value if the address does not dominate the
27+
/// alloc_stack user \p ASIUser.
28+
/// If the value is copied from another stack location, \p isCopied is set to
29+
/// true.
30+
SILValue getAddressOfStackInit(AllocStackInst *ASI, SILInstruction *ASIUser,
31+
bool &isCopied);
32+
33+
/// Find the init_existential, which could be used to determine a concrete
34+
/// type of the \p Self.
35+
/// If the value is copied from another stack location, \p isCopied is set to
36+
/// true.
37+
SILInstruction *findInitExistential(FullApplySite AI, SILValue Self,
38+
ArchetypeType *&OpenedArchetype,
39+
SILValue &OpenedArchetypeDef,
40+
bool &isCopied);
41+
} // end namespace swift
42+
43+
#endif

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 1 addition & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
2626
#include "swift/SILOptimizer/Analysis/CFG.h"
2727
#include "swift/SILOptimizer/Analysis/ValueTracking.h"
28+
#include "swift/SILOptimizer/Utils/Existential.h"
2829
#include "llvm/ADT/DenseMap.h"
2930
#include "llvm/ADT/SmallPtrSet.h"
3031
#include "llvm/ADT/SmallVector.h"
@@ -600,186 +601,6 @@ SILCombiner::optimizeConcatenationOfStringLiterals(ApplyInst *AI) {
600601
return tryToConcatenateStrings(AI, Builder);
601602
}
602603

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-
783604
/// Create a new apply instructions that uses the concrete type instead
784605
/// of the existential type.
785606
SILInstruction *

lib/SILOptimizer/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(UTILS_SOURCES
44
Utils/CheckedCastBrJumpThreading.cpp
55
Utils/ConstantFolding.cpp
66
Utils/Devirtualize.cpp
7+
Utils/Existential.cpp
78
Utils/GenericCloner.cpp
89
Utils/Generics.cpp
910
Utils/LoadStoreOptUtils.cpp

0 commit comments

Comments
 (0)